From d9e81f9bb561c649b563b80eca7ff64a8573f2d6 Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" <> Date: Mon, 29 Jul 2024 02:48:51 +0000 Subject: [PATCH] Deploy mate-desktop/caja to github.com/mate-desktop/caja.git:gh-pages --- 2024-07-29-023715-6438-1/index.html | 233 + 2024-07-29-023715-6438-1/report-16cfde.html | 3086 +++++ 2024-07-29-023715-6438-1/report-1e9f80.html | 2899 +++++ 2024-07-29-023715-6438-1/report-29d5c0.html | 4831 +++++++ 2024-07-29-023715-6438-1/report-2c7ed7.html | 1459 +++ 2024-07-29-023715-6438-1/report-337a86.html | 761 ++ 2024-07-29-023715-6438-1/report-3574f0.html | 1435 ++ 2024-07-29-023715-6438-1/report-39a95b.html | 7496 +++++++++++ 2024-07-29-023715-6438-1/report-4215de.html | 2583 ++++ 2024-07-29-023715-6438-1/report-493860.html | 12231 ++++++++++++++++++ 2024-07-29-023715-6438-1/report-4a2949.html | 933 ++ 2024-07-29-023715-6438-1/report-50b9d2.html | 2583 ++++ 2024-07-29-023715-6438-1/report-535ee1.html | 10862 ++++++++++++++++ 2024-07-29-023715-6438-1/report-554110.html | 9582 ++++++++++++++ 2024-07-29-023715-6438-1/report-5dfaea.html | 1264 ++ 2024-07-29-023715-6438-1/report-5f75fc.html | 6536 ++++++++++ 2024-07-29-023715-6438-1/report-79066c.html | 3222 +++++ 2024-07-29-023715-6438-1/report-7e131c.html | 6536 ++++++++++ 2024-07-29-023715-6438-1/report-891289.html | 1542 +++ 2024-07-29-023715-6438-1/report-895168.html | 980 ++ 2024-07-29-023715-6438-1/report-89a2be.html | 9582 ++++++++++++++ 2024-07-29-023715-6438-1/report-89fe06.html | 3283 +++++ 2024-07-29-023715-6438-1/report-8ec019.html | 1994 +++ 2024-07-29-023715-6438-1/report-9708c1.html | 4916 +++++++ 2024-07-29-023715-6438-1/report-9f0261.html | 9689 ++++++++++++++ 2024-07-29-023715-6438-1/report-a0fbb3.html | 909 ++ 2024-07-29-023715-6438-1/report-a6010e.html | 980 ++ 2024-07-29-023715-6438-1/report-a7c48d.html | 933 ++ 2024-07-29-023715-6438-1/report-b8f564.html | 2089 +++ 2024-07-29-023715-6438-1/report-be2b10.html | 7490 +++++++++++ 2024-07-29-023715-6438-1/report-bedbd9.html | 9582 ++++++++++++++ 2024-07-29-023715-6438-1/report-c08216.html | 1479 +++ 2024-07-29-023715-6438-1/report-c2fd27.html | 1723 +++ 2024-07-29-023715-6438-1/report-c35402.html | 9582 ++++++++++++++ 2024-07-29-023715-6438-1/report-ca1b2c.html | 3064 +++++ 2024-07-29-023715-6438-1/report-cb7be2.html | 2910 +++++ 2024-07-29-023715-6438-1/report-cf3974.html | 2089 +++ 2024-07-29-023715-6438-1/report-d3c816.html | 7490 +++++++++++ 2024-07-29-023715-6438-1/report-d4a7f3.html | 3086 +++++ 2024-07-29-023715-6438-1/report-efae23.html | 3086 +++++ 2024-07-29-023715-6438-1/report-f8875c.html | 902 ++ 2024-07-29-023715-6438-1/report-f8a52c.html | 2681 ++++ 2024-07-29-023715-6438-1/report-f9f9ca.html | 3086 +++++ 2024-07-29-023715-6438-1/report-fb6164.html | 1511 +++ 2024-07-29-023715-6438-1/report-fd0643.html | 2132 +++ 2024-07-29-023715-6438-1/report-fd4851.html | 6536 ++++++++++ 2024-07-29-023715-6438-1/scanview.css | 62 + 2024-07-29-023715-6438-1/sorttable.js | 492 + 48 files changed, 184412 insertions(+) create mode 100644 2024-07-29-023715-6438-1/index.html create mode 100644 2024-07-29-023715-6438-1/report-16cfde.html create mode 100644 2024-07-29-023715-6438-1/report-1e9f80.html create mode 100644 2024-07-29-023715-6438-1/report-29d5c0.html create mode 100644 2024-07-29-023715-6438-1/report-2c7ed7.html create mode 100644 2024-07-29-023715-6438-1/report-337a86.html create mode 100644 2024-07-29-023715-6438-1/report-3574f0.html create mode 100644 2024-07-29-023715-6438-1/report-39a95b.html create mode 100644 2024-07-29-023715-6438-1/report-4215de.html create mode 100644 2024-07-29-023715-6438-1/report-493860.html create mode 100644 2024-07-29-023715-6438-1/report-4a2949.html create mode 100644 2024-07-29-023715-6438-1/report-50b9d2.html create mode 100644 2024-07-29-023715-6438-1/report-535ee1.html create mode 100644 2024-07-29-023715-6438-1/report-554110.html create mode 100644 2024-07-29-023715-6438-1/report-5dfaea.html create mode 100644 2024-07-29-023715-6438-1/report-5f75fc.html create mode 100644 2024-07-29-023715-6438-1/report-79066c.html create mode 100644 2024-07-29-023715-6438-1/report-7e131c.html create mode 100644 2024-07-29-023715-6438-1/report-891289.html create mode 100644 2024-07-29-023715-6438-1/report-895168.html create mode 100644 2024-07-29-023715-6438-1/report-89a2be.html create mode 100644 2024-07-29-023715-6438-1/report-89fe06.html create mode 100644 2024-07-29-023715-6438-1/report-8ec019.html create mode 100644 2024-07-29-023715-6438-1/report-9708c1.html create mode 100644 2024-07-29-023715-6438-1/report-9f0261.html create mode 100644 2024-07-29-023715-6438-1/report-a0fbb3.html create mode 100644 2024-07-29-023715-6438-1/report-a6010e.html create mode 100644 2024-07-29-023715-6438-1/report-a7c48d.html create mode 100644 2024-07-29-023715-6438-1/report-b8f564.html create mode 100644 2024-07-29-023715-6438-1/report-be2b10.html create mode 100644 2024-07-29-023715-6438-1/report-bedbd9.html create mode 100644 2024-07-29-023715-6438-1/report-c08216.html create mode 100644 2024-07-29-023715-6438-1/report-c2fd27.html create mode 100644 2024-07-29-023715-6438-1/report-c35402.html create mode 100644 2024-07-29-023715-6438-1/report-ca1b2c.html create mode 100644 2024-07-29-023715-6438-1/report-cb7be2.html create mode 100644 2024-07-29-023715-6438-1/report-cf3974.html create mode 100644 2024-07-29-023715-6438-1/report-d3c816.html create mode 100644 2024-07-29-023715-6438-1/report-d4a7f3.html create mode 100644 2024-07-29-023715-6438-1/report-efae23.html create mode 100644 2024-07-29-023715-6438-1/report-f8875c.html create mode 100644 2024-07-29-023715-6438-1/report-f8a52c.html create mode 100644 2024-07-29-023715-6438-1/report-f9f9ca.html create mode 100644 2024-07-29-023715-6438-1/report-fb6164.html create mode 100644 2024-07-29-023715-6438-1/report-fd0643.html create mode 100644 2024-07-29-023715-6438-1/report-fd4851.html create mode 100644 2024-07-29-023715-6438-1/scanview.css create mode 100644 2024-07-29-023715-6438-1/sorttable.js diff --git a/2024-07-29-023715-6438-1/index.html b/2024-07-29-023715-6438-1/index.html new file mode 100644 index 000000000..9a387447e --- /dev/null +++ b/2024-07-29-023715-6438-1/index.html @@ -0,0 +1,233 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@fb1e43585515
Working Directory:/rootdir
Command Line:make -j 3
Clang Version:clang version 18.1.6 (Fedora 18.1.6-3.fc40) +
Date:Mon Jul 29 02:37:15 2024
+

Bug Summary

+ + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs45
Logic error
Cast from non-struct type to struct type2
Cast region with wrong size1
Dereference of null pointer8
Out-of-bound access5
Unused code
Dead assignment21
Dead increment1
Unreachable code7
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typemate-submodules/libegg/eggsmclient-xsmp.carray_prop11991View Report
Logic errorCast from non-struct type to struct typemate-submodules/libegg/eggsmclient-xsmp.cptrarray_prop12321View Report
Logic errorCast region with wrong sizelibcaja-private/caja-file-operations.cinit_common9612View Report
Unused codeDead assignmenteel/eel-labeled-image.clabeled_image_update_alignments10561View Report
Unused codeDead assignmentlibcaja-private/caja-debug-log.ccaja_debug_logv2481View Report
Unused codeDead assignmentsrc/caja-query-editor.ctype_add_rows_from_query10471View Report
Unused codeDead assignmentsrc/file-manager/fm-directory-view.creset_open_with_menu47471View Report
Unused codeDead assignmentsrc/caja-query-editor.cmodtime_row_add_to_query11581View Report
Unused codeDead assignmentlibcaja-private/caja-file.ccompare_by_emblems30891View Report
Unused codeDead assignmentsrc/caja-notebook.ccaja_notebook_add_tab3951View Report
Unused codeDead assignmentsrc/file-manager/fm-properties-window.ccreate_simple_permissions44901View Report
Unused codeDead assignmentsrc/file-manager/fm-properties-window.ccreate_permission_checkboxes45511View Report
Unused codeDead assignmentlibcaja-private/caja-mime-actions.capplication_unhandled_uri16151View Report
Unused codeDead assignmentlibcaja-private/caja-tree-view-drag-dest.creceive_uris6821View Report
Unused codeDead assignmentlibcaja-private/caja-file-operations.cverify_destination29141View Report
Unused codeDead assignmentlibcaja-private/caja-file.cget_time27921View Report
Unused codeDead assignmentlibcaja-private/caja-file.ccaja_file_get_start_stop_type11921View Report
Unused codeDead assignmentsrc/caja-application.ccaja_application_startup22461View Report
Unused codeDead assignmenteel/eel-labeled-image.clabeled_image_update_alignments11051View Report
Unused codeDead assignmenteel/eel-labeled-image.clabeled_image_update_alignments10571View Report
Unused codeDead assignmentlibcaja-private/caja-icon-dnd.ccaja_icon_container_selection_items_local6271View Report
Unused codeDead assignmenteel/eel-labeled-image.clabeled_image_update_alignments11061View Report
Unused codeDead assignmentsrc/caja-navigation-window.ccaja_navigation_window_button_press_event6051View Report
Unused codeDead assignmentsrc/file-manager/fm-properties-window.cdirectory_contents_value_field_update22371View Report
Unused codeDead incrementlibcaja-private/caja-icon-container.clay_down_icons_horizontal15121View Report
Logic errorDereference of null pointersrc/caja-pathbar.ccaja_path_bar_size_allocate84417View Report
Logic errorDereference of null pointereel/eel-canvas.cput_item_after60534View Report
Logic errorDereference of null pointerlibcaja-private/caja-extensions.ccaja_extension_set_state2345View Report
Logic errorDereference of null pointersrc/caja-window-manage-views.cdisplay_view_selection_failure221947View Report
Logic errorDereference of null pointerlibcaja-extension/tmp-introspect70zjnr57/Caja-2.0.cmain79912View Report
Logic errorDereference of null pointereel/eel-canvas.cput_item_after58065View Report
Logic errorDereference of null pointerlibcaja-private/caja-extensions.ccaja_extension_set_state2375View Report
Logic errorDereference of null pointersrc/caja-pathbar.ccaja_path_bar_scroll_down109122View Report
Logic errorOut-of-bound accesseel/eel-gdk-extensions.ceel_gradient_strip_trailing_direction_if_any10621View Report
Logic errorOut-of-bound accesslibcaja-private/caja-file.ccaja_file_get_extension_as_string338750View Report
Logic errorOut-of-bound accesseel/eel-vfs-extensions.ceel_filename_strip_extension13621View Report
Logic errorOut-of-bound accesseel/eel-string.ceel_strdup_vprintf_with_custom58528View Report
Logic errorOut-of-bound accesseel/eel-vfs-extensions.ceel_filename_strip_extension12719View Report
Unused codeUnreachable codetest/test-eel-labeled-image.cmain751View Report
Unused codeUnreachable codetest/test-eel-image-table.cimage_table_size_allocate1881View Report
Unused codeUnreachable codelibcaja-private/caja-file.ccaja_file_get_boolean_metadata39261View Report
Unused codeUnreachable codetest/test-eel-image-table.cimage_table_size_allocate1931View Report
Unused codeUnreachable codelibcaja-private/caja-vfs-file.cvfs_file_get_date4001View Report
Unused codeUnreachable codelibcaja-private/caja-file-operations.ccaja_file_set_permissions_recursive58301View Report
Unused codeUnreachable codelibcaja-extension/tmp-introspect70zjnr57/Caja-2.0.cvalue_to_string2391View Report
+ + diff --git a/2024-07-29-023715-6438-1/report-16cfde.html b/2024-07-29-023715-6438-1/report-16cfde.html new file mode 100644 index 000000000..72510d3f5 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-16cfde.html @@ -0,0 +1,3086 @@ + + + +eel-labeled-image.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-labeled-image.c
Warning:line 1056, column 13
Value stored to 'x_alignment' 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 eel-labeled-image.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-labeled-image.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* eel-labeled-image.c - A labeled image.
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Ramiro Estrugo <ramiro@eazel.com>
23*/
24
25#include <config.h>
26#include "eel-labeled-image.h"
27
28#include "eel-art-extensions.h"
29#include "eel-art-gtk-extensions.h"
30#include "eel-gtk-container.h"
31#include "eel-gtk-extensions.h"
32#include "eel-accessibility.h"
33#include <gtk/gtk.h>
34#include <gtk/gtk-a11y.h>
35#include <gdk/gdkkeysyms.h>
36#include <atk/atkimage.h>
37
38#define DEFAULT_SPACING0 0
39#define DEFAULT_X_PADDING0 0
40#define DEFAULT_Y_PADDING0 0
41#define DEFAULT_X_ALIGNMENT0.5 0.5
42#define DEFAULT_Y_ALIGNMENT0.5 0.5
43
44/* Signals */
45enum
46{
47 ACTIVATE,
48 LAST_SIGNAL
49};
50
51/* Arguments */
52enum
53{
54 PROP_0,
55 PROP_FILL,
56 PROP_LABEL,
57 PROP_LABEL_POSITION,
58 PROP_PIXBUF,
59 PROP_SHOW_IMAGE,
60 PROP_SHOW_LABEL,
61 PROP_SPACING,
62 PROP_X_ALIGNMENT,
63 PROP_X_PADDING,
64 PROP_Y_ALIGNMENT,
65 PROP_Y_PADDING
66};
67
68/* Detail member struct */
69struct EelLabeledImagePrivate
70{
71 GtkWidget *image;
72 GtkWidget *label;
73 GtkPositionType label_position;
74 gboolean show_label;
75 gboolean show_image;
76 guint spacing;
77 float x_alignment;
78 float y_alignment;
79 int x_padding;
80 int y_padding;
81 int fixed_image_height;
82 gboolean fill;
83};
84
85/* derived types so we can add our accessibility interfaces */
86static GType eel_labeled_image_button_get_type (void);
87static GType eel_labeled_image_check_button_get_type (void);
88static GType eel_labeled_image_radio_button_get_type (void);
89static GType eel_labeled_image_toggle_button_get_type (void);
90
91/* GtkWidgetClass methods */
92static GType eel_labeled_image_accessible_get_type (void);
93
94/* Private EelLabeledImage methods */
95static EelDimensions labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image);
96static EelDimensions labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image);
97static void labeled_image_ensure_label (EelLabeledImage *labeled_image);
98static void labeled_image_ensure_image (EelLabeledImage *labeled_image);
99static EelIRect labeled_image_get_content_bounds (const EelLabeledImage *labeled_image);
100static EelDimensions labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image);
101static void labeled_image_update_alignments (EelLabeledImage *labeled_image);
102static gboolean labeled_image_show_label (const EelLabeledImage *labeled_image);
103static gboolean labeled_image_show_image (const EelLabeledImage *labeled_image);
104
105static guint labeled_image_signals[LAST_SIGNAL] = { 0 };
106
107G_DEFINE_TYPE_WITH_PRIVATE (EelLabeledImage, eel_labeled_image, GTK_TYPE_CONTAINER)static void eel_labeled_image_init (EelLabeledImage *self); static
void eel_labeled_image_class_init (EelLabeledImageClass *klass
); static GType eel_labeled_image_get_type_once (void); static
gpointer eel_labeled_image_parent_class = ((void*)0); static
gint EelLabeledImage_private_offset; static void eel_labeled_image_class_intern_init
(gpointer klass) { eel_labeled_image_parent_class = g_type_class_peek_parent
(klass); if (EelLabeledImage_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelLabeledImage_private_offset); eel_labeled_image_class_init
((EelLabeledImageClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_labeled_image_get_instance_private
(EelLabeledImage *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EelLabeledImage_private_offset)))); } GType eel_labeled_image_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType eel_labeled_image_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_get_type ()), g_intern_static_string ("EelLabeledImage"
), sizeof (EelLabeledImageClass), (GClassInitFunc)(void (*)(void
)) eel_labeled_image_class_intern_init, sizeof (EelLabeledImage
), (GInstanceInitFunc)(void (*)(void)) eel_labeled_image_init
, (GTypeFlags) 0); { {{ EelLabeledImage_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (EelLabeledImagePrivate)); };} } return
g_define_type_id; }
108
109static void
110eel_labeled_image_init (EelLabeledImage *labeled_image)
111{
112 gtk_widget_set_has_window (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), FALSE(0));
113
114 labeled_image->details = eel_labeled_image_get_instance_private (labeled_image);
115 labeled_image->details->show_label = TRUE(!(0));
116 labeled_image->details->show_image = TRUE(!(0));
117 labeled_image->details->label_position = GTK_POS_BOTTOM;
118 labeled_image->details->spacing = DEFAULT_SPACING0;
119 labeled_image->details->x_padding = DEFAULT_X_PADDING0;
120 labeled_image->details->y_padding = DEFAULT_Y_PADDING0;
121 labeled_image->details->x_alignment = DEFAULT_X_ALIGNMENT0.5;
122 labeled_image->details->y_alignment = DEFAULT_Y_ALIGNMENT0.5;
123 labeled_image->details->fixed_image_height = 0;
124
125 eel_labeled_image_set_fill (labeled_image, FALSE(0));
126}
127
128static void
129eel_labeled_image_destroy (GtkWidget *object)
130{
131 EelLabeledImage *labeled_image;
132
133 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
134
135 if (labeled_image->details->image != NULL((void*)0))
136 {
137 gtk_widget_destroy (labeled_image->details->image);
138 }
139
140 if (labeled_image->details->label != NULL((void*)0))
141 {
142 gtk_widget_destroy (labeled_image->details->label);
143 }
144
145 GTK_WIDGET_CLASS (eel_labeled_image_parent_class)((((GtkWidgetClass*) (void *) ((eel_labeled_image_parent_class
)))))
->destroy (object);
146}
147
148/* GObjectClass methods */
149static void
150eel_labeled_image_set_property (GObject *object,
151 guint property_id,
152 const GValue *value,
153 GParamSpec *pspec)
154{
155 EelLabeledImage *labeled_image;
156
157 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_73
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_73
= 1; else _g_boolean_var_73 = 0; _g_boolean_var_73; }), 1)) ;
else g_assertion_message_expr ("Eel", "eel-labeled-image.c",
157, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
158
159 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
160
161 switch (property_id)
162 {
163 case PROP_PIXBUF:
164 eel_labeled_image_set_pixbuf (labeled_image,
165 g_value_get_object (value));
166 break;
167
168 case PROP_LABEL:
169 eel_labeled_image_set_text (labeled_image, g_value_get_string (value));
170 break;
171
172 case PROP_LABEL_POSITION:
173 eel_labeled_image_set_label_position (labeled_image,
174 g_value_get_enum (value));
175 break;
176
177 case PROP_SHOW_LABEL:
178 eel_labeled_image_set_show_label (labeled_image,
179 g_value_get_boolean (value));
180 break;
181
182 case PROP_SHOW_IMAGE:
183 eel_labeled_image_set_show_image (labeled_image,
184 g_value_get_boolean (value));
185 break;
186
187 case PROP_SPACING:
188 eel_labeled_image_set_spacing (labeled_image,
189 g_value_get_uint (value));
190 break;
191
192 case PROP_X_PADDING:
193 eel_labeled_image_set_x_padding (labeled_image,
194 g_value_get_int (value));
195 break;
196
197 case PROP_Y_PADDING:
198 eel_labeled_image_set_y_padding (labeled_image,
199 g_value_get_int (value));
200 break;
201
202 case PROP_X_ALIGNMENT:
203 eel_labeled_image_set_x_alignment (labeled_image,
204 g_value_get_float (value));
205 break;
206
207 case PROP_Y_ALIGNMENT:
208 eel_labeled_image_set_y_alignment (labeled_image,
209 g_value_get_float (value));
210 break;
211
212 case PROP_FILL:
213 eel_labeled_image_set_fill (labeled_image,
214 g_value_get_boolean (value));
215 break;
216 default:
217 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 217
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
218 }
219}
220
221static void
222eel_labeled_image_get_property (GObject *object,
223 guint property_id,
224 GValue *value,
225 GParamSpec *pspec)
226{
227 EelLabeledImage *labeled_image;
228
229 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_74
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_74
= 1; else _g_boolean_var_74 = 0; _g_boolean_var_74; }), 1)) ;
else g_assertion_message_expr ("Eel", "eel-labeled-image.c",
229, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
230
231 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
232
233 switch (property_id)
234 {
235 case PROP_LABEL:
236 if (labeled_image->details->label == NULL((void*)0))
237 {
238 g_value_set_string (value, NULL((void*)0));
239 }
240 else
241 {
242 g_value_set_string (value,
243 gtk_label_get_text (GTK_LABEL (((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
244 labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
));
245 }
246 break;
247
248 case PROP_LABEL_POSITION:
249 g_value_set_enum (value, eel_labeled_image_get_label_position (labeled_image));
250 break;
251
252 case PROP_SHOW_LABEL:
253 g_value_set_boolean (value, eel_labeled_image_get_show_label (labeled_image));
254 break;
255
256 case PROP_SHOW_IMAGE:
257 g_value_set_boolean (value, eel_labeled_image_get_show_image (labeled_image));
258 break;
259
260 case PROP_SPACING:
261 g_value_set_uint (value, eel_labeled_image_get_spacing (labeled_image));
262 break;
263
264 case PROP_X_PADDING:
265 g_value_set_int (value, eel_labeled_image_get_x_padding (labeled_image));
266 break;
267
268 case PROP_Y_PADDING:
269 g_value_set_int (value, eel_labeled_image_get_y_padding (labeled_image));
270 break;
271
272 case PROP_X_ALIGNMENT:
273 g_value_set_float (value, eel_labeled_image_get_x_alignment (labeled_image));
274 break;
275
276 case PROP_Y_ALIGNMENT:
277 g_value_set_float (value, eel_labeled_image_get_y_alignment (labeled_image));
278 break;
279
280 case PROP_FILL:
281 g_value_set_boolean (value, eel_labeled_image_get_fill (labeled_image));
282 break;
283
284 default:
285 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 285
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
286 }
287}
288
289/* GtkWidgetClass methods */
290static void
291eel_labeled_image_size_request (GtkWidget *widget,
292 GtkRequisition *requisition)
293{
294 EelLabeledImage *labeled_image;
295 EelDimensions content_dimensions;
296
297 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_75
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c",
297, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
298 g_assert (requisition != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_76
; if (requisition != ((void*)0)) _g_boolean_var_76 = 1; else _g_boolean_var_76
= 0; _g_boolean_var_76; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 298, ((const char*) (__func__
)), "requisition != NULL"); } while (0)
;
299
300 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
301
302 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
303
304 requisition->width =
305 MAX (1, content_dimensions.width)(((1) > (content_dimensions.width)) ? (1) : (content_dimensions
.width))
+
306 2 * labeled_image->details->x_padding;
307
308 requisition->height =
309 MAX (1, content_dimensions.height)(((1) > (content_dimensions.height)) ? (1) : (content_dimensions
.height))
+
310 2 * labeled_image->details->y_padding;
311}
312
313static void
314eel_labeled_image_get_preferred_width (GtkWidget *widget,
315 gint *minimum_width,
316 gint *natural_width)
317{
318 GtkRequisition req;
319 eel_labeled_image_size_request (widget, &req);
320 *minimum_width = *natural_width = req.width;
321}
322
323static void
324eel_labeled_image_get_preferred_height (GtkWidget *widget,
325 gint *minimum_height,
326 gint *natural_height)
327{
328 GtkRequisition req;
329 eel_labeled_image_size_request (widget, &req);
330 *minimum_height = *natural_height = req.height;
331}
332
333static void
334eel_labeled_image_size_allocate (GtkWidget *widget,
335 GtkAllocation *allocation)
336{
337 EelLabeledImage *labeled_image;
338 EelIRect image_bounds;
339 EelIRect label_bounds;
340
341 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_77
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_77
= 1; else _g_boolean_var_77 = 0; _g_boolean_var_77; }), 1)) ;
else g_assertion_message_expr ("Eel", "eel-labeled-image.c",
341, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
342 g_assert (allocation != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_78
; if (allocation != ((void*)0)) _g_boolean_var_78 = 1; else _g_boolean_var_78
= 0; _g_boolean_var_78; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 342, ((const char*) (__func__
)), "allocation != NULL"); } while (0)
;
343
344 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
345
346 gtk_widget_set_allocation (widget, allocation);
347
348 label_bounds = eel_labeled_image_get_label_bounds (labeled_image);
349 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
350 labeled_image->details->label,
351 label_bounds);
352
353 image_bounds = eel_labeled_image_get_image_bounds (labeled_image);
354 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
355 labeled_image->details->image,
356 image_bounds);
357}
358
359static int
360eel_labeled_image_draw (GtkWidget *widget,
361 cairo_t *cr)
362{
363 EelLabeledImage *labeled_image;
364 EelIRect label_bounds;
365 GtkStyleContext *context;
366
367 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_79
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_79
= 1; else _g_boolean_var_79 = 0; _g_boolean_var_79; }), 1)) ;
else g_assertion_message_expr ("Eel", "eel-labeled-image.c",
367, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
368 g_assert (gtk_widget_get_realized (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_80
; if (gtk_widget_get_realized (widget)) _g_boolean_var_80 = 1
; else _g_boolean_var_80 = 0; _g_boolean_var_80; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-labeled-image.c", 368,
((const char*) (__func__)), "gtk_widget_get_realized (widget)"
); } while (0)
;
369
370 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
371
372 context = gtk_widget_get_style_context (widget);
373 gtk_style_context_save (context);
374
375 if (gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_SELECTED ||
376 gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_ACTIVE)
377 {
378 label_bounds = eel_labeled_image_get_label_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
379
380 gtk_widget_get_state_flags (widget);
381 gtk_render_background (context,
382 cr,
383 label_bounds.x0, label_bounds.y0,
384 label_bounds.x1 - label_bounds.x0,
385 label_bounds.y1 - label_bounds.y0);
386
387 gtk_render_frame (context,
388 cr,
389 label_bounds.x0, label_bounds.y0,
390 label_bounds.x1 - label_bounds.x0,
391 label_bounds.y1 - label_bounds.y0);
392 }
393
394 if (labeled_image_show_label (labeled_image))
395 {
396 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
397 labeled_image->details->label,
398 cr);
399 }
400
401 if (labeled_image_show_image (labeled_image))
402 {
403 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
404 labeled_image->details->image,
405 cr);
406 }
407
408 if (gtk_widget_has_focus (widget))
409 {
410 label_bounds = eel_labeled_image_get_image_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
411 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_NORMAL, TRUE(!(0)));
412 gtk_render_focus (context,
413 cr,
414 label_bounds.x0, label_bounds.y0,
415 label_bounds.x1 - label_bounds.x0,
416 label_bounds.y1 - label_bounds.y0);
417 }
418
419 gtk_style_context_restore (context);
420
421 return FALSE(0);
422}
423
424static void
425eel_labeled_image_map (GtkWidget *widget)
426{
427 EelLabeledImage *labeled_image;
428
429 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_81
= 1; else _g_boolean_var_81 = 0; _g_boolean_var_81; }), 1)) ;
else g_assertion_message_expr ("Eel", "eel-labeled-image.c",
429, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
430
431 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
432
433 gtk_widget_set_mapped (widget, TRUE(!(0)));
434
435 if (labeled_image_show_label (labeled_image))
436 {
437 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
438 }
439
440 if (labeled_image_show_image (labeled_image))
441 {
442 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
443 }
444}
445
446static void
447eel_labeled_image_unmap (GtkWidget *widget)
448{
449 EelLabeledImage *labeled_image;
450
451 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_82
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c",
451, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
452
453 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
454
455 gtk_widget_set_mapped (widget, FALSE(0));
456
457 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
458 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
459}
460
461/* GtkContainerClass methods */
462static void
463eel_labeled_image_add (GtkContainer *container,
464 GtkWidget *child)
465{
466 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_83
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c",
466, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
467
468 eel_gtk_container_child_add (container, child);
469}
470
471static void
472eel_labeled_image_remove (GtkContainer *container,
473 GtkWidget *child)
474{
475 EelLabeledImage *labeled_image;
476
477 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c",
477, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
478
479 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));;
480
481 g_assert (child == labeled_image->details->image || child == labeled_image->details->label)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_85
; if (child == labeled_image->details->image || child ==
labeled_image->details->label) _g_boolean_var_85 = 1; else
_g_boolean_var_85 = 0; _g_boolean_var_85; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 481, ((const char*) (__func__
)), "child == labeled_image->details->image || child == labeled_image->details->label"
); } while (0)
;
482
483 eel_gtk_container_child_remove (container, child);
484
485 if (labeled_image->details->image == child)
486 {
487 labeled_image->details->image = NULL((void*)0);
488 }
489
490 if (labeled_image->details->label == child)
491 {
492 labeled_image->details->label = NULL((void*)0);
493 }
494}
495
496static void
497eel_labeled_image_forall (GtkContainer *container,
498 gboolean include_internals,
499 GtkCallback callback,
500 gpointer callback_data)
501{
502 EelLabeledImage *labeled_image;
503
504 g_assert (EEL_IS_LABELED_IMAGE (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 504, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (container)"
); } while (0)
;
505 g_assert (callback != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (callback != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 505, ((const char*) (__func__
)), "callback != NULL"); } while (0)
;
506
507 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));
508
509 if (include_internals)
510 {
511 if (labeled_image->details->image != NULL((void*)0))
512 {
513 (* callback) (labeled_image->details->image, callback_data);
514 }
515
516 if (labeled_image->details->label != NULL((void*)0))
517 {
518 (* callback) (labeled_image->details->label, callback_data);
519 }
520 }
521}
522
523/* Class init methods */
524static void
525eel_labeled_image_class_init (EelLabeledImageClass *labeled_image_class)
526{
527 GObjectClass *gobject_class = G_OBJECT_CLASS (labeled_image_class)((((GObjectClass*) (void *) ((labeled_image_class)))));
528 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (labeled_image_class)((((GtkWidgetClass*) (void *) ((labeled_image_class)))));
529 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (labeled_image_class)((((GtkContainerClass*) (void *) ((labeled_image_class)))));
530 GtkBindingSet *binding_set;
531
532 /* GObjectClass */
533 gobject_class->set_property = eel_labeled_image_set_property;
534 gobject_class->get_property = eel_labeled_image_get_property;
535
536 widget_class->destroy = eel_labeled_image_destroy;
537
538
539 /* GtkWidgetClass */
540 widget_class->size_allocate = eel_labeled_image_size_allocate;
541 widget_class->get_preferred_width = eel_labeled_image_get_preferred_width;
542 widget_class->get_preferred_height = eel_labeled_image_get_preferred_height;
543 widget_class->draw = eel_labeled_image_draw;
544
545 widget_class->map = eel_labeled_image_map;
546 widget_class->unmap = eel_labeled_image_unmap;
547
548 gtk_widget_class_set_accessible_type (widget_class, eel_labeled_image_accessible_get_type ());
549
550
551 /* GtkContainerClass */
552 container_class->add = eel_labeled_image_add;
553 container_class->remove = eel_labeled_image_remove;
554 container_class->forall = eel_labeled_image_forall;
555
556 labeled_image_signals[ACTIVATE] =
557 g_signal_new ("activate",
558 G_TYPE_FROM_CLASS (labeled_image_class)(((GTypeClass*) (labeled_image_class))->g_type),
559 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
560 G_STRUCT_OFFSET (EelLabeledImageClass,((glong) __builtin_offsetof(EelLabeledImageClass, activate))
561 activate)((glong) __builtin_offsetof(EelLabeledImageClass, activate)),
562 NULL((void*)0), NULL((void*)0),
563 g_cclosure_marshal_VOID__VOID,
564 G_TYPE_NONE((GType) ((1) << (2))), 0);
565 widget_class->activate_signal = labeled_image_signals[ACTIVATE];
566
567 binding_set = gtk_binding_set_by_class (gobject_class);
568
569 gtk_binding_entry_add_signal (binding_set,
570 GDK_KEY_Return0xff0d, 0,
571 "activate", 0);
572 gtk_binding_entry_add_signal (binding_set,
573 GDK_KEY_KP_Enter0xff8d, 0,
574 "activate", 0);
575 gtk_binding_entry_add_signal (binding_set,
576 GDK_KEY_space0x020, 0,
577 "activate", 0);
578
579
580 /* Properties */
581 g_object_class_install_property (
582 gobject_class,
583 PROP_PIXBUF,
584 g_param_spec_object ("pixbuf", NULL((void*)0), NULL((void*)0),
585 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ()), G_PARAM_READWRITE));
586
587 g_object_class_install_property (
588 gobject_class,
589 PROP_LABEL,
590 g_param_spec_string ("label", NULL((void*)0), NULL((void*)0),
591 "", G_PARAM_READWRITE));
592
593
594 g_object_class_install_property (
595 gobject_class,
596 PROP_LABEL_POSITION,
597 g_param_spec_enum ("label_position", NULL((void*)0), NULL((void*)0),
598 GTK_TYPE_POSITION_TYPE(gtk_position_type_get_type ()),
599 GTK_POS_BOTTOM,
600 G_PARAM_READWRITE));
601
602 g_object_class_install_property (
603 gobject_class,
604 PROP_SHOW_LABEL,
605 g_param_spec_boolean ("show_label", NULL((void*)0), NULL((void*)0),
606 TRUE(!(0)), G_PARAM_READWRITE));
607
608 g_object_class_install_property (
609 gobject_class,
610 PROP_SHOW_IMAGE,
611 g_param_spec_boolean ("show_image", NULL((void*)0), NULL((void*)0),
612 TRUE(!(0)), G_PARAM_READWRITE));
613
614
615 g_object_class_install_property (
616 gobject_class,
617 PROP_SPACING,
618 g_param_spec_uint ("spacing", NULL((void*)0), NULL((void*)0),
619 0,
620 G_MAXINT2147483647,
621 DEFAULT_SPACING0,
622 G_PARAM_READWRITE));
623
624 g_object_class_install_property (
625 gobject_class,
626 PROP_X_PADDING,
627 g_param_spec_int ("x_padding", NULL((void*)0), NULL((void*)0),
628 0,
629 G_MAXINT2147483647,
630 DEFAULT_X_PADDING0,
631 G_PARAM_READWRITE));
632
633 g_object_class_install_property (
634 gobject_class,
635 PROP_Y_PADDING,
636 g_param_spec_int ("y_padding", NULL((void*)0), NULL((void*)0),
637 0,
638 G_MAXINT2147483647,
639 DEFAULT_Y_PADDING0,
640 G_PARAM_READWRITE));
641
642 g_object_class_install_property (
643 gobject_class,
644 PROP_X_ALIGNMENT,
645 g_param_spec_float ("x_alignment", NULL((void*)0), NULL((void*)0),
646 0.0,
647 1.0,
648 DEFAULT_X_ALIGNMENT0.5,
649 G_PARAM_READWRITE));
650
651 g_object_class_install_property (
652 gobject_class,
653 PROP_Y_ALIGNMENT,
654 g_param_spec_float ("y_alignment", NULL((void*)0), NULL((void*)0),
655 0.0,
656 1.0,
657 DEFAULT_Y_ALIGNMENT0.5,
658 G_PARAM_READWRITE));
659
660 g_object_class_install_property (
661 gobject_class,
662 PROP_FILL,
663 g_param_spec_boolean ("fill", NULL((void*)0), NULL((void*)0),
664 FALSE(0),
665 G_PARAM_READWRITE));
666
667}
668
669/* Private EelLabeledImage methods */
670static gboolean
671is_fixed_height (const EelLabeledImage *labeled_image)
672{
673 return labeled_image->details->fixed_image_height > 0;
674}
675
676static EelDimensions
677labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image)
678{
679 EelDimensions image_dimensions;
680 GtkRequisition image_requisition;
681
682 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 682, ((const char*) (__func__))
, "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
683
684 if (!labeled_image_show_image (labeled_image))
685 {
686 return eel_dimensions_empty;
687 }
688
689 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
690
691 image_dimensions.width = (int) image_requisition.width;
692 image_dimensions.height = (int) image_requisition.height;
693
694 if (is_fixed_height (labeled_image))
695 {
696 image_dimensions.height = labeled_image->details->fixed_image_height;
697 }
698
699 return image_dimensions;
700}
701
702static EelDimensions
703labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image)
704{
705 EelDimensions label_dimensions;
706 GtkRequisition label_requisition;
707
708 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 708, ((const char*) (__func__))
, "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
709
710 if (!labeled_image_show_label (labeled_image))
711 {
712 return eel_dimensions_empty;
713 }
714
715 gtk_widget_get_preferred_size (labeled_image->details->label, &label_requisition, NULL((void*)0));
716
717 label_dimensions.width = (int) label_requisition.width;
718 label_dimensions.height = (int) label_requisition.height;
719
720 return label_dimensions;
721}
722
723static EelIRect
724labeled_image_get_image_bounds_fill (const EelLabeledImage *labeled_image)
725{
726 EelIRect image_bounds;
727 EelDimensions image_dimensions;
728 EelIRect content_bounds;
729 EelIRect bounds;
730
731 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_90
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 731, ((const char*) (__func__))
, "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
732
733 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
734
735 if (eel_dimensions_are_empty (image_dimensions))
736 {
737 return eel_irect_empty;
738 }
739
740 content_bounds = labeled_image_get_content_bounds (labeled_image);
741 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
742
743 if (!labeled_image_show_label (labeled_image))
744 {
745 image_bounds = bounds;
746 }
747 else
748 {
749 switch (labeled_image->details->label_position)
750 {
751 case GTK_POS_LEFT:
752 image_bounds.y0 = bounds.y0;
753 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
754 image_bounds.y1 = bounds.y1;
755 image_bounds.x1 = bounds.x1;
756 break;
757
758 case GTK_POS_RIGHT:
759 image_bounds.y0 = bounds.y0;
760 image_bounds.x0 = bounds.x0;
761 image_bounds.y1 = bounds.y1;
762 image_bounds.x1 = content_bounds.x0 + image_dimensions.width;
763 break;
764
765 case GTK_POS_TOP:
766 image_bounds.x0 = bounds.x0;
767 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
768 image_bounds.x1 = bounds.x1;
769 image_bounds.y1 = bounds.y1;
770 break;
771
772 case GTK_POS_BOTTOM:
773 image_bounds.x0 = bounds.x0;
774 image_bounds.y0 = bounds.y0;
775 image_bounds.x1 = bounds.x1;
776 image_bounds.y1 = content_bounds.y0 + image_dimensions.height;
777 break;
778
779 default:
780 image_bounds.x0 = 0;
781 image_bounds.y0 = 0;
782 image_bounds.x1 = 0;
783 image_bounds.y1 = 0;
784 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 784
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
785 }
786 }
787
788 return image_bounds;
789}
790
791EelIRect
792eel_labeled_image_get_image_bounds (const EelLabeledImage *labeled_image)
793{
794 EelDimensions image_dimensions;
795 EelDimensions label_dimensions;
796 GtkRequisition image_requisition;
797 EelIRect image_bounds;
798 EelIRect content_bounds;
799
800 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
801
802 if (labeled_image->details->fill)
803 {
804 return labeled_image_get_image_bounds_fill (labeled_image);
805 }
806
807 /* get true real dimensions if we're in fixed height mode */
808 if (is_fixed_height (labeled_image) && labeled_image_show_image (labeled_image))
809 {
810 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
811 image_dimensions.width = (int) image_requisition.width;
812 image_dimensions.height = (int) image_requisition.height;
813 }
814 else
815 {
816 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
817 }
818
819 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
820
821 if (eel_dimensions_are_empty (image_dimensions))
822 {
823 return eel_irect_empty;
824 }
825
826 content_bounds = labeled_image_get_content_bounds (labeled_image);
827
828 if (!labeled_image_show_label (labeled_image))
829 {
830 image_bounds.x0 =
831 content_bounds.x0 +
832 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
833 image_bounds.y0 =
834 content_bounds.y0 +
835 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
836 }
837 else
838 {
839 switch (labeled_image->details->label_position)
840 {
841 case GTK_POS_LEFT:
842 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
843 image_bounds.y0 =
844 content_bounds.y0 +
845 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
846 break;
847
848 case GTK_POS_RIGHT:
849 image_bounds.x0 = content_bounds.x0;
850 image_bounds.y0 =
851 content_bounds.y0 +
852 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
853 break;
854
855 case GTK_POS_TOP:
856 image_bounds.x0 =
857 content_bounds.x0 +
858 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
859 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
860 break;
861
862 case GTK_POS_BOTTOM:
863 image_bounds.x0 =
864 content_bounds.x0 +
865 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
866
867 if (is_fixed_height (labeled_image))
868 {
869 image_bounds.y0 = content_bounds.y0 + eel_irect_get_height (content_bounds)
870 - image_dimensions.height
871 - label_dimensions.height
872 - labeled_image->details->spacing;
873 }
874 else
875 {
876 image_bounds.y0 = content_bounds.y0;
877 }
878
879 break;
880
881 default:
882 image_bounds.x0 = 0;
883 image_bounds.y0 = 0;
884 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 884
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
885 }
886 }
887
888 image_bounds.x1 = image_bounds.x0 + image_dimensions.width;
889 image_bounds.y1 = image_bounds.y0 + image_dimensions.height;
890
891 return image_bounds;
892}
893
894static EelIRect
895labeled_image_get_label_bounds_fill (const EelLabeledImage *labeled_image)
896{
897 EelIRect label_bounds;
898 EelDimensions label_dimensions;
899 EelIRect content_bounds;
900 EelIRect bounds;
901
902 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_92
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 902, ((const char*) (__func__))
, "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
903
904 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
905
906 if (eel_dimensions_are_empty (label_dimensions))
907 {
908 return eel_irect_empty;
909 }
910
911 content_bounds = labeled_image_get_content_bounds (labeled_image);
912 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
913
914 /* Only the label is shown */
915 if (!labeled_image_show_image (labeled_image))
916 {
917 label_bounds = bounds;
918 /* Both label and image are shown */
919 }
920 else
921 {
922 switch (labeled_image->details->label_position)
923 {
924 case GTK_POS_LEFT:
925 label_bounds.y0 = bounds.y0;
926 label_bounds.x0 = bounds.x0;
927 label_bounds.y1 = bounds.y1;
928 label_bounds.x1 = content_bounds.x0 + label_dimensions.width;
929 break;
930
931 case GTK_POS_RIGHT:
932 label_bounds.y0 = bounds.y0;
933 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
934 label_bounds.y1 = bounds.y1;
935 label_bounds.x1 = bounds.x1;
936 break;
937
938 case GTK_POS_TOP:
939 label_bounds.x0 = bounds.x0;
940 label_bounds.y0 = bounds.y0;
941 label_bounds.x1 = bounds.x1;
942 label_bounds.y1 = content_bounds.y0 + label_dimensions.height;
943 break;
944
945 case GTK_POS_BOTTOM:
946 label_bounds.x0 = bounds.x0;
947 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
948 label_bounds.x1 = bounds.x1;
949 label_bounds.y1 = bounds.y1;
950 break;
951
952 default:
953 label_bounds.x0 = 0;
954 label_bounds.y0 = 0;
955 label_bounds.x1 = 0;
956 label_bounds.y1 = 0;
957 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 957
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
958 }
959 }
960
961 return label_bounds;
962}
963
964EelIRect
965eel_labeled_image_get_label_bounds (const EelLabeledImage *labeled_image)
966{
967 EelIRect label_bounds;
968 EelDimensions label_dimensions;
969 EelIRect content_bounds;
970
971 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_93 = 1; else _g_boolean_var_93 = 0
; _g_boolean_var_93; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
972
973 if (labeled_image->details->fill)
974 {
975 return labeled_image_get_label_bounds_fill (labeled_image);
976 }
977
978 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
979
980 if (eel_dimensions_are_empty (label_dimensions))
981 {
982 return eel_irect_empty;
983 }
984
985 content_bounds = labeled_image_get_content_bounds (labeled_image);
986
987 /* Only the label is shown */
988 if (!labeled_image_show_image (labeled_image))
989 {
990 label_bounds.x0 =
991 content_bounds.x0 +
992 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
993 label_bounds.y0 =
994 content_bounds.y0 +
995 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
996 /* Both label and image are shown */
997 }
998 else
999 {
1000 switch (labeled_image->details->label_position)
1001 {
1002 case GTK_POS_LEFT:
1003 label_bounds.x0 = content_bounds.x0;
1004 label_bounds.y0 =
1005 content_bounds.y0 +
1006 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1007 break;
1008
1009 case GTK_POS_RIGHT:
1010 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
1011 label_bounds.y0 =
1012 content_bounds.y0 +
1013 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1014 break;
1015
1016 case GTK_POS_TOP:
1017 label_bounds.x0 =
1018 content_bounds.x0 +
1019 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1020 label_bounds.y0 = content_bounds.y0;
1021 break;
1022
1023 case GTK_POS_BOTTOM:
1024 label_bounds.x0 =
1025 content_bounds.x0 +
1026 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1027 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
1028 break;
1029
1030 default:
1031 label_bounds.x0 = 0;
1032 label_bounds.y0 = 0;
1033 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 1033
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1034 }
1035 }
1036
1037 label_bounds.x1 = label_bounds.x0 + label_dimensions.width;
1038 label_bounds.y1 = label_bounds.y0 + label_dimensions.height;
1039
1040 return label_bounds;
1041}
1042
1043static void
1044labeled_image_update_alignments (EelLabeledImage *labeled_image)
1045{
1046
1047 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_94
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 1047, ((const char*) (__func__)
), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1048
1049 if (labeled_image->details->label != NULL((void*)0))
1050 {
1051 if (labeled_image->details->fill)
1052 {
1053 float x_alignment;
1054 float y_alignment;
1055
1056 x_alignment = gtk_label_get_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
)
;
Value stored to 'x_alignment' is never read
1057 y_alignment = gtk_label_get_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
1058
1059 /* Only the label is shown */
1060 if (!labeled_image_show_image (labeled_image))
1061 {
1062 x_alignment = 0.5;
1063 y_alignment = 0.5;
1064 /* Both label and image are shown */
1065 }
1066 else
1067 {
1068 switch (labeled_image->details->label_position)
1069 {
1070 case GTK_POS_LEFT:
1071 x_alignment = 1.0;
1072 y_alignment = 0.5;
1073 break;
1074
1075 case GTK_POS_RIGHT:
1076 x_alignment = 0.0;
1077 y_alignment = 0.5;
1078 break;
1079
1080 case GTK_POS_TOP:
1081 x_alignment = 0.5;
1082 y_alignment = 1.0;
1083 break;
1084
1085 case GTK_POS_BOTTOM:
1086 x_alignment = 0.5;
1087 y_alignment = 0.0;
1088 break;
1089 }
1090
1091 }
1092
1093 gtk_label_set_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, x_alignment);
1094 gtk_label_set_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, y_alignment);
1095 }
1096 }
1097
1098 if (labeled_image->details->image != NULL((void*)0))
1099 {
1100 if (labeled_image->details->fill)
1101 {
1102 float x_alignment;
1103 float y_alignment;
1104
1105 x_alignment = gtk_widget_get_halign (labeled_image->details->image);
1106 y_alignment = gtk_widget_get_valign (labeled_image->details->image);
1107
1108 /* Only the image is shown */
1109 if (!labeled_image_show_label (labeled_image))
1110 {
1111 x_alignment = 0.5;
1112 y_alignment = 0.5;
1113 /* Both label and image are shown */
1114 }
1115 else
1116 {
1117 switch (labeled_image->details->label_position)
1118 {
1119 case GTK_POS_LEFT:
1120 x_alignment = 0.0;
1121 y_alignment = 0.5;
1122 break;
1123
1124 case GTK_POS_RIGHT:
1125 x_alignment = 1.0;
1126 y_alignment = 0.5;
1127 break;
1128
1129 case GTK_POS_TOP:
1130 x_alignment = 0.5;
1131 y_alignment = 0.0;
1132 break;
1133
1134 case GTK_POS_BOTTOM:
1135 x_alignment = 0.5;
1136 y_alignment = 1.0;
1137 break;
1138 }
1139 }
1140
1141 gtk_widget_set_halign (labeled_image->details->image, x_alignment);
1142 gtk_widget_set_valign (labeled_image->details->image, y_alignment);
1143 }
1144 }
1145}
1146
1147static EelDimensions
1148labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image)
1149{
1150 EelDimensions image_dimensions;
1151 EelDimensions label_dimensions;
1152 EelDimensions content_dimensions;
1153
1154 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_95 = 1; else _g_boolean_var_95 = 0
; _g_boolean_var_95; }), 1)) ; else g_assertion_message_expr (
"Eel", "eel-labeled-image.c", 1154, ((const char*) (__func__)
), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1155
1156 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
1157 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
1158
1159 content_dimensions = eel_dimensions_empty;
1160
1161 /* Both shown */
1162 if (!eel_dimensions_are_empty (image_dimensions) && !eel_dimensions_are_empty (label_dimensions))
1163 {
1164 content_dimensions.width =
1165 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1166 switch (labeled_image->details->label_position)
1167 {
1168 case GTK_POS_LEFT:
1169 case GTK_POS_RIGHT:
1170 content_dimensions.width =
1171 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1172 content_dimensions.height = MAX (image_dimensions.height, label_dimensions.height)(((image_dimensions.height) > (label_dimensions.height)) ?
(image_dimensions.height) : (label_dimensions.height))
;
1173 break;
1174
1175 case GTK_POS_TOP:
1176 case GTK_POS_BOTTOM:
1177 content_dimensions.width = MAX (image_dimensions.width, label_dimensions.width)(((image_dimensions.width) > (label_dimensions.width)) ? (
image_dimensions.width) : (label_dimensions.width))
;
1178 content_dimensions.height =
1179 image_dimensions.height + labeled_image->details->spacing + label_dimensions.height;
1180 break;
1181 }
1182 /* Only image shown */
1183 }
1184 else if (!eel_dimensions_are_empty (image_dimensions))
1185 {
1186 content_dimensions.width = image_dimensions.width;
1187 content_dimensions.height = image_dimensions.height;
1188 /* Only label shown */
1189 }
1190 else
1191 {
1192 content_dimensions.width = label_dimensions.width;
1193 content_dimensions.height = label_dimensions.height;
1194 }
1195
1196 return content_dimensions;
1197}
1198
1199static EelIRect
1200labeled_image_get_content_bounds (const EelLabeledImage *labeled_image)
1201{
1202 EelDimensions content_dimensions;
1203 EelIRect content_bounds;
1204 EelIRect bounds;
1205
1206 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_96
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 1206, ((const char*) (__func__)
), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1207
1208 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1209
1210 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
1211 content_bounds = eel_irect_align (bounds,
1212 content_dimensions.width,
1213 content_dimensions.height,
1214 labeled_image->details->x_alignment,
1215 labeled_image->details->y_alignment);
1216
1217 return content_bounds;
1218}
1219
1220static void
1221labeled_image_ensure_label (EelLabeledImage *labeled_image)
1222{
1223 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_97
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_97 = 1; else _g_boolean_var_97 = 0
; _g_boolean_var_97; }), 1)) ; else g_assertion_message_expr (
"Eel", "eel-labeled-image.c", 1223, ((const char*) (__func__)
), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1224
1225 if (labeled_image->details->label != NULL((void*)0))
1226 {
1227 return;
1228 }
1229
1230 labeled_image->details->label = gtk_label_new (NULL((void*)0));
1231 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->label);
1232 gtk_widget_show (labeled_image->details->label);
1233}
1234
1235static void
1236labeled_image_ensure_image (EelLabeledImage *labeled_image)
1237{
1238 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 1238, ((const char*) (__func__)
), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1239
1240 if (labeled_image->details->image != NULL((void*)0))
1241 {
1242 return;
1243 }
1244
1245 labeled_image->details->image = gtk_image_new ();
1246 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->image);
1247 gtk_widget_show (labeled_image->details->image);
1248}
1249
1250static gboolean
1251labeled_image_show_image (const EelLabeledImage *labeled_image)
1252{
1253 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_99
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr (
"Eel", "eel-labeled-image.c", 1253, ((const char*) (__func__)
), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1254
1255 return labeled_image->details->image != NULL((void*)0) && labeled_image->details->show_image;
1256}
1257
1258static gboolean
1259labeled_image_show_label (const EelLabeledImage *labeled_image)
1260{
1261 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1261, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1262
1263 return labeled_image->details->label != NULL((void*)0) && labeled_image->details->show_label;
1264}
1265
1266/**
1267 * eel_labeled_image_new:
1268 * @text: Text to use for label or NULL.
1269 * @pixbuf: Pixbuf to use for image or NULL.
1270 *
1271 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1272 * NULL then the LabeledImage will show a label. If the &pixbuf parameter is not
1273 * NULL then the LabeledImage will show a pixbuf. Either of these can be NULL at
1274 * creation time.
1275 *
1276 * Later in the lifetime of the widget you can invoke methods that affect the
1277 * label and/or the image. If at creation time these were NULL, then they will
1278 * be created as neeeded.
1279 *
1280 * Thus, using this widget in place of EelImage or EelLabel is "free" with
1281 * only the GtkWidget and function call overhead.
1282 *
1283 */
1284GtkWidget*
1285eel_labeled_image_new (const char *text,
1286 GdkPixbuf *pixbuf)
1287{
1288 EelLabeledImage *labeled_image;
1289
1290 labeled_image = EEL_LABELED_IMAGE (gtk_widget_new (eel_labeled_image_get_type (), NULL))((((EelLabeledImage*) (void *) ((gtk_widget_new (eel_labeled_image_get_type
(), ((void*)0)))))))
;
1291
1292 if (text != NULL((void*)0))
1293 {
1294 eel_labeled_image_set_text (labeled_image, text);
1295 }
1296
1297 if (pixbuf != NULL((void*)0))
1298 {
1299 eel_labeled_image_set_pixbuf (labeled_image, pixbuf);
1300 }
1301
1302 labeled_image_update_alignments (labeled_image);
1303
1304 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1305}
1306
1307/**
1308 * eel_labeled_image_new_from_file_name:
1309 * @text: Text to use for label or NULL.
1310 * @file_name: File name of picture to use for pixbuf. Cannot be NULL.
1311 *
1312 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1313 * NULL then the LabeledImage will show a label.
1314 *
1315 */
1316GtkWidget*
1317eel_labeled_image_new_from_file_name (const char *text,
1318 const char *pixbuf_file_name)
1319{
1320 EelLabeledImage *labeled_image;
1321
1322 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_101 = 1;
else _g_boolean_var_101 = 0; _g_boolean_var_101; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1323
1324 labeled_image = EEL_LABELED_IMAGE (eel_labeled_image_new (text, NULL))((((EelLabeledImage*) (void *) ((eel_labeled_image_new (text,
((void*)0)))))))
;
1325 eel_labeled_image_set_pixbuf_from_file_name (labeled_image, pixbuf_file_name);
1326 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1327}
1328
1329/**
1330 * eel_labeled_image_set_label_position:
1331 * @labeled_image: A EelLabeledImage.
1332 * @label_position: The position of the label with respect to the image.
1333 *
1334 * Set the position of the label with respect to the image as follows:
1335 *
1336 * GTK_POS_LEFT:
1337 * [ <label> <image> ]
1338 *
1339 * GTK_POS_RIGHT:
1340 * [ <image> <label> ]
1341 *
1342 * GTK_POS_TOP:
1343 * [ <label> ]
1344 * [ <image> ]
1345 *
1346 * GTK_POS_BOTTOM:
1347 * [ <image> ]
1348 * [ <label> ]
1349 *
1350 */
1351void
1352eel_labeled_image_set_label_position (EelLabeledImage *labeled_image,
1353 GtkPositionType label_position)
1354{
1355 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1356 g_return_if_fail (label_position >= GTK_POS_LEFT)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
; if (label_position >= GTK_POS_LEFT) _g_boolean_var_103 =
1; else _g_boolean_var_103 = 0; _g_boolean_var_103; }), 1)))
{ } else { g_return_if_fail_warning ("Eel", ((const char*) (
__func__)), "label_position >= GTK_POS_LEFT"); return; } }
while (0)
;
1357 g_return_if_fail (label_position <= GTK_POS_BOTTOM)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if (label_position <= GTK_POS_BOTTOM) _g_boolean_var_104
= 1; else _g_boolean_var_104 = 0; _g_boolean_var_104; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "label_position <= GTK_POS_BOTTOM"); return;
} } while (0)
;
1358
1359 if (labeled_image->details->label_position == label_position)
1360 {
1361 return;
1362 }
1363
1364 labeled_image->details->label_position = label_position;
1365
1366 labeled_image_update_alignments (labeled_image);
1367
1368 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1369}
1370
1371/**
1372 * eel_labeled_image_get_label_postiion:
1373 * @labeled_image: A EelLabeledImage.
1374 *
1375 * Returns an enumeration indicating the position of the label with respect to the image.
1376 */
1377GtkPositionType
1378eel_labeled_image_get_label_position (const EelLabeledImage *labeled_image)
1379{
1380 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1381
1382 return labeled_image->details->label_position;
1383}
1384
1385/**
1386 * eel_labeled_image_set_show_label:
1387 * @labeled_image: A EelLabeledImage.
1388 * @show_image: A boolean value indicating whether the label should be shown.
1389 *
1390 * Update the labeled image to either show or hide the internal label widget.
1391 * This function doesnt have any effect if the LabeledImage doesnt already
1392 * contain an label.
1393 */
1394void
1395eel_labeled_image_set_show_label (EelLabeledImage *labeled_image,
1396 gboolean show_label)
1397{
1398 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1399
1400 if (labeled_image->details->show_label == show_label)
1401 {
1402 return;
1403 }
1404
1405 labeled_image->details->show_label = show_label;
1406
1407 if (labeled_image->details->label != NULL((void*)0))
1408 {
1409 if (labeled_image->details->show_label)
1410 {
1411 gtk_widget_show (labeled_image->details->label);
1412 }
1413 else
1414 {
1415 gtk_widget_hide (labeled_image->details->label);
1416 }
1417 }
1418
1419 labeled_image_update_alignments (labeled_image);
1420
1421 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1422}
1423
1424/**
1425 * eel_labeled_image_get_show_label:
1426 * @labeled_image: A EelLabeledImage.
1427 *
1428 * Returns a boolean value indicating whether the internal label is shown.
1429 */
1430gboolean
1431eel_labeled_image_get_show_label (const EelLabeledImage *labeled_image)
1432{
1433 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1434
1435 return labeled_image->details->show_label;
1436}
1437
1438/**
1439 * eel_labeled_image_set_show_image:
1440 * @labeled_image: A EelLabeledImage.
1441 * @show_image: A boolean value indicating whether the image should be shown.
1442 *
1443 * Update the labeled image to either show or hide the internal image widget.
1444 * This function doesnt have any effect if the LabeledImage doesnt already
1445 * contain an image.
1446 */
1447void
1448eel_labeled_image_set_show_image (EelLabeledImage *labeled_image,
1449 gboolean show_image)
1450{
1451 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1452
1453 if (labeled_image->details->show_image == show_image)
1454 {
1455 return;
1456 }
1457
1458 labeled_image->details->show_image = show_image;
1459
1460 if (labeled_image->details->image != NULL((void*)0))
1461 {
1462 if (labeled_image->details->show_image)
1463 {
1464 gtk_widget_show (labeled_image->details->image);
1465 }
1466 else
1467 {
1468 gtk_widget_hide (labeled_image->details->image);
1469 }
1470 }
1471
1472 labeled_image_update_alignments (labeled_image);
1473
1474 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1475}
1476
1477/**
1478 * eel_labeled_image_get_show_image:
1479 * @labeled_image: A EelLabeledImage.
1480 *
1481 * Returns a boolean value indicating whether the internal image is shown.
1482 */
1483gboolean
1484eel_labeled_image_get_show_image (const EelLabeledImage *labeled_image)
1485{
1486 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1487
1488 return labeled_image->details->show_image;
1489}
1490
1491
1492/**
1493 * eel_labeled_image_set_fixed_image_height:
1494 * @labeled_image: A EelLabeledImage.
1495 * @fixed_image_height: The new fixed image height.
1496 *
1497 * Normally, we measure the height of images, but it's sometimes useful
1498 * to use a fixed height for all the images. This routine sets the
1499 * image height to the passed in value
1500 *
1501 */
1502void
1503eel_labeled_image_set_fixed_image_height (EelLabeledImage *labeled_image,
1504 int new_height)
1505{
1506 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1507
1508 if (labeled_image->details->fixed_image_height == new_height)
1509 {
1510 return;
1511 }
1512
1513 labeled_image->details->fixed_image_height = new_height;
1514
1515 labeled_image_update_alignments (labeled_image);
1516
1517 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1518}
1519
1520/**
1521 * eel_labeled_image_set_selected:
1522 * @labeled_image: A EelLabeledImage.
1523 * @selected: A boolean value indicating whether the labeled image
1524 * should be selected.
1525 *
1526 * Selects or deselects the labeled image.
1527 *
1528 */
1529void
1530eel_labeled_image_set_selected (EelLabeledImage *labeled_image,
1531 gboolean selected)
1532{
1533 GtkStateFlags state;
1534 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1535
1536 state = selected ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_NORMAL;
1537
1538 gtk_widget_set_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), state, TRUE(!(0)));
1539 gtk_widget_set_state_flags (labeled_image->details->image, state, TRUE(!(0)));
1540 gtk_widget_set_state_flags (labeled_image->details->label, state, TRUE(!(0)));
1541
1542}
1543
1544/**
1545 * eel_labeled_image_get_selected:
1546 * @labeled_image: A EelLabeledImage.
1547 *
1548 * Returns the selected state of the labeled image.
1549 *
1550 */
1551gboolean
1552eel_labeled_image_get_selected (EelLabeledImage *labeled_image)
1553{
1554 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return ((0)); } } while (0)
;
1555
1556 return gtk_widget_get_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))))) == GTK_STATE_FLAG_SELECTED;
1557}
1558
1559/**
1560 * eel_labeled_image_set_spacing:
1561 * @labeled_image: A EelLabeledImage.
1562 * @spacing: The new spacing between label and image.
1563 *
1564 * Set the spacing between label and image. This will only affect
1565 * the geometry of the widget if both a label and image are currently
1566 * visible.
1567 *
1568 */
1569void
1570eel_labeled_image_set_spacing (EelLabeledImage *labeled_image,
1571 guint spacing)
1572{
1573 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1574
1575 if (labeled_image->details->spacing == spacing)
1576 {
1577 return;
1578 }
1579
1580 labeled_image->details->spacing = spacing;
1581
1582 labeled_image_update_alignments (labeled_image);
1583
1584 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1585}
1586
1587/**
1588 * eel_labeled_image_get_spacing:
1589 * @labeled_image: A EelLabeledImage.
1590 *
1591 * Returns: The spacing between the label and image.
1592 */
1593guint
1594eel_labeled_image_get_spacing (const EelLabeledImage *labeled_image)
1595{
1596 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1597
1598 return labeled_image->details->spacing;
1599}
1600
1601/**
1602 * eel_labeled_image_set_x_padding:
1603 * @labeled_image: A EelLabeledImage.
1604 * @x_padding: The new horizontal padding.
1605 *
1606 * Set horizontal padding for the EelLabeledImage. The padding
1607 * attribute work just like that in GtkMisc.
1608 */
1609void
1610eel_labeled_image_set_x_padding (EelLabeledImage *labeled_image,
1611 int x_padding)
1612{
1613 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1614
1615 x_padding = MAX (0, x_padding)(((0) > (x_padding)) ? (0) : (x_padding));
1616
1617 if (labeled_image->details->x_padding == x_padding)
1618 {
1619 return;
1620 }
1621
1622 labeled_image->details->x_padding = x_padding;
1623 labeled_image_update_alignments (labeled_image);
1624 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1625}
1626
1627/**
1628 * eel_labeled_image_get_x_padding:
1629 * @labeled_image: A EelLabeledImage.
1630 *
1631 * Returns: The horizontal padding for the LabeledImage's content.
1632 */
1633int
1634eel_labeled_image_get_x_padding (const EelLabeledImage *labeled_image)
1635{
1636 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1637
1638 return labeled_image->details->x_padding;
1639}
1640
1641/**
1642 * eel_labeled_image_set_y_padding:
1643 * @labeled_image: A EelLabeledImage.
1644 * @x_padding: The new vertical padding.
1645 *
1646 * Set vertical padding for the EelLabeledImage. The padding
1647 * attribute work just like that in GtkMisc.
1648 */
1649void
1650eel_labeled_image_set_y_padding (EelLabeledImage *labeled_image,
1651 int y_padding)
1652{
1653 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1654
1655 y_padding = MAX (0, y_padding)(((0) > (y_padding)) ? (0) : (y_padding));
1656
1657 if (labeled_image->details->y_padding == y_padding)
1658 {
1659 return;
1660 }
1661
1662 labeled_image->details->y_padding = y_padding;
1663 labeled_image_update_alignments (labeled_image);
1664 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1665}
1666
1667/**
1668 * eel_labeled_image_get_x_padding:
1669 * @labeled_image: A EelLabeledImage.
1670 *
1671 * Returns: The vertical padding for the LabeledImage's content.
1672 */
1673int
1674eel_labeled_image_get_y_padding (const EelLabeledImage *labeled_image)
1675{
1676 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1677
1678 return labeled_image->details->y_padding;
1679}
1680
1681/**
1682 * eel_labeled_image_set_x_alignment:
1683 * @labeled_image: A EelLabeledImage.
1684 * @x_alignment: The new horizontal alignment.
1685 *
1686 * Set horizontal alignment for the EelLabeledImage's content.
1687 * The 'content' is the union of the image and label. The alignment
1688 * attribute work just like that in GtkMisc.
1689 */
1690void
1691eel_labeled_image_set_x_alignment (EelLabeledImage *labeled_image,
1692 float x_alignment)
1693{
1694 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1695
1696 x_alignment = MAX (0, x_alignment)(((0) > (x_alignment)) ? (0) : (x_alignment));
1697 x_alignment = MIN (1.0, x_alignment)(((1.0) < (x_alignment)) ? (1.0) : (x_alignment));
1698
1699 if (labeled_image->details->x_alignment == x_alignment)
1700 {
1701 return;
1702 }
1703
1704 labeled_image->details->x_alignment = x_alignment;
1705 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1706}
1707
1708/**
1709 * eel_labeled_image_get_x_alignment:
1710 * @labeled_image: A EelLabeledImage.
1711 *
1712 * Returns: The horizontal alignment for the LabeledImage's content.
1713 */
1714float
1715eel_labeled_image_get_x_alignment (const EelLabeledImage *labeled_image)
1716{
1717 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1718
1719 return labeled_image->details->x_alignment;
1720}
1721
1722/**
1723 * eel_labeled_image_set_y_alignment:
1724 * @labeled_image: A EelLabeledImage.
1725 * @y_alignment: The new vertical alignment.
1726 *
1727 * Set vertical alignment for the EelLabeledImage's content.
1728 * The 'content' is the union of the image and label. The alignment
1729 * attribute work just like that in GtkMisc.
1730 */
1731void
1732eel_labeled_image_set_y_alignment (EelLabeledImage *labeled_image,
1733 float y_alignment)
1734{
1735 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1736
1737 y_alignment = MAX (0, y_alignment)(((0) > (y_alignment)) ? (0) : (y_alignment));
1738 y_alignment = MIN (1.0, y_alignment)(((1.0) < (y_alignment)) ? (1.0) : (y_alignment));
1739
1740 if (labeled_image->details->y_alignment == y_alignment)
1741 {
1742 return;
1743 }
1744
1745 labeled_image->details->y_alignment = y_alignment;
1746 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1747}
1748
1749/**
1750 * eel_labeled_image_get_y_alignment:
1751 * @labeled_image: A EelLabeledImage.
1752 *
1753 * Returns: The vertical alignment for the LabeledImage's content.
1754 */
1755float
1756eel_labeled_image_get_y_alignment (const EelLabeledImage *labeled_image)
1757{
1758 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1759
1760 return labeled_image->details->y_alignment;
1761}
1762
1763/**
1764 * eel_labeled_image_set_fill:
1765 * @labeled_image: A EelLabeledImage.
1766 * @fill: A boolean value indicating whether the internal image and label
1767 * widgets should fill all the available allocation.
1768 *
1769 * By default the internal image and label wigets are sized to their natural
1770 * preferred geometry. You can use the 'fill' attribute of LabeledImage
1771 * to have the internal widgets fill as much of the LabeledImage allocation
1772 * as is available.
1773 */
1774void
1775eel_labeled_image_set_fill (EelLabeledImage *labeled_image,
1776 gboolean fill)
1777{
1778 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1779
1780 if (labeled_image->details->fill == fill)
1781 {
1782 return;
1783 }
1784
1785 labeled_image->details->fill = fill;
1786
1787 labeled_image_update_alignments (labeled_image);
1788
1789 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1790}
1791
1792/**
1793 * eel_labeled_image_get_fill:
1794 * @labeled_image: A EelLabeledImage.
1795 *
1796 * Retruns a boolean value indicating whether the internal widgets fill
1797 * all the available allocation.
1798 */
1799gboolean
1800eel_labeled_image_get_fill (const EelLabeledImage *labeled_image)
1801{
1802 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_124 = 1; else _g_boolean_var_124 =
0; _g_boolean_var_124; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1803
1804 return labeled_image->details->fill;
1805}
1806
1807static void
1808eel_labled_set_mnemonic_widget (GtkWidget *image_widget,
1809 GtkWidget *mnemonic_widget)
1810{
1811 EelLabeledImage *image;
1812
1813 g_assert (EEL_IS_LABELED_IMAGE (image_widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_widget)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1813, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (image_widget)"); } while (0)
;
1814
1815 image = EEL_LABELED_IMAGE (image_widget)((((EelLabeledImage*) (void *) ((image_widget)))));
1816
1817 if (image->details->label)
1818 gtk_label_set_mnemonic_widget
1819 (GTK_LABEL (image->details->label)((((GtkLabel*) (void *) ((image->details->label))))), mnemonic_widget);
1820}
1821
1822/**
1823 * eel_labeled_image_button_new:
1824 * @text: Text to use for label or NULL.
1825 * @pixbuf: Pixbuf to use for image or NULL.
1826 *
1827 * Create a stock GtkButton with a EelLabeledImage child.
1828 *
1829 */
1830GtkWidget *
1831eel_labeled_image_button_new (const char *text,
1832 GdkPixbuf *pixbuf)
1833{
1834 GtkWidget *button;
1835 GtkWidget *labeled_image;
1836
1837 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1838 labeled_image = eel_labeled_image_new (text, pixbuf);
1839 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1840 eel_labled_set_mnemonic_widget (labeled_image, button);
1841 gtk_widget_show (labeled_image);
1842
1843 return button;
1844}
1845
1846/**
1847 * eel_labeled_image_button_new_from_file_name:
1848 * @text: Text to use for label or NULL.
1849 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1850 *
1851 * Create a stock GtkToggleButton with a EelLabeledImage child.
1852 *
1853 */
1854GtkWidget *
1855eel_labeled_image_button_new_from_file_name (const char *text,
1856 const char *pixbuf_file_name)
1857{
1858 GtkWidget *button;
1859 GtkWidget *labeled_image;
1860
1861 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_126 = 1;
else _g_boolean_var_126 = 0; _g_boolean_var_126; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1862
1863 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1864 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1865 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1866 eel_labled_set_mnemonic_widget (labeled_image, button);
1867 gtk_widget_show (labeled_image);
1868
1869 return button;
1870}
1871
1872/**
1873 * eel_labeled_image_toggle_button_new:
1874 * @text: Text to use for label or NULL.
1875 * @pixbuf: Pixbuf to use for image or NULL.
1876 *
1877 * Create a stock GtkToggleButton with a EelLabeledImage child.
1878 *
1879 */
1880GtkWidget *
1881eel_labeled_image_toggle_button_new (const char *text,
1882 GdkPixbuf *pixbuf)
1883{
1884 GtkWidget *toggle_button;
1885 GtkWidget *labeled_image;
1886
1887 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1888 labeled_image = eel_labeled_image_new (text, pixbuf);
1889 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1890 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1891 gtk_widget_show (labeled_image);
1892
1893 return toggle_button;
1894}
1895
1896/**
1897 * eel_labeled_image_toggle_button_new_from_file_name:
1898 * @text: Text to use for label or NULL.
1899 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1900 *
1901 * Create a stock GtkToggleButton with a EelLabeledImage child.
1902 *
1903 */
1904GtkWidget *
1905eel_labeled_image_toggle_button_new_from_file_name (const char *text,
1906 const char *pixbuf_file_name)
1907{
1908 GtkWidget *toggle_button;
1909 GtkWidget *labeled_image;
1910
1911 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_127 = 1;
else _g_boolean_var_127 = 0; _g_boolean_var_127; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1912
1913 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1914 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1915 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1916 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1917 gtk_widget_show (labeled_image);
1918
1919 return toggle_button;
1920}
1921
1922/**
1923 * eel_labeled_image_toggle_button_new:
1924 * @text: Text to use for label or NULL.
1925 * @pixbuf: Pixbuf to use for image or NULL.
1926 *
1927 * Create a stock GtkToggleButton with a EelLabeledImage child.
1928 *
1929 * Returns: the new radio button.
1930 */
1931GtkWidget *
1932eel_labeled_image_radio_button_new (const char *text,
1933 GdkPixbuf *pixbuf)
1934{
1935 GtkWidget *radio_button;
1936 GtkWidget *labeled_image;
1937
1938 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1939 labeled_image = eel_labeled_image_new (text, pixbuf);
1940 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1941 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1942 gtk_widget_show (labeled_image);
1943
1944 return radio_button;
1945}
1946
1947/**
1948 * eel_labeled_image_radio_button_new_from_file_name:
1949 * @text: Text to use for label or NULL.
1950 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1951 *
1952 * Create a stock GtkRadioButton with a EelLabeledImage child.
1953 *
1954 * Returns: the new radio button.
1955 */
1956GtkWidget *
1957eel_labeled_image_radio_button_new_from_file_name (const char *text,
1958 const char *pixbuf_file_name)
1959{
1960 GtkWidget *radio_button;
1961 GtkWidget *labeled_image;
1962
1963 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_128 = 1;
else _g_boolean_var_128 = 0; _g_boolean_var_128; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1964
1965 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1966 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1967 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1968 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1969 gtk_widget_show (labeled_image);
1970
1971 return radio_button;
1972}
1973
1974/*
1975 * Workaround some bugs in GtkCheckButton where the widget
1976 * does not redraw properly after leave or focus out events
1977 *
1978 * The workaround is to draw a little bit more than the
1979 * widget itself - 4 pixels worth. For some reason the
1980 * widget does not properly redraw its edges.
1981 */
1982static void
1983button_leave_callback (GtkWidget *widget,
1984 gpointer callback_data)
1985{
1986 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_129
= 1; else _g_boolean_var_129 = 0; _g_boolean_var_129; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 1986, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
1987
1988 if (gtk_widget_is_drawable (widget))
1989 {
1990 const int fudge = 4;
1991 EelIRect bounds;
1992
1993 bounds = eel_gtk_widget_get_bounds (widget);
1994
1995 bounds.x0 -= fudge;
1996 bounds.y0 -= fudge;
1997 bounds.x1 += fudge;
1998 bounds.y1 += fudge;
1999
2000 gtk_widget_queue_draw_area (gtk_widget_get_parent (widget),
2001 bounds.x0,
2002 bounds.y0,
2003 eel_irect_get_width (bounds),
2004 eel_irect_get_height (bounds));
2005 }
2006}
2007
2008static gint
2009button_focus_out_event_callback (GtkWidget *widget,
2010 GdkEventFocus *event,
2011 gpointer callback_data)
2012{
2013 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_130
= 1; else _g_boolean_var_130 = 0; _g_boolean_var_130; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 2013, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
2014
2015 button_leave_callback (widget, callback_data);
2016
2017 return FALSE(0);
2018}
2019
2020/**
2021 * eel_labeled_image_check_button_new:
2022 * @text: Text to use for label or NULL.
2023 * @pixbuf: Pixbuf to use for image or NULL.
2024 *
2025 * Create a stock GtkCheckButton with a EelLabeledImage child.
2026 *
2027 */
2028GtkWidget *
2029eel_labeled_image_check_button_new (const char *text,
2030 GdkPixbuf *pixbuf)
2031{
2032 GtkWidget *check_button;
2033 GtkWidget *labeled_image;
2034
2035 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2036 labeled_image = eel_labeled_image_new (text, pixbuf);
2037 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2038 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2039 gtk_widget_show (labeled_image);
2040
2041 /*
2042 * Workaround some bugs in GtkCheckButton where the widget
2043 * does not redraw properly after leave or focus out events
2044 */
2045 g_signal_connect (check_button, "leave",g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
2046 G_CALLBACK (button_leave_callback), NULL)g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
2047 g_signal_connect (check_button, "focus_out_event",g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
2048 G_CALLBACK (button_focus_out_event_callback), NULL)g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
;
2049
2050 return check_button;
2051}
2052
2053/**
2054 * eel_labeled_image_check_button_new_from_file_name:
2055 * @text: Text to use for label or NULL.
2056 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
2057 *
2058 * Create a stock GtkCheckButton with a EelLabeledImage child.
2059 *
2060 */
2061GtkWidget *
2062eel_labeled_image_check_button_new_from_file_name (const char *text,
2063 const char *pixbuf_file_name)
2064{
2065 GtkWidget *check_button;
2066 GtkWidget *labeled_image;
2067
2068 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_131 = 1;
else _g_boolean_var_131 = 0; _g_boolean_var_131; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
2069
2070 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2071 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
2072 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2073 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2074 gtk_widget_show (labeled_image);
2075
2076 return check_button;
2077}
2078
2079/*
2080 * The rest of the methods are proxies for those in EelImage and
2081 * EelLabel. We have all these so that we dont have to expose
2082 * our internal widgets at all. Probably more of these will be added
2083 * as they are needed.
2084 */
2085
2086/**
2087 * eel_labeled_image_set_pixbuf:
2088 * @labaled_image: A EelLabeledImage.
2089 * @pixbuf: New pixbuf to use or NULL.
2090 *
2091 * Change the pixbuf displayed by the LabeledImage. Note that the widget display
2092 * is only updated if the show_image attribute is TRUE.
2093 *
2094 * If no internal image widget exists as of yet, a new one will be created.
2095 *
2096 * A NULL &pixbuf will cause the internal image widget (if alive) to be destroyed.
2097 */
2098void
2099eel_labeled_image_set_pixbuf (EelLabeledImage *labeled_image,
2100 GdkPixbuf *pixbuf)
2101{
2102 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_132 = 1; else _g_boolean_var_132 =
0; _g_boolean_var_132; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2103
2104 if (pixbuf == NULL((void*)0))
2105 {
2106 if (labeled_image->details->image != NULL((void*)0))
2107 {
2108 gtk_widget_destroy (labeled_image->details->image);
2109 labeled_image->details->image = NULL((void*)0);
2110 }
2111
2112 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2113 }
2114 else
2115 {
2116 labeled_image_ensure_image (labeled_image);
2117 gtk_image_set_from_pixbuf (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf);
2118 }
2119}
2120
2121void
2122eel_labeled_image_set_pixbuf_from_file_name (EelLabeledImage *labeled_image,
2123 const char *pixbuf_file_name)
2124{
2125 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2126
2127 labeled_image_ensure_image (labeled_image);
2128 gtk_image_set_from_file (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf_file_name);
2129}
2130
2131/**
2132 * eel_labeled_image_set_text:
2133 * @labaled_image: A EelLabeledImage.
2134 * @text: New text (with mnemnonic) to use or NULL.
2135 *
2136 * Change the text displayed by the LabeledImage. Note that the widget display
2137 * is only updated if the show_label attribute is TRUE.
2138 *
2139 * If no internal label widget exists as of yet, a new one will be created.
2140 *
2141 * A NULL &text will cause the internal label widget (if alive) to be destroyed.
2142 */
2143void
2144eel_labeled_image_set_text (EelLabeledImage *labeled_image,
2145 const char *text)
2146{
2147 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_134 = 1; else _g_boolean_var_134 =
0; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2148
2149 if (text == NULL((void*)0))
2150 {
2151 if (labeled_image->details->label)
2152 {
2153 gtk_widget_destroy (labeled_image->details->label);
2154 labeled_image->details->label = NULL((void*)0);
2155 }
2156
2157 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2158 }
2159 else
2160 {
2161 labeled_image_ensure_label (labeled_image);
2162 gtk_label_set_text_with_mnemonic
2163 (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, text);
2164 }
2165}
2166
2167char *
2168eel_labeled_image_get_text (const EelLabeledImage *labeled_image)
2169{
2170 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_135 = 1; else _g_boolean_var_135 =
0; _g_boolean_var_135; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (((void*)0)); } } while (0)
;
2171
2172 if (labeled_image->details->label == NULL((void*)0))
2173 {
2174 return NULL((void*)0);
2175 }
2176
2177 return g_strdup (gtk_label_get_text (GTK_LABEL (labeled_image->details->label)))g_strdup_inline (gtk_label_get_text (((((GtkLabel*) (void *) (
(labeled_image->details->label)))))))
;
2178}
2179
2180void
2181eel_labeled_image_set_can_focus (EelLabeledImage *labeled_image,
2182 gboolean can_focus)
2183{
2184 gtk_widget_set_can_focus (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), can_focus);
2185}
2186
2187static AtkObjectClass *a11y_parent_class = NULL((void*)0);
2188
2189static void
2190eel_labeled_image_accessible_initialize (AtkObject *accessible,
2191 gpointer widget)
2192{
2193 a11y_parent_class->initialize (accessible, widget);
2194 atk_object_set_role (accessible, ATK_ROLE_IMAGE);
2195
2196}
2197
2198static EelLabeledImage *
2199get_image (gpointer object)
2200{
2201 GtkWidget *widget;
2202
2203 if (!(widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (object)((((GtkAccessible*) (void *) ((object))))))))
2204 {
2205 return NULL((void*)0);
2206 }
2207
2208 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; }))))
)
2209 widget = gtk_bin_get_child (GTK_BIN (widget)((((GtkBin*) (void *) ((widget))))));
2210
2211 return EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
2212}
2213
2214static const gchar* eel_labeled_image_accessible_get_name(AtkObject* accessible)
2215{
2216 EelLabeledImage* labeled_image;
2217
2218 labeled_image = get_image(accessible);
2219
2220 if (labeled_image && labeled_image->details && labeled_image->details->label)
2221 {
2222 return gtk_label_get_text(GTK_LABEL(labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
2223 }
2224
2225 g_warning("no label on '%p'", labeled_image);
2226
2227 return NULL((void*)0);
2228}
2229
2230static void
2231eel_labeled_image_accessible_image_get_size (AtkImage *image,
2232 gint *width,
2233 gint *height)
2234{
2235 EelLabeledImage *labeled_image;
2236 GtkAllocation allocation;
2237
2238 labeled_image = get_image (image);
2239
2240 if (!labeled_image || !labeled_image->details->image)
2241 {
2242 *width = *height = 0;
2243 return;
2244 }
2245
2246 gtk_widget_get_allocation (labeled_image->details->image, &allocation);
2247 *width = allocation.width;
2248 *height = allocation.height;
2249}
2250
2251static void
2252eel_labeled_image_accessible_image_interface_init (AtkImageIface *iface)
2253{
2254 iface->get_image_size = eel_labeled_image_accessible_image_get_size;
2255}
2256
2257typedef struct _EelLabeledImageAccessible EelLabeledImageAccessible;
2258typedef struct _EelLabeledImageAccessibleClass EelLabeledImageAccessibleClass;
2259
2260struct _EelLabeledImageAccessible
2261{
2262 GtkContainerAccessible parent;
2263};
2264
2265struct _EelLabeledImageAccessibleClass
2266{
2267 GtkContainerAccessibleClass parent_class;
2268};
2269
2270G_DEFINE_TYPE_WITH_CODE (EelLabeledImageAccessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2271 eel_labeled_image_accessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2272 GTK_TYPE_CONTAINER_ACCESSIBLE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2273 G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2274 eel_labeled_image_accessible_image_interface_init))static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
;
2275static void
2276eel_labeled_image_accessible_class_init (EelLabeledImageAccessibleClass *klass)
2277{
2278 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
2279 a11y_parent_class = g_type_class_peek_parent (klass);
2280
2281 atk_class->get_name = eel_labeled_image_accessible_get_name;
2282 atk_class->initialize = eel_labeled_image_accessible_initialize;
2283}
2284
2285static void
2286eel_labeled_image_accessible_init (EelLabeledImageAccessible *accessible)
2287{
2288}
2289
2290static void
2291eel_labeled_image_button_class_init (GtkWidgetClass *klass)
2292{
2293}
2294
2295static GType
2296eel_labeled_image_button_get_type (void)
2297{
2298 static GType type = 0;
2299
2300 if (!type)
2301 {
2302 GTypeInfo info =
2303 {
2304 sizeof (GtkButtonClass),
2305 (GBaseInitFunc) NULL((void*)0),
2306 (GBaseFinalizeFunc) NULL((void*)0),
2307 (GClassInitFunc) eel_labeled_image_button_class_init,
2308 NULL((void*)0), /* class_finalize */
2309 NULL((void*)0), /* class_data */
2310 sizeof (GtkButton),
2311 0, /* n_preallocs */
2312 (GInstanceInitFunc) NULL((void*)0)
2313 };
2314
2315 type = g_type_register_static
2316 (GTK_TYPE_BUTTON(gtk_button_get_type ()),
2317 "EelLabeledImageButton", &info, 0);
2318 }
2319
2320 return type;
2321}
2322
2323static GType
2324eel_labeled_image_check_button_get_type (void)
2325{
2326 static GType type = 0;
2327
2328 if (!type)
2329 {
2330 GTypeInfo info =
2331 {
2332 sizeof (GtkCheckButtonClass),
2333 (GBaseInitFunc) NULL((void*)0),
2334 (GBaseFinalizeFunc) NULL((void*)0),
2335 (GClassInitFunc) eel_labeled_image_button_class_init,
2336 NULL((void*)0), /* class_finalize */
2337 NULL((void*)0), /* class_data */
2338 sizeof (GtkCheckButton),
2339 0, /* n_preallocs */
2340 (GInstanceInitFunc) NULL((void*)0)
2341 };
2342
2343 type = g_type_register_static
2344 (GTK_TYPE_CHECK_BUTTON(gtk_check_button_get_type ()),
2345 "EelLabeledImageCheckButton", &info, 0);
2346 }
2347
2348 return type;
2349}
2350
2351static GType
2352eel_labeled_image_toggle_button_get_type (void)
2353{
2354 static GType type = 0;
2355
2356 if (!type)
2357 {
2358 GTypeInfo info =
2359 {
2360 sizeof (GtkToggleButtonClass),
2361 (GBaseInitFunc) NULL((void*)0),
2362 (GBaseFinalizeFunc) NULL((void*)0),
2363 (GClassInitFunc) eel_labeled_image_button_class_init,
2364 NULL((void*)0), /* class_finalize */
2365 NULL((void*)0), /* class_data */
2366 sizeof (GtkToggleButton),
2367 0, /* n_preallocs */
2368 (GInstanceInitFunc) NULL((void*)0)
2369 };
2370
2371 type = g_type_register_static
2372 (GTK_TYPE_TOGGLE_BUTTON(gtk_toggle_button_get_type ()),
2373 "EelLabeledImageToggleButton", &info, 0);
2374 }
2375
2376 return type;
2377}
2378
2379
2380static GType
2381eel_labeled_image_radio_button_get_type (void)
2382{
2383 static GType type = 0;
2384
2385 if (!type)
2386 {
2387 GTypeInfo info =
2388 {
2389 sizeof (GtkRadioButtonClass),
2390 (GBaseInitFunc) NULL((void*)0),
2391 (GBaseFinalizeFunc) NULL((void*)0),
2392 (GClassInitFunc) eel_labeled_image_button_class_init,
2393 NULL((void*)0), /* class_finalize */
2394 NULL((void*)0), /* class_data */
2395 sizeof (GtkRadioButton),
2396 0, /* n_preallocs */
2397 (GInstanceInitFunc) NULL((void*)0)
2398 };
2399
2400 type = g_type_register_static
2401 (GTK_TYPE_RADIO_BUTTON(gtk_radio_button_get_type ()),
2402 "EelLabeledImageRadioButton", &info, 0);
2403 }
2404
2405 return type;
2406}
diff --git a/2024-07-29-023715-6438-1/report-1e9f80.html b/2024-07-29-023715-6438-1/report-1e9f80.html new file mode 100644 index 000000000..6d28e5532 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-1e9f80.html @@ -0,0 +1,2899 @@ + + + +caja-pathbar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-pathbar.c
Warning:line 844, column 17
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'first_button')
+ +

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 caja-pathbar.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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-pathbar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* caja-pathbar.c
3 * Copyright (C) 2004 Red Hat, Inc., Jonathan Blandford <jrb@gnome.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include <config.h>
22#include <string.h>
23
24#include <gtk/gtk.h>
25#include <glib/gi18n.h>
26#include <gio/gio.h>
27
28#include <libcaja-private/caja-file.h>
29#include <libcaja-private/caja-file-utilities.h>
30#include <libcaja-private/caja-global-preferences.h>
31#include <libcaja-private/caja-icon-names.h>
32#include <libcaja-private/caja-trash-monitor.h>
33#include <libcaja-private/caja-dnd.h>
34#include <libcaja-private/caja-icon-dnd.h>
35
36#include "caja-pathbar.h"
37
38enum
39{
40 PATH_CLICKED,
41 PATH_EVENT,
42 LAST_SIGNAL
43};
44
45typedef enum
46{
47 NORMAL_BUTTON,
48 ROOT_BUTTON,
49 HOME_BUTTON,
50 DESKTOP_BUTTON,
51 MOUNT_BUTTON,
52 DEFAULT_LOCATION_BUTTON,
53} ButtonType;
54
55#define BUTTON_DATA(x)((ButtonData *)(x)) ((ButtonData *)(x))
56
57#define SCROLL_TIMEOUT150 150
58#define INITIAL_SCROLL_TIMEOUT300 300
59
60static guint path_bar_signals [LAST_SIGNAL] = { 0 };
61
62static gboolean desktop_is_home;
63
64#define CAJA_PATH_BAR_ICON_SIZE16 16
65
66typedef struct _ButtonData ButtonData;
67
68struct _ButtonData
69{
70 GtkWidget *button;
71 ButtonType type;
72 char *dir_name;
73 GFile *path;
74 CajaFile *file;
75 unsigned int file_changed_signal_id;
76
77 /* custom icon */
78 cairo_surface_t *custom_icon;
79
80 /* flag to indicate its the base folder in the URI */
81 gboolean is_base_dir;
82
83 GtkWidget *image;
84 GtkWidget *label;
85 guint ignore_changes : 1;
86 guint file_is_hidden : 1;
87 guint fake_root : 1;
88
89 CajaDragSlotProxyInfo drag_info;
90};
91
92G_DEFINE_TYPE (CajaPathBar,static void caja_path_bar_init (CajaPathBar *self); static void
caja_path_bar_class_init (CajaPathBarClass *klass); static GType
caja_path_bar_get_type_once (void); static gpointer caja_path_bar_parent_class
= ((void*)0); static gint CajaPathBar_private_offset; static
void caja_path_bar_class_intern_init (gpointer klass) { caja_path_bar_parent_class
= g_type_class_peek_parent (klass); if (CajaPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaPathBar_private_offset
); caja_path_bar_class_init ((CajaPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer caja_path_bar_get_instance_private
(CajaPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CajaPathBar_private_offset)))); } GType caja_path_bar_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_path_bar_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_container_get_type ()), g_intern_static_string ("CajaPathBar"
), sizeof (CajaPathBarClass), (GClassInitFunc)(void (*)(void)
) caja_path_bar_class_intern_init, sizeof (CajaPathBar), (GInstanceInitFunc
)(void (*)(void)) caja_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
93 caja_path_bar,static void caja_path_bar_init (CajaPathBar *self); static void
caja_path_bar_class_init (CajaPathBarClass *klass); static GType
caja_path_bar_get_type_once (void); static gpointer caja_path_bar_parent_class
= ((void*)0); static gint CajaPathBar_private_offset; static
void caja_path_bar_class_intern_init (gpointer klass) { caja_path_bar_parent_class
= g_type_class_peek_parent (klass); if (CajaPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaPathBar_private_offset
); caja_path_bar_class_init ((CajaPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer caja_path_bar_get_instance_private
(CajaPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CajaPathBar_private_offset)))); } GType caja_path_bar_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_path_bar_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_container_get_type ()), g_intern_static_string ("CajaPathBar"
), sizeof (CajaPathBarClass), (GClassInitFunc)(void (*)(void)
) caja_path_bar_class_intern_init, sizeof (CajaPathBar), (GInstanceInitFunc
)(void (*)(void)) caja_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
94 GTK_TYPE_CONTAINER)static void caja_path_bar_init (CajaPathBar *self); static void
caja_path_bar_class_init (CajaPathBarClass *klass); static GType
caja_path_bar_get_type_once (void); static gpointer caja_path_bar_parent_class
= ((void*)0); static gint CajaPathBar_private_offset; static
void caja_path_bar_class_intern_init (gpointer klass) { caja_path_bar_parent_class
= g_type_class_peek_parent (klass); if (CajaPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaPathBar_private_offset
); caja_path_bar_class_init ((CajaPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer caja_path_bar_get_instance_private
(CajaPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CajaPathBar_private_offset)))); } GType caja_path_bar_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_path_bar_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_container_get_type ()), g_intern_static_string ("CajaPathBar"
), sizeof (CajaPathBarClass), (GClassInitFunc)(void (*)(void)
) caja_path_bar_class_intern_init, sizeof (CajaPathBar), (GInstanceInitFunc
)(void (*)(void)) caja_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
;
95
96static void caja_path_bar_finalize (GObject *object);
97static void caja_path_bar_dispose (GObject *object);
98
99static void caja_path_bar_get_preferred_width (GtkWidget *widget,
100 gint *minimum,
101 gint *natural);
102static void caja_path_bar_get_preferred_height (GtkWidget *widget,
103 gint *minimum,
104 gint *natural);
105
106static void caja_path_bar_unmap (GtkWidget *widget);
107static void caja_path_bar_size_allocate (GtkWidget *widget,
108 GtkAllocation *allocation);
109static void caja_path_bar_add (GtkContainer *container,
110 GtkWidget *widget);
111static void caja_path_bar_remove (GtkContainer *container,
112 GtkWidget *widget);
113static void caja_path_bar_forall (GtkContainer *container,
114 gboolean include_internals,
115 GtkCallback callback,
116 gpointer callback_data);
117static void caja_path_bar_scroll_up (CajaPathBar *path_bar);
118static void caja_path_bar_scroll_down (CajaPathBar *path_bar);
119static gboolean caja_path_bar_scroll (GtkWidget *path_bar,
120 GdkEventScroll *scroll);
121static void caja_path_bar_stop_scrolling (CajaPathBar *path_bar);
122static gboolean caja_path_bar_slider_button_press (GtkWidget *widget,
123 GdkEventButton *event,
124 CajaPathBar *path_bar);
125static gboolean caja_path_bar_slider_button_release (GtkWidget *widget,
126 GdkEventButton *event,
127 CajaPathBar *path_bar);
128static void caja_path_bar_grab_notify (GtkWidget *widget,
129 gboolean was_grabbed);
130static void caja_path_bar_state_flags_changed (GtkWidget *widget,
131 GtkStateFlags previous_state);
132
133static void caja_path_bar_style_updated (GtkWidget *widget);
134
135static void caja_path_bar_screen_changed (GtkWidget *widget,
136 GdkScreen *previous_screen);
137static void caja_path_bar_check_icon_theme (CajaPathBar *path_bar);
138static void caja_path_bar_update_button_appearance (ButtonData *button_data);
139static void caja_path_bar_update_button_state (ButtonData *button_data,
140 gboolean current_dir);
141static gboolean caja_path_bar_update_path (CajaPathBar *path_bar,
142 GFile *file_path,
143 gboolean emit_signal);
144
145
146static GtkWidget *
147get_slider_button (CajaPathBar *path_bar,
148 const gchar *arrow_type)
149{
150 GtkWidget *button;
151
152 button = gtk_button_new ();
153 gtk_widget_set_focus_on_click (button, FALSE(0));
154 gtk_widget_add_events (button, GDK_SCROLL_MASK);
155 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))),
156 gtk_image_new_from_icon_name (arrow_type, GTK_ICON_SIZE_MENU));
157 gtk_container_add (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))), button);
158 gtk_widget_show_all (button);
159
160 return button;
161}
162
163static void
164update_button_types (CajaPathBar *path_bar)
165{
166 GList *list;
167 GFile *path = NULL((void*)0);
168
169 for (list = path_bar->button_list; list; list = list->next)
170 {
171 ButtonData *button_data;
172 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
173 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_data->button)((((GtkToggleButton*) (void *) ((button_data->button)))))))
174 {
175 /*Increase the reference count on path so it does not get cleared
176 *by caja_path_bar_clear_buttons during caja_path_bar_update_path
177 */
178 path = g_object_ref (button_data->path)((__typeof__ (button_data->path)) (g_object_ref) (button_data
->path))
;
179 break;
180 }
181 }
182 if (path != NULL((void*)0))
183 {
184 caja_path_bar_update_path (path_bar, path, TRUE(!(0)));
185 g_object_unref (path);
186 }
187}
188
189
190static void
191desktop_location_changed_callback (gpointer user_data)
192{
193 CajaPathBar *path_bar;
194
195 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
196
197 g_object_unref (path_bar->desktop_path);
198 g_object_unref (path_bar->home_path);
199 path_bar->desktop_path = caja_get_desktop_location ();
200 path_bar->home_path = g_file_new_for_path (g_get_home_dir ());
201 desktop_is_home = g_file_equal (path_bar->home_path, path_bar->desktop_path);
202
203 update_button_types (path_bar);
204}
205
206static void
207trash_state_changed_cb (CajaTrashMonitor *monitor,
208 gboolean state,
209 CajaPathBar *path_bar)
210{
211 GFile *file;
212 GList *list;
213 gint scale;
214
215 file = g_file_new_for_uri ("trash:///");
216 scale = gtk_widget_get_scale_factor (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
217 for (list = path_bar->button_list; list; list = list->next)
218 {
219 ButtonData *button_data;
220 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
221 if (g_file_equal (file, button_data->path))
222 {
223 GIcon *icon;
224 CajaIconInfo *icon_info;
225 cairo_surface_t *surface;
226
227 icon = caja_trash_monitor_get_icon ();
228 icon_info = caja_icon_info_lookup (icon, CAJA_PATH_BAR_ICON_SIZE16, scale);
229 surface = caja_icon_info_get_surface_at_size (icon_info, CAJA_PATH_BAR_ICON_SIZE16);
230 gtk_image_set_from_surface (GTK_IMAGE (button_data->image)((((GtkImage*) (void *) ((button_data->image))))), surface);
231 }
232 }
233 g_object_unref (file);
234}
235
236static gboolean
237slider_timeout (gpointer user_data)
238{
239 CajaPathBar *path_bar;
240
241 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
242
243 path_bar->drag_slider_timeout = 0;
244
245 if (gtk_widget_get_visible (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar)))))))
246 {
247 if (path_bar->drag_slider_timeout_for_up_button)
248 {
249 caja_path_bar_scroll_up (path_bar);
250 }
251 else
252 {
253 caja_path_bar_scroll_down (path_bar);
254 }
255 }
256
257 return FALSE(0);
258}
259
260static void
261caja_path_bar_slider_drag_motion (GtkWidget *widget,
262 GdkDragContext *context,
263 int x,
264 int y,
265 unsigned int time,
266 gpointer user_data)
267{
268 CajaPathBar *path_bar;
269 unsigned int timeout;
270
271 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
272
273 if (path_bar->drag_slider_timeout == 0)
274 {
275 GtkSettings *settings;
276
277 settings = gtk_widget_get_settings (widget);
278
279 g_object_get (settings, "gtk-timeout-expand", &timeout, NULL((void*)0));
280 path_bar->drag_slider_timeout =
281 g_timeout_add (timeout,
282 slider_timeout,
283 path_bar);
284
285 path_bar->drag_slider_timeout_for_up_button =
286 widget == path_bar->up_slider_button;
287 }
288}
289
290static void
291caja_path_bar_slider_drag_leave (GtkWidget *widget,
292 GdkDragContext *context,
293 unsigned int time,
294 gpointer user_data)
295{
296 CajaPathBar *path_bar;
297
298 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
299
300 if (path_bar->drag_slider_timeout != 0)
301 {
302 g_source_remove (path_bar->drag_slider_timeout);
303 path_bar->drag_slider_timeout = 0;
304 }
305}
306
307static void
308caja_path_bar_init (CajaPathBar *path_bar)
309{
310 char *p;
311 GtkStyleContext *context;
312
313 context = gtk_widget_get_style_context (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
314 gtk_style_context_add_class (context, "caja-pathbar");
315
316 gtk_widget_set_has_window (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))), FALSE(0));
317 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))), FALSE(0));
318
319 path_bar->spacing = 3;
320 path_bar->up_slider_button = get_slider_button (path_bar, "pan-start-symbolic");
321 path_bar->down_slider_button = get_slider_button (path_bar, "pan-end-symbolic");
322 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button)))))),
323 "slider-button");
324 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (path_bar->down_slider_button)((((GtkWidget*) (void *) ((path_bar->down_slider_button)))
))
),
325 "slider-button");
326
327 path_bar->icon_size = CAJA_PATH_BAR_ICON_SIZE16;
328
329 p = caja_get_desktop_directory ();
330 path_bar->desktop_path = g_file_new_for_path (p);
331 g_free (p);
332 path_bar->home_path = g_file_new_for_path (g_get_home_dir ());
333 path_bar->root_path = g_file_new_for_path ("/");
334 path_bar->current_path = NULL((void*)0);
335 path_bar->current_button_data = NULL((void*)0);
336
337 desktop_is_home = g_file_equal (path_bar->home_path, path_bar->desktop_path);
338
339 g_signal_connect_swapped (caja_preferences, "changed::" CAJA_PREFERENCES_DESKTOP_IS_HOME_DIR,g_signal_connect_data ((caja_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
340 G_CALLBACK(desktop_location_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
341 path_bar)g_signal_connect_data ((caja_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
;
342
343 g_signal_connect_swapped (path_bar->up_slider_button, "clicked", G_CALLBACK (caja_path_bar_scroll_up), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("clicked"
), (((GCallback) (caja_path_bar_scroll_up))), (path_bar), ((void
*)0), G_CONNECT_SWAPPED)
;
344 g_signal_connect_swapped (path_bar->down_slider_button, "clicked", G_CALLBACK (caja_path_bar_scroll_down), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("clicked"
), (((GCallback) (caja_path_bar_scroll_down))), (path_bar), (
(void*)0), G_CONNECT_SWAPPED)
;
345
346 g_signal_connect (path_bar->up_slider_button, "button_press_event", G_CALLBACK (caja_path_bar_slider_button_press), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("button_press_event"
), (((GCallback) (caja_path_bar_slider_button_press))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
347 g_signal_connect (path_bar->up_slider_button, "button_release_event", G_CALLBACK (caja_path_bar_slider_button_release), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("button_release_event"
), (((GCallback) (caja_path_bar_slider_button_release))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
348 g_signal_connect (path_bar->down_slider_button, "button_press_event", G_CALLBACK (caja_path_bar_slider_button_press), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("button_press_event"
), (((GCallback) (caja_path_bar_slider_button_press))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
349 g_signal_connect (path_bar->down_slider_button, "button_release_event", G_CALLBACK (caja_path_bar_slider_button_release), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("button_release_event"
), (((GCallback) (caja_path_bar_slider_button_release))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
350
351 gtk_drag_dest_set (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button))))),
352 0, NULL((void*)0), 0, 0);
353 gtk_drag_dest_set_track_motion (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button))))), TRUE(!(0)));
354 g_signal_connect (path_bar->up_slider_button,g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
355 "drag-motion",g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
356 G_CALLBACK (caja_path_bar_slider_drag_motion),g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
357 path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
358 g_signal_connect (path_bar->up_slider_button,g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
359 "drag-leave",g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
360 G_CALLBACK (caja_path_bar_slider_drag_leave),g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
361 path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
362
363 gtk_drag_dest_set (GTK_WIDGET (path_bar->down_slider_button)((((GtkWidget*) (void *) ((path_bar->down_slider_button)))
))
,
364 0, NULL((void*)0), 0, 0);
365 gtk_drag_dest_set_track_motion (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button))))), TRUE(!(0)));
366 g_signal_connect (path_bar->down_slider_button,g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
367 "drag-motion",g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
368 G_CALLBACK (caja_path_bar_slider_drag_motion),g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
369 path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
370 g_signal_connect (path_bar->down_slider_button,g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
371 "drag-leave",g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
372 G_CALLBACK (caja_path_bar_slider_drag_leave),g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
373 path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
374
375 g_signal_connect (caja_trash_monitor_get (),g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
376 "trash_state_changed",g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
377 G_CALLBACK (trash_state_changed_cb),g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
378 path_bar)g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
;
379}
380
381static void
382caja_path_bar_class_init (CajaPathBarClass *path_bar_class)
383{
384 GObjectClass *gobject_class;
385 GtkWidgetClass *widget_class;
386 GtkContainerClass *container_class;
387
388 gobject_class = (GObjectClass *) path_bar_class;
389 widget_class = (GtkWidgetClass *) path_bar_class;
390 container_class = (GtkContainerClass *) path_bar_class;
391
392 gobject_class->finalize = caja_path_bar_finalize;
393 gobject_class->dispose = caja_path_bar_dispose;
394
395 widget_class->get_preferred_height = caja_path_bar_get_preferred_height;
396 widget_class->get_preferred_width = caja_path_bar_get_preferred_width;
397
398 widget_class->unmap = caja_path_bar_unmap;
399 widget_class->size_allocate = caja_path_bar_size_allocate;
400 widget_class->style_updated = caja_path_bar_style_updated;
401
402 widget_class->screen_changed = caja_path_bar_screen_changed;
403 widget_class->grab_notify = caja_path_bar_grab_notify;
404 widget_class->state_flags_changed = caja_path_bar_state_flags_changed;
405 widget_class->scroll_event = caja_path_bar_scroll;
406
407 container_class->add = caja_path_bar_add;
408 container_class->forall = caja_path_bar_forall;
409 container_class->remove = caja_path_bar_remove;
410
411 path_bar_signals [PATH_CLICKED] =
412 g_signal_new ("path-clicked",
413 G_OBJECT_CLASS_TYPE (path_bar_class)((((GTypeClass*) (path_bar_class))->g_type)),
414 G_SIGNAL_RUN_FIRST,
415 G_STRUCT_OFFSET (CajaPathBarClass, path_clicked)((glong) __builtin_offsetof(CajaPathBarClass, path_clicked)),
416 NULL((void*)0), NULL((void*)0),
417 g_cclosure_marshal_VOID__OBJECT,
418 G_TYPE_NONE((GType) ((1) << (2))), 1,
419 G_TYPE_FILE(g_file_get_type ()));
420
421 path_bar_signals [PATH_EVENT] =
422 g_signal_new ("path-event",
423 G_OBJECT_CLASS_TYPE (path_bar_class)((((GTypeClass*) (path_bar_class))->g_type)),
424 G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
425 G_STRUCT_OFFSET (CajaPathBarClass, path_event)((glong) __builtin_offsetof(CajaPathBarClass, path_event)),
426 NULL((void*)0), NULL((void*)0), NULL((void*)0),
427 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
428 G_TYPE_FILE(g_file_get_type ()),
429 GDK_TYPE_EVENT(gdk_event_get_type ()));
430
431 gtk_container_class_handle_border_width (container_class);
432}
433
434
435static void
436caja_path_bar_finalize (GObject *object)
437{
438 CajaPathBar *path_bar;
439
440 path_bar = CAJA_PATH_BAR (object)((((CajaPathBar*) (void *) ((object)))));
441
442 caja_path_bar_stop_scrolling (path_bar);
443
444 if (path_bar->drag_slider_timeout != 0)
445 {
446 g_source_remove (path_bar->drag_slider_timeout);
447 path_bar->drag_slider_timeout = 0;
448 }
449
450 g_list_free (path_bar->button_list);
451 if (path_bar->root_path)
452 {
453 g_object_unref (path_bar->root_path);
454 path_bar->root_path = NULL((void*)0);
455 }
456 if (path_bar->home_path)
457 {
458 g_object_unref (path_bar->home_path);
459 path_bar->home_path = NULL((void*)0);
460 }
461 if (path_bar->desktop_path)
462 {
463 g_object_unref (path_bar->desktop_path);
464 path_bar->desktop_path = NULL((void*)0);
465 }
466
467 g_signal_handlers_disconnect_by_func (caja_trash_monitor_get (),g_signal_handlers_disconnect_matched ((caja_trash_monitor_get
()), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (trash_state_changed_cb), (path_bar))
468 trash_state_changed_cb, path_bar)g_signal_handlers_disconnect_matched ((caja_trash_monitor_get
()), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (trash_state_changed_cb), (path_bar))
;
469 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
470 desktop_location_changed_callback,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
471 path_bar)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
;
472
473 G_OBJECT_CLASS (caja_path_bar_parent_class)((((GObjectClass*) (void *) ((caja_path_bar_parent_class)))))->finalize (object);
474}
475
476/* Removes the settings signal handler. It's safe to call multiple times */
477static void
478remove_settings_signal (CajaPathBar *path_bar,
479 GdkScreen *screen)
480{
481 if (path_bar->settings_signal_id)
482 {
483 GtkSettings *settings;
484
485 settings = gtk_settings_get_for_screen (screen);
486 g_signal_handler_disconnect (settings,
487 path_bar->settings_signal_id);
488 path_bar->settings_signal_id = 0;
489 }
490}
491
492static void
493caja_path_bar_dispose (GObject *object)
494{
495 remove_settings_signal (CAJA_PATH_BAR (object)((((CajaPathBar*) (void *) ((object))))), gtk_widget_get_screen (GTK_WIDGET (object)((((GtkWidget*) (void *) ((object)))))));
496
497 G_OBJECT_CLASS (caja_path_bar_parent_class)((((GObjectClass*) (void *) ((caja_path_bar_parent_class)))))->dispose (object);
498}
499
500/* Size requisition:
501 *
502 * Ideally, our size is determined by another widget, and we are just filling
503 * available space.
504 */
505
506static void
507caja_path_bar_get_preferred_width (GtkWidget *widget,
508 gint *minimum,
509 gint *natural)
510{
511 CajaPathBar *path_bar;
512 GList *list;
513 gint child_height;
514 gint height;
515 gint child_min, child_nat;
516 gint slider_width;
517 ButtonData *button_data = NULL((void*)0);
518
519 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
520
521 *minimum = *natural = 0;
522 height = 0;
523
524 for (list = path_bar->button_list; list; list = list->next) {
525 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
526 gtk_widget_get_preferred_width (button_data->button, &child_min, &child_nat);
527 gtk_widget_get_preferred_height (button_data->button, &child_height, NULL((void*)0));
528 height = MAX (height, child_height)(((height) > (child_height)) ? (height) : (child_height));
529
530 if (button_data->type == NORMAL_BUTTON) {
531 /* Use 2*Height as button width because of ellipsized label. */
532 child_min = MAX (child_min, child_height * 2)(((child_min) > (child_height * 2)) ? (child_min) : (child_height
* 2))
;
533 child_nat = MAX (child_min, child_height * 2)(((child_min) > (child_height * 2)) ? (child_min) : (child_height
* 2))
;
534 }
535
536 *minimum = MAX (*minimum, child_min)(((*minimum) > (child_min)) ? (*minimum) : (child_min));
537 *natural = MAX (*natural, child_nat)(((*natural) > (child_nat)) ? (*natural) : (child_nat));
538 }
539
540 /* Add space for slider, if we have more than one path */
541 /* Theoretically, the slider could be bigger than the other button. But we're
542 * not going to worry about that now.
543 */
544 gtk_widget_get_preferred_width (path_bar->down_slider_button,
545 &slider_width,
546 NULL((void*)0));
547 gtk_widget_get_preferred_width (path_bar->up_slider_button,
548 &slider_width,
549 NULL((void*)0));
550
551
552 if (path_bar->button_list) {
553 *minimum += (path_bar->spacing + slider_width) * 2;
554 *natural += (path_bar->spacing + slider_width) * 2;
555 }
556 /*Let's keep the rest of this as it was */
557 path_bar->slider_width = slider_width;
558}
559
560static void
561caja_path_bar_get_preferred_height (GtkWidget *widget,
562 gint *minimum,
563 gint *natural)
564{
565 CajaPathBar *path_bar;
566 GList *list;
567 gint child_min, child_nat;
568 ButtonData *button_data = NULL((void*)0);
569
570 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
571
572 *minimum = *natural = 0;
573
574 for (list = path_bar->button_list; list; list = list->next) {
575 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
576 gtk_widget_get_preferred_height (button_data->button, &child_min, &child_nat);
577
578 *minimum = MAX (*minimum, child_min)(((*minimum) > (child_min)) ? (*minimum) : (child_min));
579 *natural = MAX (*natural, child_nat)(((*natural) > (child_nat)) ? (*natural) : (child_nat));
580 }
581}
582
583static void
584caja_path_bar_update_slider_buttons (CajaPathBar *path_bar)
585{
586 if (path_bar->button_list)
587 {
588
589 GtkWidget *button;
590
591 button = BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button;
592 if (gtk_widget_get_child_visible (button))
593 {
594 gtk_widget_set_sensitive (path_bar->down_slider_button, FALSE(0));
595 }
596 else
597 {
598 gtk_widget_set_sensitive (path_bar->down_slider_button, TRUE(!(0)));
599 }
600 button = BUTTON_DATA (g_list_last (path_bar->button_list)->data)((ButtonData *)(g_list_last (path_bar->button_list)->data
))
->button;
601 if (gtk_widget_get_child_visible (button))
602 {
603 gtk_widget_set_sensitive (path_bar->up_slider_button, FALSE(0));
604 }
605 else
606 {
607 gtk_widget_set_sensitive (path_bar->up_slider_button, TRUE(!(0)));
608 }
609 }
610}
611
612static void
613caja_path_bar_unmap (GtkWidget *widget)
614{
615 caja_path_bar_stop_scrolling (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
616
617 GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->unmap (widget);
618}
619
620/* This is a tad complicated */
621static void
622caja_path_bar_size_allocate (GtkWidget *widget,
623 GtkAllocation *allocation)
624{
625 GtkWidget *child;
626 CajaPathBar *path_bar;
627 GtkTextDirection direction;
628 GtkAllocation child_allocation;
629 GList *list, *first_button;
630 gint width;
631 gint allocation_width;
632 gboolean need_sliders;
633 gint up_slider_offset;
634 gint down_slider_offset;
635 GtkRequisition child_requisition;
636 GtkAllocation widget_allocation;
637
638 need_sliders = TRUE(!(0));
639 up_slider_offset = 0;
640 down_slider_offset = 0;
641 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
642
643 gtk_widget_set_allocation (widget, allocation);
644
645 /* No path is set so we don't have to allocate anything. */
646 if (path_bar->button_list == NULL((void*)0))
1
Assuming field 'button_list' is not equal to NULL
2
Taking false branch
647 {
648 return;
649 }
650 direction = gtk_widget_get_direction (widget);
651
652 allocation_width = allocation->width;
653
654 /* First, we check to see if we need the scrollbars. */
655 if (path_bar->fake_root)
3
Assuming field 'fake_root' is null
4
Taking false branch
656 {
657 width = path_bar->spacing + path_bar->slider_width;
658 }
659 else
660 {
661 width = 0;
662 }
663
664 gtk_widget_get_preferred_size (BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button,
665 &child_requisition, NULL((void*)0));
666 width += child_requisition.width;
667
668 for (list = path_bar->button_list->next; list; list = list->next)
5
Loop condition is false. Execution continues on line 680
669 {
670 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
671 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
672 width += child_requisition.width + path_bar->spacing;
673
674 if (list == path_bar->fake_root)
675 {
676 break;
677 }
678 }
679
680 if (width <= allocation_width)
6
Assuming 'width' is <= 'allocation_width'
7
Taking true branch
681 {
682 if (path_bar->fake_root
7.1
Field 'fake_root' is null
)
8
Taking false branch
683 {
684 first_button = path_bar->fake_root;
685 }
686 else
687 {
688 first_button = g_list_last (path_bar->button_list);
9
Value assigned to 'first_button'
689 }
690 }
691 else
692 {
693 gboolean reached_end;
694 gint slider_space;
695 reached_end = FALSE(0);
696 slider_space = 2 * (path_bar->spacing + path_bar->slider_width);
697
698 if (path_bar->first_scrolled_button)
699 {
700 first_button = path_bar->first_scrolled_button;
701 }
702 else
703 {
704 first_button = path_bar->button_list;
705 }
706
707 need_sliders = TRUE(!(0));
708 /* To see how much space we have, and how many buttons we can display.
709 * We start at the first button, count forward until hit the new
710 * button, then count backwards.
711 */
712 /* Count down the path chain towards the end. */
713 gtk_widget_get_preferred_size (BUTTON_DATA (first_button->data)((ButtonData *)(first_button->data))->button,
714 &child_requisition, NULL((void*)0));
715 width = child_requisition.width;
716 list = first_button->prev;
717 while (list && !reached_end)
718 {
719 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
720 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
721
722 if (width + child_requisition.width + path_bar->spacing + slider_space > allocation_width)
723 {
724 reached_end = TRUE(!(0));
725 }
726 else
727 {
728 if (list == path_bar->fake_root)
729 {
730 break;
731 }
732 else
733 {
734 width += child_requisition.width + path_bar->spacing;
735 }
736 }
737
738 list = list->prev;
739 }
740
741 /* Finally, we walk up, seeing how many of the previous buttons we can add*/
742
743 while (first_button->next && ! reached_end)
744 {
745 child = BUTTON_DATA (first_button->next->data)((ButtonData *)(first_button->next->data))->button;
746 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
747
748 if (width + child_requisition.width + path_bar->spacing + slider_space > allocation_width)
749 {
750 reached_end = TRUE(!(0));
751 }
752 else
753 {
754 width += child_requisition.width + path_bar->spacing;
755 if (first_button == path_bar->fake_root)
756 {
757 break;
758 }
759 first_button = first_button->next;
760 }
761 }
762 }
763
764 /* Now, we allocate space to the buttons */
765 child_allocation.y = allocation->y;
766 child_allocation.height = allocation->height;
767
768 if (direction == GTK_TEXT_DIR_RTL)
10
Assuming 'direction' is not equal to GTK_TEXT_DIR_RTL
11
Taking false branch
769 {
770 child_allocation.x = allocation->x + allocation->width;
771
772 if (need_sliders || path_bar->fake_root)
773 {
774 child_allocation.x -= (path_bar->spacing + path_bar->slider_width);
775 up_slider_offset = allocation->width - path_bar->slider_width;
776
777 }
778 }
779 else
780 {
781 child_allocation.x = allocation->x;
782
783 if (need_sliders
11.1
'need_sliders' is 1
|| path_bar->fake_root)
784 {
785 up_slider_offset = 0;
786 child_allocation.x += (path_bar->spacing + path_bar->slider_width);
787 }
788 }
789
790 for (list = first_button; list; list = list->prev)
12
Assuming pointer value is null
13
Loop condition is false. Execution continues on line 839
791 {
792 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
793 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
794
795 gtk_widget_get_allocation (widget, &widget_allocation);
796
797 child_allocation.width = child_requisition.width;
798 if (direction == GTK_TEXT_DIR_RTL)
799 {
800 child_allocation.x -= child_allocation.width;
801 }
802 /* Check to see if we've don't have any more space to allocate buttons */
803 if (need_sliders && direction == GTK_TEXT_DIR_RTL)
804 {
805 if (child_allocation.x - path_bar->spacing - path_bar->slider_width < widget_allocation.x)
806 {
807 break;
808 }
809 }
810 else
811 {
812 if (need_sliders && direction == GTK_TEXT_DIR_LTR)
813 {
814 if (child_allocation.x + child_allocation.width + path_bar->spacing + path_bar->slider_width > widget_allocation.x + allocation_width)
815
816 {
817 break;
818 }
819 }
820 }
821
822 gtk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, TRUE(!(0)));
823 gtk_widget_size_allocate (child, &child_allocation);
824
825 if (direction == GTK_TEXT_DIR_RTL)
826 {
827 child_allocation.x -= path_bar->spacing;
828 down_slider_offset = child_allocation.x - allocation->x - path_bar->slider_width;
829 }
830 else
831 {
832 down_slider_offset = child_allocation.x - widget_allocation.x;
833 down_slider_offset += child_allocation.width + path_bar->spacing;
834
835 child_allocation.x += child_allocation.width + path_bar->spacing;
836 }
837 }
838 /* Now we go hide all the widgets that don't fit */
839 while (list)
14
Loop condition is false. Execution continues on line 844
840 {
841 gtk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, FALSE(0));
842 list = list->prev;
843 }
844 for (list = first_button->next; list; list = list->next)
15
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'first_button')
845 {
846 gtk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, FALSE(0));
847 }
848
849 if (need_sliders || path_bar->fake_root)
850 {
851 child_allocation.width = path_bar->slider_width;
852 child_allocation.x = up_slider_offset + allocation->x;
853 gtk_widget_size_allocate (path_bar->up_slider_button, &child_allocation);
854
855 gtk_widget_set_child_visible (path_bar->up_slider_button, TRUE(!(0)));
856 gtk_widget_show_all (path_bar->up_slider_button);
857 }
858 else
859 {
860 gtk_widget_set_child_visible (path_bar->up_slider_button, FALSE(0));
861 }
862
863 if (need_sliders)
864 {
865 child_allocation.width = path_bar->slider_width;
866 child_allocation.x = down_slider_offset + allocation->x;
867 gtk_widget_size_allocate (path_bar->down_slider_button, &child_allocation);
868
869 gtk_widget_set_child_visible (path_bar->down_slider_button, TRUE(!(0)));
870 gtk_widget_show_all (path_bar->down_slider_button);
871 caja_path_bar_update_slider_buttons (path_bar);
872 }
873 else
874 {
875 gtk_widget_set_child_visible (path_bar->down_slider_button, FALSE(0));
876 }
877}
878
879static void
880caja_path_bar_style_updated (GtkWidget *widget)
881{
882 if (GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->style_updated)
883 {
884 GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->style_updated (widget);
885 }
886
887 caja_path_bar_check_icon_theme (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
888}
889
890static void
891caja_path_bar_screen_changed (GtkWidget *widget,
892 GdkScreen *previous_screen)
893{
894 if (GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->screen_changed)
895 {
896 GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->screen_changed (widget, previous_screen);
897 }
898 /* We might nave a new settings, so we remove the old one */
899 if (previous_screen)
900 {
901 remove_settings_signal (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))), previous_screen);
902 }
903 caja_path_bar_check_icon_theme (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
904}
905
906static gboolean
907caja_path_bar_scroll (GtkWidget *widget,
908 GdkEventScroll *event)
909{
910 CajaPathBar *path_bar;
911
912 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
913
914 switch (event->direction)
915 {
916 case GDK_SCROLL_RIGHT:
917 case GDK_SCROLL_DOWN:
918 caja_path_bar_scroll_down (path_bar);
919 return TRUE(!(0));
920
921 case GDK_SCROLL_LEFT:
922 case GDK_SCROLL_UP:
923 caja_path_bar_scroll_up (path_bar);
924 return TRUE(!(0));
925
926 case GDK_SCROLL_SMOOTH:
927 break;
928 }
929
930 return FALSE(0);
931}
932
933
934static void
935caja_path_bar_add (GtkContainer *container,
936 GtkWidget *widget)
937{
938 gtk_widget_set_parent (widget, GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
939}
940
941static void
942caja_path_bar_remove_1 (GtkContainer *container,
943 GtkWidget *widget)
944{
945 gboolean was_visible = gtk_widget_get_visible (widget);
946 gtk_widget_unparent (widget);
947 if (was_visible)
948 {
949 gtk_widget_queue_resize (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
950 }
951}
952
953static void
954caja_path_bar_remove (GtkContainer *container,
955 GtkWidget *widget)
956{
957 CajaPathBar *path_bar;
958 GList *children;
959
960 path_bar = CAJA_PATH_BAR (container)((((CajaPathBar*) (void *) ((container)))));
961
962 if (widget == path_bar->up_slider_button)
963 {
964 caja_path_bar_remove_1 (container, widget);
965 path_bar->up_slider_button = NULL((void*)0);
966 return;
967 }
968
969 if (widget == path_bar->down_slider_button)
970 {
971 caja_path_bar_remove_1 (container, widget);
972 path_bar->down_slider_button = NULL((void*)0);
973 return;
974 }
975
976 children = path_bar->button_list;
977 while (children)
978 {
979 if (widget == BUTTON_DATA (children->data)((ButtonData *)(children->data))->button)
980 {
981 caja_path_bar_remove_1 (container, widget);
982 path_bar->button_list = g_list_remove_link (path_bar->button_list, children);
983 g_list_free_1 (children);
984 return;
985 }
986 children = children->next;
987 }
988}
989
990static void
991caja_path_bar_forall (GtkContainer *container,
992 gboolean include_internals,
993 GtkCallback callback,
994 gpointer callback_data)
995{
996 CajaPathBar *path_bar;
997 GList *children;
998
999 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (callback != ((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__)), "callback != NULL"
); return; } } while (0)
;
1000 path_bar = CAJA_PATH_BAR (container)((((CajaPathBar*) (void *) ((container)))));
1001
1002 children = path_bar->button_list;
1003 while (children)
1004 {
1005 GtkWidget *child;
1006 child = BUTTON_DATA (children->data)((ButtonData *)(children->data))->button;
1007 children = children->next;
1008 (* callback) (child, callback_data);
1009 }
1010
1011 if (path_bar->up_slider_button)
1012 {
1013 (* callback) (path_bar->up_slider_button, callback_data);
1014 }
1015
1016 if (path_bar->down_slider_button)
1017 {
1018 (* callback) (path_bar->down_slider_button, callback_data);
1019 }
1020}
1021
1022static void
1023caja_path_bar_scroll_down (CajaPathBar *path_bar)
1024{
1025 GList *list;
1026 GList *down_button;
1027 GList *up_button;
1028 gint space_available;
1029 gint space_needed;
1030 GtkTextDirection direction;
1031 GtkAllocation allocation, button_allocation, slider_allocation;
1032
1033 down_button = NULL((void*)0);
1034 up_button = NULL((void*)0);
1035
1036 if (path_bar->ignore_click)
1037 {
1038 path_bar->ignore_click = FALSE(0);
1039 return;
1040 }
1041
1042 gtk_widget_queue_resize (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
1043
1044 direction = gtk_widget_get_direction (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
1045
1046 /* We find the button at the 'down' end that we have to make */
1047 /* visible */
1048 for (list = path_bar->button_list; list; list = list->next)
1049 {
1050 if (list->next && gtk_widget_get_child_visible (BUTTON_DATA (list->next->data)((ButtonData *)(list->next->data))->button))
1051 {
1052 down_button = list;
1053 break;
1054 }
1055 }
1056
1057 if (down_button == NULL((void*)0))
1058 {
1059 return;
1060 }
1061
1062 /* Find the last visible button on the 'up' end */
1063 for (list = g_list_last (path_bar->button_list); list; list = list->prev)
1064 {
1065 if (gtk_widget_get_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button))
1066 {
1067 up_button = list;
1068 break;
1069 }
1070 }
1071
1072 gtk_widget_get_allocation (BUTTON_DATA (down_button->data)((ButtonData *)(down_button->data))->button, &button_allocation);
1073 gtk_widget_get_allocation (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))), &allocation);
1074 gtk_widget_get_allocation (path_bar->down_slider_button, &slider_allocation);
1075
1076 space_needed = button_allocation.width + path_bar->spacing;
1077 if (direction == GTK_TEXT_DIR_RTL)
1078 {
1079 space_available = slider_allocation.x - allocation.x;
1080 }
1081 else
1082 {
1083 space_available = (allocation.x + allocation.width) -
1084 (slider_allocation.x + slider_allocation.width);
1085 }
1086
1087 /* We have space_available extra space that's not being used. We
1088 * need space_needed space to make the button fit. So we walk down
1089 * from the end, removing buttons until we get all the space we
1090 * need. */
1091 gtk_widget_get_allocation (BUTTON_DATA (up_button->data)((ButtonData *)(up_button->data))->button, &button_allocation);
1092 while (space_available < space_needed && up_button)
1093 {
1094 space_available += button_allocation.width + path_bar->spacing;
1095 up_button = up_button->prev;
1096 path_bar->first_scrolled_button = up_button;
1097 }
1098}
1099
1100static void
1101caja_path_bar_scroll_up (CajaPathBar *path_bar)
1102{
1103 GList *list;
1104
1105 if (path_bar->ignore_click)
1106 {
1107 path_bar->ignore_click = FALSE(0);
1108 return;
1109 }
1110
1111 gtk_widget_queue_resize (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
1112
1113 for (list = g_list_last (path_bar->button_list); list; list = list->prev)
1114 {
1115 if (list->prev && gtk_widget_get_child_visible (BUTTON_DATA (list->prev->data)((ButtonData *)(list->prev->data))->button))
1116 {
1117 if (list->prev == path_bar->fake_root)
1118 {
1119 path_bar->fake_root = NULL((void*)0);
1120 }
1121 path_bar->first_scrolled_button = list;
1122 return;
1123 }
1124 }
1125}
1126
1127static gboolean
1128caja_path_bar_scroll_timeout (CajaPathBar *path_bar)
1129{
1130 gboolean retval = FALSE(0);
1131
1132 if (path_bar->timer)
1133 {
1134 if (gtk_widget_has_focus (path_bar->up_slider_button))
1135 {
1136 caja_path_bar_scroll_up (path_bar);
1137 }
1138 else
1139 {
1140 if (gtk_widget_has_focus (path_bar->down_slider_button))
1141 {
1142 caja_path_bar_scroll_down (path_bar);
1143 }
1144 }
1145 if (path_bar->need_timer)
1146 {
1147 path_bar->need_timer = FALSE(0);
1148
1149 path_bar->timer = g_timeout_add (SCROLL_TIMEOUT150,
1150 (GSourceFunc)caja_path_bar_scroll_timeout,
1151 path_bar);
1152
1153 }
1154 else
1155 {
1156 retval = TRUE(!(0));
1157 }
1158 }
1159
1160 return retval;
1161}
1162
1163static void
1164caja_path_bar_stop_scrolling (CajaPathBar *path_bar)
1165{
1166 if (path_bar->timer)
1167 {
1168 g_source_remove (path_bar->timer);
1169 path_bar->timer = 0;
1170 path_bar->need_timer = FALSE(0);
1171 }
1172}
1173
1174static gboolean
1175caja_path_bar_slider_button_press (GtkWidget *widget,
1176 GdkEventButton *event,
1177 CajaPathBar *path_bar)
1178{
1179 if (!gtk_widget_has_focus (widget))
1180 {
1181 gtk_widget_grab_focus (widget);
1182 }
1183
1184 if (event->type != GDK_BUTTON_PRESS || event->button != 1)
1185 {
1186 return FALSE(0);
1187 }
1188
1189 path_bar->ignore_click = FALSE(0);
1190
1191 if (widget == path_bar->up_slider_button)
1192 {
1193 caja_path_bar_scroll_up (path_bar);
1194 }
1195 else
1196 {
1197 if (widget == path_bar->down_slider_button)
1198 {
1199 caja_path_bar_scroll_down (path_bar);
1200 }
1201 }
1202
1203 if (!path_bar->timer)
1204 {
1205 path_bar->need_timer = TRUE(!(0));
1206 path_bar->timer = g_timeout_add (INITIAL_SCROLL_TIMEOUT300,
1207 (GSourceFunc)caja_path_bar_scroll_timeout,
1208 path_bar);
1209 }
1210
1211 return FALSE(0);
1212}
1213
1214static gboolean
1215caja_path_bar_slider_button_release (GtkWidget *widget,
1216 GdkEventButton *event,
1217 CajaPathBar *path_bar)
1218{
1219 if (event->type != GDK_BUTTON_RELEASE)
1220 {
1221 return FALSE(0);
1222 }
1223
1224 path_bar->ignore_click = TRUE(!(0));
1225 caja_path_bar_stop_scrolling (path_bar);
1226
1227 return FALSE(0);
1228}
1229
1230static void
1231caja_path_bar_grab_notify (GtkWidget *widget,
1232 gboolean was_grabbed)
1233{
1234 if (!was_grabbed)
1235 {
1236 caja_path_bar_stop_scrolling (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
1237 }
1238}
1239
1240static void
1241caja_path_bar_state_flags_changed (GtkWidget *widget,
1242 GtkStateFlags previous_state)
1243{
1244 if (!gtk_widget_get_sensitive (widget))
1245 {
1246 caja_path_bar_stop_scrolling (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
1247 }
1248}
1249
1250
1251
1252/* Changes the icons wherever it is needed */
1253static void
1254reload_icons (CajaPathBar *path_bar)
1255{
1256 GList *list;
1257
1258 for (list = path_bar->button_list; list; list = list->next)
1259 {
1260 ButtonData *button_data;
1261
1262 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
1263 if (button_data->type != NORMAL_BUTTON || button_data->is_base_dir)
1264 {
1265 caja_path_bar_update_button_appearance (button_data);
1266 }
1267
1268 }
1269}
1270
1271static void
1272change_icon_theme (CajaPathBar *path_bar)
1273{
1274 path_bar->icon_size = CAJA_PATH_BAR_ICON_SIZE16;
1275 reload_icons (path_bar);
1276}
1277
1278/* Callback used when a GtkSettings value changes */
1279static void
1280settings_notify_cb (GObject *object,
1281 GParamSpec *pspec,
1282 CajaPathBar *path_bar)
1283{
1284 const char *name;
1285
1286 name = g_param_spec_get_name (pspec);
1287
1288 if (! strcmp (name, "gtk-icon-theme-name") || ! strcmp (name, "gtk-icon-sizes"))
1289 {
1290 change_icon_theme (path_bar);
1291 }
1292}
1293
1294static void
1295caja_path_bar_check_icon_theme (CajaPathBar *path_bar)
1296{
1297 GtkSettings *settings;
1298
1299 if (path_bar->settings_signal_id)
1300 {
1301 return;
1302 }
1303
1304 settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar)))))));
1305 path_bar->settings_signal_id = g_signal_connect (settings, "notify", G_CALLBACK (settings_notify_cb), path_bar)g_signal_connect_data ((settings), ("notify"), (((GCallback) (
settings_notify_cb))), (path_bar), ((void*)0), (GConnectFlags
) 0)
;
1306
1307 change_icon_theme (path_bar);
1308}
1309
1310/* Public functions and their helpers */
1311void
1312caja_path_bar_clear_buttons (CajaPathBar *path_bar)
1313{
1314 while (path_bar->button_list != NULL((void*)0))
1315 {
1316 gtk_container_remove (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))), BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button);
1317 }
1318 path_bar->first_scrolled_button = NULL((void*)0);
1319 path_bar->fake_root = NULL((void*)0);
1320}
1321
1322static void
1323button_clicked_cb (GtkWidget *button,
1324 gpointer data)
1325{
1326 ButtonData *button_data;
1327 CajaPathBar *path_bar;
1328 GList *button_list;
1329
1330 button_data = BUTTON_DATA (data)((ButtonData *)(data));
1331 if (button_data->ignore_changes)
1332 {
1333 return;
1334 }
1335
1336 path_bar = CAJA_PATH_BAR (gtk_widget_get_parent (button))((((CajaPathBar*) (void *) ((gtk_widget_get_parent (button)))
)))
;
1337
1338 button_list = g_list_find (path_bar->button_list, button_data);
1339 g_assert (button_list != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (button_list != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-pathbar.c", 1339, ((const char*) (__func__
)), "button_list != NULL"); } while (0)
;
1340
1341 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))), TRUE(!(0)));
1342
1343 g_signal_emit (path_bar, path_bar_signals [PATH_CLICKED], 0, button_data->path);
1344}
1345
1346static gboolean
1347button_event_cb (GtkWidget *button,
1348 GdkEventButton *event,
1349 gpointer data)
1350{
1351 ButtonData *button_data;
1352 CajaPathBar *path_bar;
1353 GList *button_list;
1354 gboolean retval;
1355
1356 button_data = BUTTON_DATA (data)((ButtonData *)(data));
1357 path_bar = CAJA_PATH_BAR (gtk_widget_get_parent (button))((((CajaPathBar*) (void *) ((gtk_widget_get_parent (button)))
)))
;
1358
1359 if (event->type == GDK_BUTTON_PRESS) {
1360 g_object_set_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "handle-button-release",
1361 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
1362 }
1363
1364 if (event->type == GDK_BUTTON_RELEASE &&
1365 !GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button),((guint) (gulong) (g_object_get_data (((((GObject*) (void *) (
(button))))), "handle-button-release")))
1366 "handle-button-release"))((guint) (gulong) (g_object_get_data (((((GObject*) (void *) (
(button))))), "handle-button-release")))
) {
1367 return FALSE(0);
1368 }
1369
1370 button_list = g_list_find (path_bar->button_list, button_data);
1371 g_assert (button_list != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (button_list != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-pathbar.c", 1371, ((const char*) (__func__
)), "button_list != NULL"); } while (0)
;
1372
1373 g_signal_emit (path_bar, path_bar_signals [PATH_EVENT], 0, button_data->path, event, &retval);
1374
1375 return retval;
1376}
1377
1378static void
1379button_drag_begin_cb (GtkWidget *widget,
1380 GdkDragContext *drag_context,
1381 gpointer user_data)
1382{
1383 g_object_set_data (G_OBJECT (widget)((((GObject*) (void *) ((widget))))), "handle-button-release",
1384 GINT_TO_POINTER (FALSE)((gpointer) (glong) ((0))));
1385}
1386
1387
1388static CajaIconInfo *
1389get_type_icon_info (ButtonData *button_data)
1390{
1391 gint icon_scale = gtk_widget_get_scale_factor (GTK_WIDGET (button_data->button)((((GtkWidget*) (void *) ((button_data->button))))));
1392
1393 switch (button_data->type)
1394 {
1395 case ROOT_BUTTON:
1396 return caja_icon_info_lookup_from_name (CAJA_ICON_FILESYSTEM"drive-harddisk",
1397 CAJA_PATH_BAR_ICON_SIZE16,
1398 icon_scale);
1399
1400 case HOME_BUTTON:
1401 return caja_icon_info_lookup_from_name (CAJA_ICON_HOME"user-home",
1402 CAJA_PATH_BAR_ICON_SIZE16,
1403 icon_scale);
1404
1405 case DESKTOP_BUTTON:
1406 return caja_icon_info_lookup_from_name (CAJA_ICON_DESKTOP"user-desktop",
1407 CAJA_PATH_BAR_ICON_SIZE16,
1408 icon_scale);
1409
1410 case NORMAL_BUTTON:
1411 if (button_data->is_base_dir)
1412 {
1413 return caja_file_get_icon (button_data->file,
1414 CAJA_PATH_BAR_ICON_SIZE16, icon_scale,
1415 CAJA_FILE_ICON_FLAGS_NONE);
1416 }
1417
1418 default:
1419 return NULL((void*)0);
1420 }
1421
1422 return NULL((void*)0);
1423}
1424
1425static void
1426button_data_free (ButtonData *button_data)
1427{
1428 g_object_unref (button_data->path);
1429 g_free (button_data->dir_name);
1430 if (button_data->custom_icon)
1431 {
1432 cairo_surface_destroy (button_data->custom_icon);
1433 }
1434 if (button_data->file != NULL((void*)0))
1435 {
1436 g_signal_handler_disconnect (button_data->file,
1437 button_data->file_changed_signal_id);
1438 caja_file_monitor_remove (button_data->file, button_data);
1439 caja_file_unref (button_data->file);
1440 }
1441
1442 g_object_unref (button_data->drag_info.target_location);
1443 button_data->drag_info.target_location = NULL((void*)0);
1444
1445 g_free (button_data);
1446}
1447
1448static const char *
1449get_dir_name (ButtonData *button_data)
1450{
1451 if (button_data->type == DESKTOP_BUTTON)
1452 {
1453 return _("Desktop")dcgettext (((void*)0), "Desktop", 5);
1454 }
1455 else
1456 {
1457 return button_data->dir_name;
1458 }
1459}
1460
1461/* We always want to request the same size for the label, whether
1462 * or not the contents are bold
1463 */
1464static void
1465set_label_padding_size (ButtonData *button_data)
1466{
1467 const gchar *dir_name = get_dir_name (button_data);
1468 PangoLayout *layout;
1469 gint width, height, bold_width, bold_height;
1470 gint pad_left, pad_right;
1471 gchar *markup;
1472
1473 layout = gtk_widget_create_pango_layout (button_data->label, dir_name);
1474 pango_layout_get_pixel_size (layout, &width, &height);
1475
1476 markup = g_markup_printf_escaped ("<b>%s</b>", dir_name);
1477 pango_layout_set_markup (layout, markup, -1);
1478 g_free (markup);
1479
1480 pango_layout_get_pixel_size (layout, &bold_width, &bold_height);
1481
1482 pad_left = (bold_width - width) / 2;
1483 pad_right = (bold_width + 1 - width) / 2; /* this ensures rounding up - the
1484 pixel size difference between bold and normal fonts is not always even and
1485 will give an off-by-one error when dividing by 2 */
1486
1487 gtk_widget_set_margin_start (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), pad_left);
1488 gtk_widget_set_margin_end (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), pad_right);
1489
1490 g_object_unref (layout);
1491}
1492
1493static void
1494caja_path_bar_update_button_appearance (ButtonData *button_data)
1495{
1496 const gchar *dir_name = get_dir_name (button_data);
1497
1498 if (button_data->label != NULL((void*)0))
1499 {
1500 if (gtk_label_get_use_markup (GTK_LABEL (button_data->label)((((GtkLabel*) (void *) ((button_data->label)))))))
1501 {
1502 char *markup;
1503
1504 markup = g_markup_printf_escaped ("<b>%s</b>", dir_name);
1505 gtk_label_set_markup (GTK_LABEL (button_data->label)((((GtkLabel*) (void *) ((button_data->label))))), markup);
1506
1507 gtk_widget_set_margin_end (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), 0);
1508 gtk_widget_set_margin_start (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), 0);
1509 g_free(markup);
1510 }
1511 else
1512 {
1513 gtk_label_set_text (GTK_LABEL (button_data->label)((((GtkLabel*) (void *) ((button_data->label))))), dir_name);
1514 set_label_padding_size (button_data);
1515 }
1516 }
1517
1518 if (button_data->image != NULL((void*)0))
1519 {
1520 if (button_data->custom_icon)
1521 {
1522 gtk_image_set_from_surface (GTK_IMAGE (button_data->image)((((GtkImage*) (void *) ((button_data->image))))), button_data->custom_icon);
1523 gtk_widget_show (GTK_WIDGET (button_data->image)((((GtkWidget*) (void *) ((button_data->image))))));
1524 }
1525 else
1526 {
1527 CajaIconInfo *icon_info;
1528 cairo_surface_t *surface;
1529
1530 icon_info = get_type_icon_info (button_data);
1531 surface = NULL((void*)0);
1532
1533 if (icon_info != NULL((void*)0))
1534 {
1535 surface = caja_icon_info_get_surface_at_size (icon_info, CAJA_PATH_BAR_ICON_SIZE16);
1536 g_object_unref (icon_info);
1537 }
1538
1539 if (surface != NULL((void*)0))
1540 {
1541 gtk_image_set_from_surface (GTK_IMAGE (button_data->image)((((GtkImage*) (void *) ((button_data->image))))), surface);
1542 gtk_style_context_add_class (gtk_widget_get_style_context (button_data->button),
1543 "image-button");
1544 gtk_widget_show (GTK_WIDGET (button_data->image)((((GtkWidget*) (void *) ((button_data->image))))));
1545 cairo_surface_destroy (surface);
1546 }
1547 else
1548 {
1549 gtk_widget_hide (GTK_WIDGET (button_data->image)((((GtkWidget*) (void *) ((button_data->image))))));
1550 gtk_style_context_remove_class (gtk_widget_get_style_context (button_data->button),
1551 "image-button");
1552 }
1553 }
1554 }
1555
1556}
1557
1558static void
1559caja_path_bar_update_button_state (ButtonData *button_data,
1560 gboolean current_dir)
1561{
1562 if (button_data->label != NULL((void*)0))
1563 {
1564 g_object_set (button_data->label, "use-markup", current_dir, NULL((void*)0));
1565 }
1566
1567 caja_path_bar_update_button_appearance (button_data);
1568
1569 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_data->button)((((GtkToggleButton*) (void *) ((button_data->button)))))) != current_dir)
1570 {
1571 button_data->ignore_changes = TRUE(!(0));
1572 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_data->button)((((GtkToggleButton*) (void *) ((button_data->button))))), current_dir);
1573 button_data->ignore_changes = FALSE(0);
1574 }
1575}
1576
1577static gboolean
1578setup_file_path_mounted_mount (GFile *location, ButtonData *button_data)
1579{
1580 GVolumeMonitor *volume_monitor;
1581 GList *mounts, *l;
1582 gboolean result;
1583 GIcon *icon;
1584 CajaIconInfo *info;
1585 GFile *root, *default_location;
1586 gint scale;
1587 GMount *mount = NULL((void*)0);
1588
1589 /* Return false if button has not been set up yet or has been destroyed*/
1590 if (!button_data->button)
1591 return FALSE(0);
1592 result = FALSE(0);
1593 volume_monitor = g_volume_monitor_get ();
1594 mounts = g_volume_monitor_get_mounts (volume_monitor);
1595
1596 scale = gtk_widget_get_scale_factor (GTK_WIDGET (button_data->button)((((GtkWidget*) (void *) ((button_data->button))))));
1597 for (l = mounts; l != NULL((void*)0); l = l->next)
1598 {
1599 mount = l->data;
1600 if (g_mount_is_shadowed (mount))
1601 {
1602 continue;
1603 }
1604 if (result)
1605 {
1606 continue;
1607 }
1608 root = g_mount_get_root (mount);
1609 if (g_file_equal (location, root))
1610 {
1611 result = TRUE(!(0));
1612 /* set mount specific details in button_data */
1613 icon = g_mount_get_icon (mount);
1614 if (icon == NULL((void*)0))
1615 {
1616 icon = g_themed_icon_new (CAJA_ICON_FOLDER"folder");
1617 }
1618 info = caja_icon_info_lookup (icon, CAJA_PATH_BAR_ICON_SIZE16, scale);
1619 g_object_unref (icon);
1620 button_data->custom_icon = caja_icon_info_get_surface_at_size (info, CAJA_PATH_BAR_ICON_SIZE16);
1621 g_object_unref (info);
1622 button_data->dir_name = g_mount_get_name (mount);
1623 button_data->type = MOUNT_BUTTON;
1624 button_data->fake_root = TRUE(!(0));
1625 g_object_unref (root);
1626 break;
1627 }
1628 default_location = g_mount_get_default_location (mount);
1629 if (!g_file_equal (default_location, root) &&
1630 g_file_equal (location, default_location))
1631 {
1632 result = TRUE(!(0));
1633 /* set mount specific details in button_data */
1634 icon = g_mount_get_icon (mount);
1635 if (icon == NULL((void*)0))
1636 {
1637 icon = g_themed_icon_new (CAJA_ICON_FOLDER"folder");
1638 }
1639 info = caja_icon_info_lookup (icon, CAJA_PATH_BAR_ICON_SIZE16, scale);
1640 g_object_unref (icon);
1641 button_data->custom_icon = caja_icon_info_get_surface_at_size (info, CAJA_PATH_BAR_ICON_SIZE16);
1642 g_object_unref (info);
1643 button_data->type = DEFAULT_LOCATION_BUTTON;
1644 button_data->fake_root = TRUE(!(0));
1645 g_object_unref (default_location);
1646 g_object_unref (root);
1647 break;
1648 }
1649 g_object_unref (default_location);
1650 g_object_unref (root);
1651 }
1652 g_list_free_full (mounts, g_object_unref);
1653 return result;
1654}
1655
1656static void
1657setup_button_type (ButtonData *button_data,
1658 CajaPathBar *path_bar,
1659 GFile *location)
1660{
1661 if (path_bar->root_path != NULL((void*)0) && g_file_equal (location, path_bar->root_path))
1662 {
1663 button_data->type = ROOT_BUTTON;
1664 }
1665 else if (path_bar->home_path != NULL((void*)0) && g_file_equal (location, path_bar->home_path))
1666 {
1667 button_data->type = HOME_BUTTON;
1668 button_data->fake_root = TRUE(!(0));
1669 }
1670 else if (path_bar->desktop_path != NULL((void*)0) && g_file_equal (location, path_bar->desktop_path))
1671 {
1672 if (!desktop_is_home)
1673 {
1674 button_data->type = DESKTOP_BUTTON;
1675 }
1676 else
1677 {
1678 button_data->type = NORMAL_BUTTON;
1679 }
1680 }
1681 else if (setup_file_path_mounted_mount (location, button_data))
1682 {
1683 /* already setup */
1684 }
1685 else
1686 {
1687 button_data->type = NORMAL_BUTTON;
1688 }
1689}
1690
1691static void
1692button_drag_data_get_cb (GtkWidget *widget,
1693 GdkDragContext *context,
1694 GtkSelectionData *selection_data,
1695 guint info,
1696 guint time_,
1697 gpointer user_data)
1698{
1699 ButtonData *button_data;
1700 char *uri_list[2];
1701
1702 button_data = user_data;
1703
1704 uri_list[0] = g_file_get_uri (button_data->path);
1705 uri_list[1] = NULL((void*)0);
1706
1707 if (info == CAJA_ICON_DND_MATE_ICON_LIST)
1708 {
1709 char *tmp;
1710
1711 tmp = g_strdup_printf ("%s\r\n", uri_list[0]);
1712 gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data),
1713 8, tmp, strlen (tmp));
1714 g_free (tmp);
1715 }
1716 else if (info == CAJA_ICON_DND_URI_LIST)
1717 {
1718 gtk_selection_data_set_uris (selection_data, uri_list);
1719 }
1720
1721 g_free (uri_list[0]);
1722}
1723
1724static void
1725setup_button_drag_source (ButtonData *button_data)
1726{
1727 GtkTargetList *target_list;
1728 const GtkTargetEntry targets[] =
1729 {
1730 { CAJA_ICON_DND_MATE_ICON_LIST_TYPE"x-special/mate-icon-list", 0, CAJA_ICON_DND_MATE_ICON_LIST }
1731 };
1732
1733 gtk_drag_source_set (button_data->button,
1734 GDK_BUTTON1_MASK |
1735 GDK_BUTTON2_MASK,
1736 NULL((void*)0), 0,
1737 GDK_ACTION_MOVE |
1738 GDK_ACTION_COPY |
1739 GDK_ACTION_LINK |
1740 GDK_ACTION_ASK);
1741
1742 target_list = gtk_target_list_new (targets, G_N_ELEMENTS (targets)(sizeof (targets) / sizeof ((targets)[0])));
1743 gtk_target_list_add_uri_targets (target_list, CAJA_ICON_DND_URI_LIST);
1744 gtk_drag_source_set_target_list (button_data->button, target_list);
1745 gtk_target_list_unref (target_list);
1746
1747 g_signal_connect (button_data->button, "drag-data-get",g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
1748 G_CALLBACK (button_drag_data_get_cb),g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
1749 button_data)g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
;
1750}
1751
1752static void
1753button_data_file_changed (CajaFile *file,
1754 ButtonData *button_data)
1755{
1756 GFile *location, *current_location;
1757 ButtonData *current_button_data;
1758 CajaPathBar *path_bar;
1759 gboolean renamed, child;
1760
1761 path_bar = (CajaPathBar *) gtk_widget_get_ancestor (button_data->button,
1762 CAJA_TYPE_PATH_BAR(caja_path_bar_get_type ()));
1763 if (path_bar == NULL((void*)0))
1764 {
1765 return;
1766 }
1767
1768 g_return_if_fail (path_bar->current_path != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (path_bar->current_path != ((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__)), "path_bar->current_path != NULL"); return;
} } while (0)
;
1769 g_return_if_fail (path_bar->current_button_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (path_bar->current_button_data != ((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__)), "path_bar->current_button_data != NULL"); return
; } } while (0)
;
1770
1771 current_button_data = path_bar->current_button_data;
1772
1773 location = caja_file_get_location (file);
1774 if (!g_file_equal (button_data->path, location))
1775 {
1776 GFile *parent, *button_parent;
1777
1778 parent = g_file_get_parent (location);
1779 button_parent = g_file_get_parent (button_data->path);
1780
1781 renamed = (parent != NULL((void*)0) && button_parent != NULL((void*)0)) &&
1782 g_file_equal (parent, button_parent);
1783
1784 if (parent != NULL((void*)0))
1785 {
1786 g_object_unref (parent);
1787 }
1788 if (button_parent != NULL((void*)0))
1789 {
1790 g_object_unref (button_parent);
1791 }
1792
1793 if (renamed)
1794 {
1795 button_data->path = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
1796 }
1797 else
1798 {
1799 /* the file has been moved.
1800 * If it was below the currently displayed location, remove it.
1801 * If it was not below the currently displayed location, update the path bar
1802 */
1803 child = g_file_has_prefix (button_data->path,
1804 path_bar->current_path);
1805
1806 if (child)
1807 {
1808 /* moved file inside current path hierarchy */
1809 g_object_unref (location);
1810 location = g_file_get_parent (button_data->path);
1811 current_location = g_object_ref (path_bar->current_path)((__typeof__ (path_bar->current_path)) (g_object_ref) (path_bar
->current_path))
;
1812 }
1813 else
1814 {
1815 /* moved current path, or file outside current path hierarchy.
1816 * Update path bar to new locations.
1817 */
1818 current_location = caja_file_get_location (current_button_data->file);
1819 }
1820
1821 caja_path_bar_update_path (path_bar, location, FALSE(0));
1822 caja_path_bar_set_path (path_bar, current_location);
1823 g_object_unref (location);
1824 g_object_unref (current_location);
1825 return;
1826 }
1827 }
1828 else if (caja_file_is_gone (file))
1829 {
1830 gint idx, position;
1831
1832 /* if the current or a parent location are gone, don't do anything, as the view
1833 * will get the event too and call us back.
1834 */
1835 current_location = caja_file_get_location (current_button_data->file);
1836
1837 if (g_file_has_prefix (location, current_location))
1838 {
1839 /* remove this and the following buttons */
1840 position = g_list_position (path_bar->button_list,
1841 g_list_find (path_bar->button_list, button_data));
1842
1843 if (position != -1)
1844 {
1845 for (idx = 0; idx <= position; idx++)
1846 {
1847 gtk_container_remove (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))),
1848 BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button);
1849 }
1850 }
1851 }
1852
1853 g_object_unref (current_location);
1854 g_object_unref (location);
1855 return;
1856 }
1857 g_object_unref (location);
1858
1859 /* MOUNTs use the GMount as the name, so don't update for those */
1860 if (button_data->type != MOUNT_BUTTON)
1861 {
1862 char *display_name;
1863
1864 display_name = caja_file_get_display_name (file);
1865 if (g_strcmp0 (display_name, button_data->dir_name) != 0)
1866 {
1867 g_free (button_data->dir_name);
1868 button_data->dir_name = g_strdup (display_name)g_strdup_inline (display_name);
1869 }
1870
1871 g_free (display_name);
1872 }
1873 caja_path_bar_update_button_appearance (button_data);
1874}
1875
1876static ButtonData *
1877make_directory_button (CajaPathBar *path_bar,
1878 CajaFile *file,
1879 gboolean current_dir,
1880 gboolean base_dir,
1881 gboolean file_is_hidden)
1882{
1883 GFile *path;
1884 GtkWidget *child;
1885 ButtonData *button_data;
1886
1887 path = caja_file_get_location (file);
1888
1889 child = NULL((void*)0);
1890
1891 file_is_hidden = !! file_is_hidden;
1892 /* Is it a special button? */
1893 button_data = g_new0 (ButtonData, 1)(ButtonData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (ButtonData); 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; }))
;
1894
1895 setup_button_type (button_data, path_bar, path);
1896 button_data->button = gtk_toggle_button_new ();
1897 gtk_style_context_add_class (gtk_widget_get_style_context (button_data->button),
1898 "text-button");
1899 gtk_widget_set_focus_on_click (button_data->button, FALSE(0));
1900 gtk_widget_add_events (button_data->button, GDK_SCROLL_MASK);
1901 /* TODO update button type when xdg directories change */
1902
1903 button_data->drag_info.target_location = g_object_ref (path)((__typeof__ (path)) (g_object_ref) (path));
1904
1905 button_data->image = gtk_image_new ();
1906
1907 switch (button_data->type)
1908 {
1909 case ROOT_BUTTON:
1910 /* Fall through */
1911 case HOME_BUTTON:
1912 /* Fall through */
1913 case DESKTOP_BUTTON:
1914 /* Fall through */
1915 case MOUNT_BUTTON:
1916 /* Fall through */
1917 case DEFAULT_LOCATION_BUTTON:
1918 button_data->label = gtk_label_new (NULL((void*)0));
1919 child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
1920 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->image, FALSE(0), FALSE(0), 0);
1921 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->label, FALSE(0), FALSE(0), 0);
1922
1923 break;
1924 case NORMAL_BUTTON:
1925 default:
1926 button_data->label = gtk_label_new (NULL((void*)0));
1927 child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
1928 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->image, FALSE(0), FALSE(0), 0);
1929 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->label, FALSE(0), FALSE(0), 0);
1930 button_data->is_base_dir = base_dir;
1931 }
1932
1933 if (button_data->path == NULL((void*)0))
1934 {
1935 button_data->path = g_object_ref (path)((__typeof__ (path)) (g_object_ref) (path));
1936 }
1937 if (button_data->dir_name == NULL((void*)0))
1938 {
1939 button_data->dir_name = caja_file_get_display_name (file);
1940 }
1941 if (button_data->file == NULL((void*)0))
1942 {
1943 button_data->file = caja_file_ref (file);
1944 caja_file_monitor_add (button_data->file, button_data,
1945 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
);
1946 button_data->file_changed_signal_id =
1947 g_signal_connect (button_data->file, "changed",g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
1948 G_CALLBACK (button_data_file_changed),g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
1949 button_data)g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
;
1950 }
1951
1952 button_data->file_is_hidden = file_is_hidden;
1953
1954 gtk_container_add (GTK_CONTAINER (button_data->button)((((GtkContainer*) (void *) ((button_data->button))))), child);
1955 gtk_widget_show_all (button_data->button);
1956
1957 caja_path_bar_update_button_state (button_data, current_dir);
1958
1959 g_signal_connect (button_data->button, "clicked", G_CALLBACK (button_clicked_cb), button_data)g_signal_connect_data ((button_data->button), ("clicked"),
(((GCallback) (button_clicked_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1960 g_signal_connect (button_data->button, "button-press-event", G_CALLBACK (button_event_cb), button_data)g_signal_connect_data ((button_data->button), ("button-press-event"
), (((GCallback) (button_event_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1961 g_signal_connect (button_data->button, "button-release-event", G_CALLBACK (button_event_cb), button_data)g_signal_connect_data ((button_data->button), ("button-release-event"
), (((GCallback) (button_event_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1962 g_signal_connect (button_data->button, "drag-begin", G_CALLBACK (button_drag_begin_cb), button_data)g_signal_connect_data ((button_data->button), ("drag-begin"
), (((GCallback) (button_drag_begin_cb))), (button_data), ((void
*)0), (GConnectFlags) 0)
;
1963 g_object_weak_ref (G_OBJECT (button_data->button)((((GObject*) (void *) ((button_data->button))))), (GWeakNotify) button_data_free, button_data);
1964
1965 setup_button_drag_source (button_data);
1966
1967 caja_drag_slot_proxy_init (button_data->button,
1968 &(button_data->drag_info));
1969
1970 g_object_unref (path);
1971
1972 return button_data;
1973}
1974
1975static gboolean
1976caja_path_bar_check_parent_path (CajaPathBar *path_bar,
1977 GFile *location,
1978 ButtonData **current_button_data)
1979{
1980 GList *list;
1981 GList *current_path;
1982 gboolean need_new_fake_root;
1983
1984 current_path = NULL((void*)0);
1985 need_new_fake_root = FALSE(0);
1986
1987 if (current_button_data)
1988 {
1989 *current_button_data = NULL((void*)0);
1990 }
1991
1992 for (list = path_bar->button_list; list; list = list->next)
1993 {
1994 ButtonData *button_data;
1995
1996 button_data = list->data;
1997 if (g_file_equal (location, button_data->path))
1998 {
1999 current_path = list;
2000
2001 if (current_button_data)
2002 {
2003 *current_button_data = button_data;
2004 }
2005 break;
2006 }
2007 if (list == path_bar->fake_root)
2008 {
2009 need_new_fake_root = TRUE(!(0));
2010 }
2011 }
2012
2013 if (current_path)
2014 {
2015
2016 if (need_new_fake_root)
2017 {
2018 path_bar->fake_root = NULL((void*)0);
2019 for (list = current_path; list; list = list->next)
2020 {
2021 ButtonData *button_data;
2022
2023 button_data = list->data;
2024 if (list->prev != NULL((void*)0) &&
2025 button_data->fake_root)
2026 {
2027 path_bar->fake_root = list;
2028 break;
2029 }
2030 }
2031 }
2032
2033 for (list = path_bar->button_list; list; list = list->next)
2034 {
2035
2036 caja_path_bar_update_button_state (BUTTON_DATA (list->data)((ButtonData *)(list->data)),
2037 (list == current_path) ? TRUE(!(0)) : FALSE(0));
2038 }
2039
2040 if (!gtk_widget_get_child_visible (BUTTON_DATA (current_path->data)((ButtonData *)(current_path->data))->button))
2041 {
2042 path_bar->first_scrolled_button = current_path;
2043 gtk_widget_queue_resize (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
2044 }
2045 return TRUE(!(0));
2046 }
2047 return FALSE(0);
2048}
2049
2050static gboolean
2051caja_path_bar_update_path (CajaPathBar *path_bar,
2052 GFile *file_path,
2053 gboolean emit_signal)
2054{
2055 CajaFile *file, *parent_file;
2056 gboolean first_directory, last_directory;
2057 gboolean result;
2058 GList *new_buttons, *l, *fake_root;
2059 ButtonData *button_data, *current_button_data;
2060
2061 g_return_val_if_fail (CAJA_IS_PATH_BAR (path_bar), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((caja_path_bar_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_26
= 1; else _g_boolean_var_26 = 0; _g_boolean_var_26; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_PATH_BAR (path_bar)"); return ((0));
} } while (0)
;
2062 g_return_val_if_fail (file_path != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if (file_path != ((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__)), "file_path != NULL"
); return ((0)); } } while (0)
;
2063
2064 fake_root = NULL((void*)0);
2065 result = TRUE(!(0));
2066 first_directory = TRUE(!(0));
2067 new_buttons = NULL((void*)0);
2068 current_button_data = NULL((void*)0);
2069
2070 file = caja_file_get (file_path);
2071
2072 while (file != NULL((void*)0))
2073 {
2074 parent_file = caja_file_get_parent (file);
2075 last_directory = !parent_file;
2076 button_data = make_directory_button (path_bar, file, first_directory, last_directory, FALSE(0));
2077 caja_file_unref (file);
2078
2079 if (first_directory)
2080 {
2081 current_button_data = button_data;
2082 }
2083
2084 new_buttons = g_list_prepend (new_buttons, button_data);
2085
2086 if (parent_file != NULL((void*)0) &&
2087 button_data->fake_root)
2088 {
2089 fake_root = new_buttons;
2090 }
2091
2092 file = parent_file;
2093 first_directory = FALSE(0);
2094 }
2095
2096 caja_path_bar_clear_buttons (path_bar);
2097 path_bar->button_list = g_list_reverse (new_buttons);
2098 path_bar->fake_root = fake_root;
2099
2100 for (l = path_bar->button_list; l; l = l->next)
2101 {
2102 GtkWidget *button;
2103 button = BUTTON_DATA (l->data)((ButtonData *)(l->data))->button;
2104 gtk_container_add (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))), button);
2105 }
2106
2107 if (path_bar->current_path != NULL((void*)0))
2108 {
2109 g_object_unref (path_bar->current_path);
2110 }
2111
2112 path_bar->current_path = g_object_ref (file_path)((__typeof__ (file_path)) (g_object_ref) (file_path));
2113
2114 path_bar->current_button_data = current_button_data;
2115
2116 return result;
2117}
2118
2119gboolean
2120caja_path_bar_set_path (CajaPathBar *path_bar, GFile *file_path)
2121{
2122 ButtonData *button_data;
2123
2124 g_return_val_if_fail (CAJA_IS_PATH_BAR (path_bar), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_28
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((caja_path_bar_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_28
= 1; else _g_boolean_var_28 = 0; _g_boolean_var_28; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_PATH_BAR (path_bar)"); return ((0));
} } while (0)
;
2125 g_return_val_if_fail (file_path != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if (file_path != ((void*)0)) _g_boolean_var_29 = 1; else _g_boolean_var_29
= 0; _g_boolean_var_29; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_path != NULL"
); return ((0)); } } while (0)
;
2126
2127 /* Check whether the new path is already present in the pathbar as buttons.
2128 * This could be a parent directory or a previous selected subdirectory. */
2129 if (caja_path_bar_check_parent_path (path_bar, file_path, &button_data))
2130 {
2131 if (path_bar->current_path != NULL((void*)0))
2132 {
2133 g_object_unref (path_bar->current_path);
2134 }
2135
2136 path_bar->current_path = g_object_ref (file_path)((__typeof__ (file_path)) (g_object_ref) (file_path));
2137 path_bar->current_button_data = button_data;
2138
2139 return TRUE(!(0));
2140 }
2141
2142 return caja_path_bar_update_path (path_bar, file_path, TRUE(!(0)));
2143}
2144
2145GFile *
2146caja_path_bar_get_path_for_button (CajaPathBar *path_bar,
2147 GtkWidget *button)
2148{
2149 GList *list;
2150
2151 g_return_val_if_fail (CAJA_IS_PATH_BAR (path_bar), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((caja_path_bar_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_30
= 1; else _g_boolean_var_30 = 0; _g_boolean_var_30; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_PATH_BAR (path_bar)"); return (((void
*)0)); } } while (0)
;
2152 g_return_val_if_fail (GTK_IS_BUTTON (button), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); 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; }))))) _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__)), "GTK_IS_BUTTON (button)"); return (((void*)0)
); } } while (0)
;
2153
2154 for (list = path_bar->button_list; list; list = list->next)
2155 {
2156 ButtonData *button_data;
2157 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
2158 if (button_data->button == button)
2159 {
2160 return g_object_ref (button_data->path)((__typeof__ (button_data->path)) (g_object_ref) (button_data
->path))
;
2161 }
2162 }
2163
2164 return NULL((void*)0);
2165}
2166
2167GtkWidget *
2168caja_path_bar_get_button_from_button_list_entry (gpointer entry)
2169{
2170 return BUTTON_DATA(entry)((ButtonData *)(entry))->button;
2171}
diff --git a/2024-07-29-023715-6438-1/report-29d5c0.html b/2024-07-29-023715-6438-1/report-29d5c0.html new file mode 100644 index 000000000..22efc0a92 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-29d5c0.html @@ -0,0 +1,4831 @@ + + + +eel-canvas.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-canvas.c
Warning:line 605, column 37
Access to field 'prev' results in a dereference of a null pointer (loaded from field 'item_list')
+ +

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 eel-canvas.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-canvas.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
2/*
3 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
4 * All rights reserved.
5 *
6 * This file is part of the Mate Library.
7 *
8 * The Mate Library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * The Mate 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 the Mate Library; see the file COPYING.LIB. If not,
20 * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23/*
24 @NOTATION@
25 */
26/*
27 * EelCanvas widget - Tk-like canvas widget for Mate
28 *
29 * EelCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
30 * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
31 *
32 *
33 * Authors: Federico Mena <federico@nuclecu.unam.mx>
34 * Raph Levien <raph@gimp.org>
35 */
36
37/*
38 * TO-DO list for the canvas:
39 *
40 * - Allow to specify whether EelCanvasImage sizes are in units or pixels (scale or don't scale).
41 *
42 * - Implement a flag for eel_canvas_item_reparent() that tells the function to keep the item
43 * visually in the same place, that is, to keep it in the same place with respect to the canvas
44 * origin.
45 *
46 * - GC put functions for items.
47 *
48 * - Widget item (finish it).
49 *
50 * - GList *eel_canvas_gimme_all_items_contained_in_this_area (EelCanvas *canvas, Rectangle area);
51 *
52 * - Retrofit all the primitive items with microtile support.
53 *
54 * - Curve support for line item.
55 *
56 * - Arc item (Havoc has it; to be integrated in EelCanvasEllipse).
57 *
58 * - Sane font handling API.
59 *
60 * - Get_arg methods for items:
61 * - How to fetch the outline width and know whether it is in pixels or units?
62 */
63
64#include <config.h>
65
66#include <math.h>
67#include <string.h>
68#include <stdio.h>
69#include <gdk/gdkprivate.h>
70#include <gtk/gtk.h>
71#include <gtk/gtk-a11y.h>
72#include <glib/gi18n-lib.h>
73#include <cairo/cairo-gobject.h>
74#include "eel-canvas.h"
75
76#include "eel-marshal.h"
77
78static void eel_canvas_request_update (EelCanvas *canvas);
79static void group_add (EelCanvasGroup *group,
80 EelCanvasItem *item);
81static void group_remove (EelCanvasGroup *group,
82 EelCanvasItem *item);
83static void redraw_and_repick_if_mapped (EelCanvasItem *item);
84
85/*** EelCanvasItem ***/
86
87/* Some convenience stuff */
88#define GCI_UPDATE_MASK(EEL_CANVAS_UPDATE_REQUESTED | EEL_CANVAS_UPDATE_DEEP) (EEL_CANVAS_UPDATE_REQUESTED | EEL_CANVAS_UPDATE_DEEP)
89
90enum
91{
92 ITEM_PROP_0,
93 ITEM_PROP_PARENT,
94 ITEM_PROP_VISIBLE
95};
96
97enum
98{
99 ITEM_DESTROY,
100 ITEM_EVENT,
101 ITEM_LAST_SIGNAL
102};
103
104static void eel_canvas_item_class_init (EelCanvasItemClass *klass);
105static void eel_canvas_item_init (EelCanvasItem *item);
106static int emit_event (EelCanvas *canvas, GdkEvent *event);
107
108static guint item_signals[ITEM_LAST_SIGNAL] = { 0 };
109
110static GObjectClass *item_parent_class;
111
112static gpointer accessible_item_parent_class;
113static gpointer accessible_parent_class;
114
115
116/**
117 * eel_canvas_item_get_type:
118 *
119 * Registers the &EelCanvasItem class if necessary, and returns the type ID
120 * associated to it.
121 *
122 * Return value: The type ID of the &EelCanvasItem class.
123 **/
124GType
125eel_canvas_item_get_type (void)
126{
127 static GType canvas_item_type = 0;
128
129 if (!canvas_item_type)
130 {
131 static const GTypeInfo canvas_item_info =
132 {
133 sizeof (EelCanvasItemClass),
134 (GBaseInitFunc) NULL((void*)0),
135 (GBaseFinalizeFunc) NULL((void*)0),
136 (GClassInitFunc) eel_canvas_item_class_init,
137 NULL((void*)0), /* class_finalize */
138 NULL((void*)0), /* class_data */
139 sizeof (EelCanvasItem),
140 0, /* n_preallocs */
141 (GInstanceInitFunc) eel_canvas_item_init
142 };
143
144 canvas_item_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED(g_initially_unowned_get_type()),
145 "EelCanvasItem",
146 &canvas_item_info,
147 0);
148 }
149
150 return canvas_item_type;
151}
152
153/* Object initialization function for EelCanvasItem */
154static void
155eel_canvas_item_init (EelCanvasItem *item)
156{
157 item->flags |= EEL_CANVAS_ITEM_VISIBLE;
158}
159
160/**
161 * eel_canvas_item_new:
162 * @parent: The parent group for the new item.
163 * @type: The object type of the item.
164 * @first_arg_name: A list of object argument name/value pairs, NULL-terminated,
165 * used to configure the item. For example, "fill_color", "black",
166 * "width_units", 5.0, NULL.
167 * @Varargs:
168 *
169 * Creates a new canvas item with @parent as its parent group. The item is
170 * created at the top of its parent's stack, and starts up as visible. The item
171 * is of the specified @type, for example, it can be
172 * eel_canvas_rect_get_type(). The list of object arguments/value pairs is
173 * used to configure the item.
174 *
175 * Return value: The newly-created item.
176 **/
177EelCanvasItem *
178eel_canvas_item_new (EelCanvasGroup *parent, GType type, const gchar *first_arg_name, ...)
179{
180 EelCanvasItem *item;
181 va_list args;
182
183 g_return_val_if_fail (EEL_IS_CANVAS_GROUP (parent), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent)); GType __t = ((eel_canvas_group_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (parent)"); return (((void
*)0)); } } while (0)
;
184 g_return_val_if_fail (g_type_is_a (type, eel_canvas_item_get_type ()), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if (((type) == (eel_canvas_item_get_type ()) || (g_type_is_a
) ((type), (eel_canvas_item_get_type ())))) _g_boolean_var_199
= 1; else _g_boolean_var_199 = 0; _g_boolean_var_199; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "g_type_is_a (type, eel_canvas_item_get_type ())"
); return (((void*)0)); } } while (0)
;
185
186 item = EEL_CANVAS_ITEM (g_object_new (type, NULL))((((EelCanvasItem*) (void *) ((g_object_new (type, ((void*)0)
))))))
;
187
188 va_start (args, first_arg_name)__builtin_va_start(args, first_arg_name);
189 eel_canvas_item_construct (item, parent, first_arg_name, args);
190 va_end (args)__builtin_va_end(args);
191
192 return item;
193}
194
195
196/* Performs post-creation operations on a canvas item (adding it to its parent
197 * group, etc.)
198 */
199static void
200item_post_create_setup (EelCanvasItem *item)
201{
202 group_add (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent))))), item);
203
204 redraw_and_repick_if_mapped (item);
205}
206
207/* Set_property handler for canvas items */
208static void
209eel_canvas_item_set_property (GObject *gobject, guint param_id,
210 const GValue *value, GParamSpec *pspec)
211{
212 EelCanvasItem *item;
213
214 g_return_if_fail (EEL_IS_CANVAS_ITEM (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_200
= 1; else _g_boolean_var_200 = 0; _g_boolean_var_200; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (gobject)"); return; } } while
(0)
;
215
216 item = EEL_CANVAS_ITEM (gobject)((((EelCanvasItem*) (void *) ((gobject)))));
217
218 switch (param_id)
219 {
220 case ITEM_PROP_PARENT:
221 if (item->parent != NULL((void*)0))
222 {
223 g_warning ("Cannot set `parent' argument after item has "
224 "already been constructed.");
225 }
226 else if (g_value_get_object (value))
227 {
228 item->parent = EEL_CANVAS_ITEM (g_value_get_object (value))((((EelCanvasItem*) (void *) ((g_value_get_object (value)))))
)
;
229 item->canvas = item->parent->canvas;
230 item_post_create_setup (item);
231 }
232 break;
233 case ITEM_PROP_VISIBLE:
234 if (g_value_get_boolean (value))
235 {
236 eel_canvas_item_show (item);
237 }
238 else
239 {
240 eel_canvas_item_hide (item);
241 }
242 break;
243 default:
244 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 244, ("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)
;
245 break;
246 }
247}
248
249/* Get_property handler for canvas items */
250static void
251eel_canvas_item_get_property (GObject *gobject, guint param_id,
252 GValue *value, GParamSpec *pspec)
253{
254 EelCanvasItem *item;
255
256 g_return_if_fail (EEL_IS_CANVAS_ITEM (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_201
= 1; else _g_boolean_var_201 = 0; _g_boolean_var_201; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (gobject)"); return; } } while
(0)
;
257
258 item = EEL_CANVAS_ITEM (gobject)((((EelCanvasItem*) (void *) ((gobject)))));
259
260 switch (param_id)
261 {
262 case ITEM_PROP_VISIBLE:
263 g_value_set_boolean (value, item->flags & EEL_CANVAS_ITEM_VISIBLE);
264 break;
265 default:
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 266, ("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)
;
267 break;
268 }
269}
270
271/**
272 * eel_canvas_item_construct:
273 * @item: An unconstructed canvas item.
274 * @parent: The parent group for the item.
275 * @first_arg_name: The name of the first argument for configuring the item.
276 * @args: The list of arguments used to configure the item.
277 *
278 * Constructs a canvas item; meant for use only by item implementations.
279 **/
280void
281eel_canvas_item_construct (EelCanvasItem *item, EelCanvasGroup *parent,
282 const gchar *first_arg_name, va_list args)
283{
284 g_return_if_fail (EEL_IS_CANVAS_GROUP (parent))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent)); GType __t = ((eel_canvas_group_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_202
= 1; else _g_boolean_var_202 = 0; _g_boolean_var_202; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (parent)"); return; } } while
(0)
;
285 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_203
= 1; else _g_boolean_var_203 = 0; _g_boolean_var_203; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
286
287 item->parent = EEL_CANVAS_ITEM (parent)((((EelCanvasItem*) (void *) ((parent)))));
288 item->canvas = item->parent->canvas;
289
290 g_object_set_valist (G_OBJECT (item)((((GObject*) (void *) ((item))))), first_arg_name, args);
291
292 item_post_create_setup (item);
293}
294
295
296static void
297redraw_and_repick_if_mapped (EelCanvasItem *item)
298{
299 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
300 {
301 eel_canvas_item_request_redraw (item);
302 item->canvas->need_repick = TRUE(!(0));
303 }
304}
305
306/* Dispose handler for canvas items */
307static void
308eel_canvas_item_dispose (GObject *object)
309{
310 EelCanvasItem *item;
311
312 g_return_if_fail (EEL_IS_CANVAS_ITEM (object))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_204
= 1; else _g_boolean_var_204 = 0; _g_boolean_var_204; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (object)"); return; } } while
(0)
;
313
314 item = EEL_CANVAS_ITEM (object)((((EelCanvasItem*) (void *) ((object)))));
315
316 if (item->canvas)
317 {
318 eel_canvas_item_request_redraw (item);
319
320 /* Make the canvas forget about us */
321
322 if (item == item->canvas->current_item)
323 {
324 item->canvas->current_item = NULL((void*)0);
325 item->canvas->need_repick = TRUE(!(0));
326 }
327
328 if (item == item->canvas->new_current_item)
329 {
330 item->canvas->new_current_item = NULL((void*)0);
331 item->canvas->need_repick = TRUE(!(0));
332 }
333
334 eel_canvas_item_ungrab (item);
335
336 if (item == item->canvas->focused_item)
337 item->canvas->focused_item = NULL((void*)0);
338
339 /* Normal destroy stuff */
340
341 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
342 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
343
344 if (item->flags & EEL_CANVAS_ITEM_REALIZED)
345 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unrealize) (item);
346
347 if (item->parent)
348 group_remove (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent))))), item);
349
350 item->canvas = NULL((void*)0);
351 }
352
353 g_object_set_data (object, "in-destruction", GINT_TO_POINTER (1)((gpointer) (glong) (1)));
354 g_signal_emit (object, item_signals[ITEM_DESTROY], 0);
355
356 g_object_set_data (object, "in-destruction", NULL((void*)0));
357
358 G_OBJECT_CLASS (item_parent_class)((((GObjectClass*) (void *) ((item_parent_class)))))->dispose (object);
359}
360
361void
362eel_canvas_item_destroy (EelCanvasItem *item)
363{
364 if (g_object_get_data (G_OBJECT (item)((((GObject*) (void *) ((item))))), "in-destruction") == NULL((void*)0)) {
365 g_object_run_dispose (G_OBJECT (item)((((GObject*) (void *) ((item))))));
366 }
367}
368
369/* Realize handler for canvas items */
370static void
371eel_canvas_item_realize (EelCanvasItem *item)
372{
373 if (item->parent && !(item->parent->flags & EEL_CANVAS_ITEM_REALIZED))
374 (* EEL_CANVAS_ITEM_GET_CLASS (item->parent)((((EelCanvasItemClass*) (((GTypeInstance*) ((item->parent
)))->g_class))))
->realize) (item->parent);
375
376 if (item->parent == NULL((void*)0) && !gtk_widget_get_realized (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))))))
377 gtk_widget_realize (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
378
379 item->flags |= EEL_CANVAS_ITEM_REALIZED;
380
381 eel_canvas_item_request_update (item);
382}
383
384/* Unrealize handler for canvas items */
385static void
386eel_canvas_item_unrealize (EelCanvasItem *item)
387{
388 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
389 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
390
391 item->flags &= ~(EEL_CANVAS_ITEM_REALIZED);
392}
393
394/* Map handler for canvas items */
395static void
396eel_canvas_item_map (EelCanvasItem *item)
397{
398 item->flags |= EEL_CANVAS_ITEM_MAPPED;
399}
400
401/* Unmap handler for canvas items */
402static void
403eel_canvas_item_unmap (EelCanvasItem *item)
404{
405 item->flags &= ~(EEL_CANVAS_ITEM_MAPPED);
406}
407
408/* Update handler for canvas items */
409static void
410eel_canvas_item_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags)
411{
412 item->flags &= ~(EEL_CANVAS_ITEM_NEED_UPDATE);
413 item->flags &= ~(EEL_CANVAS_ITEM_NEED_DEEP_UPDATE);
414}
415
416/*
417 * This routine invokes the update method of the item
418 * Please notice, that we take parent to canvas pixel matrix as argument
419 * unlike virtual method ::update, whose argument is item 2 canvas pixel
420 * matrix
421 *
422 * I will try to force somewhat meaningful naming for affines (Lauris)
423 * General naming rule is FROM2TO, where FROM and TO are abbreviations
424 * So p2cpx is Parent2CanvasPixel and i2cpx is Item2CanvasPixel
425 * I hope that this helps to keep track of what really happens
426 *
427 */
428
429static void
430eel_canvas_item_invoke_update (EelCanvasItem *item,
431 double i2w_dx,
432 double i2w_dy,
433 int flags)
434{
435 int child_flags;
436
437 child_flags = flags;
438
439 /* apply object flags to child flags */
440 child_flags &= ~EEL_CANVAS_UPDATE_REQUESTED;
441
442 if (item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)
443 child_flags |= EEL_CANVAS_UPDATE_REQUESTED;
444
445 if (item->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE)
446 child_flags |= EEL_CANVAS_UPDATE_DEEP;
447
448 if (child_flags & GCI_UPDATE_MASK(EEL_CANVAS_UPDATE_REQUESTED | EEL_CANVAS_UPDATE_DEEP))
449 {
450 if (EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->update)
451 EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->update (item, i2w_dx, i2w_dy, child_flags);
452 }
453
454 /* If this fail you probably forgot to chain up to
455 * EelCanvasItem::update from a derived class */
456 g_return_if_fail (!(item->flags & EEL_CANVAS_ITEM_NEED_UPDATE))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if (!(item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)) _g_boolean_var_205
= 1; else _g_boolean_var_205 = 0; _g_boolean_var_205; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "!(item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)"
); return; } } while (0)
;
457}
458
459/*
460 * This routine invokes the point method of the item.
461 * The arguments x, y should be in the parent item local coordinates.
462 */
463
464static double
465eel_canvas_item_invoke_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item)
466{
467 /* Calculate x & y in item local coordinates */
468
469 if (EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->point)
470 return EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->point (item, x, y, cx, cy, actual_item);
471
472 return 1e18;
473}
474
475/**
476 * eel_canvas_item_set:
477 * @item: A canvas item.
478 * @first_arg_name: The list of object argument name/value pairs used to configure the item.
479 * @Varargs:
480 *
481 * Configures a canvas item. The arguments in the item are set to the specified
482 * values, and the item is repainted as appropriate.
483 **/
484void
485eel_canvas_item_set (EelCanvasItem *item, const gchar *first_arg_name, ...)
486{
487 va_list args;
488
489 va_start (args, first_arg_name)__builtin_va_start(args, first_arg_name);
490 eel_canvas_item_set_valist (item, first_arg_name, args);
491 va_end (args)__builtin_va_end(args);
492}
493
494
495/**
496 * eel_canvas_item_set_valist:
497 * @item: A canvas item.
498 * @first_arg_name: The name of the first argument used to configure the item.
499 * @args: The list of object argument name/value pairs used to configure the item.
500 *
501 * Configures a canvas item. The arguments in the item are set to the specified
502 * values, and the item is repainted as appropriate.
503 **/
504void
505eel_canvas_item_set_valist (EelCanvasItem *item, const gchar *first_arg_name, va_list args)
506{
507 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_206
= 1; else _g_boolean_var_206 = 0; _g_boolean_var_206; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
508
509 g_object_set_valist (G_OBJECT (item)((((GObject*) (void *) ((item))))), first_arg_name, args);
510
511 item->canvas->need_repick = TRUE(!(0));
512}
513
514
515/**
516 * eel_canvas_item_move:
517 * @item: A canvas item.
518 * @dx: Horizontal offset.
519 * @dy: Vertical offset.
520 *
521 * Moves a canvas item by creating an affine transformation matrix for
522 * translation by using the specified values. This happens in item
523 * local coordinate system, so if you have nontrivial transform, it
524 * most probably does not do, what you want.
525 **/
526void
527eel_canvas_item_move (EelCanvasItem *item, double dx, double dy)
528{
529 g_return_if_fail (item != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if (item != ((void*)0)) _g_boolean_var_207 = 1; else _g_boolean_var_207
= 0; _g_boolean_var_207; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "item != NULL"); return;
} } while (0)
;
530 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_208
= 1; else _g_boolean_var_208 = 0; _g_boolean_var_208; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
531
532 if (!EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->translate)
533 {
534 g_warning ("Item type %s does not implement translate method.\n",
535 g_type_name (G_OBJECT_TYPE (item)(((((GTypeClass*) (((GTypeInstance*) (item))->g_class))->
g_type)))
));
536 return;
537 }
538
539 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->translate) (item, dx, dy);
540
541 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
542 item->canvas->need_repick = TRUE(!(0));
543
544 if (!(item->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
545 {
546 item->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
547 if (item->parent != NULL((void*)0))
548 eel_canvas_item_request_update (item->parent);
549 else
550 eel_canvas_request_update (item->canvas);
551 }
552
553}
554
555static void
556eel_canvas_queue_resize (EelCanvas *canvas)
557{
558 if (gtk_widget_is_drawable (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas)))))))
559 gtk_widget_queue_resize (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))));
560}
561
562/* Convenience function to reorder items in a group's child list. This puts the
563 * specified link after the "before" link. Returns TRUE if the list was changed.
564 */
565static gboolean
566put_item_after (GList *link, GList *before)
567{
568 EelCanvasGroup *parent;
569
570 if (link == before)
23
Assuming 'link' is not equal to 'before'
24
Taking false branch
571 return FALSE(0);
572
573 parent = EEL_CANVAS_GROUP (EEL_CANVAS_ITEM (link->data)->parent)((((EelCanvasGroup*) (void *) ((((((EelCanvasItem*) (void *) (
(link->data)))))->parent)))))
;
574
575 if (before == NULL((void*)0))
25
Assuming 'before' is not equal to NULL
576 {
577 if (link == parent->item_list)
578 return FALSE(0);
579
580 link->prev->next = link->next;
581
582 if (link->next)
583 link->next->prev = link->prev;
584 else
585 parent->item_list_end = link->prev;
586
587 link->prev = before;
588 link->next = parent->item_list;
589 link->next->prev = link;
590 parent->item_list = link;
591 }
592 else
593 {
594 if ((link == parent->item_list_end) && (before == parent->item_list_end->prev))
26
Assuming 'link' is not equal to field 'item_list_end'
595 return FALSE(0);
596
597 if (link->next)
27
Assuming field 'next' is null
28
Taking false branch
598 link->next->prev = link->prev;
599
600 if (link->prev)
29
Assuming field 'prev' is null
30
Taking false branch
601 link->prev->next = link->next;
602 else
603 {
604 parent->item_list = link->next;
31
Null pointer value stored to field 'item_list'
605 parent->item_list->prev = NULL((void*)0);
32
Access to field 'prev' results in a dereference of a null pointer (loaded from field 'item_list')
606 }
607
608 link->prev = before;
609 link->next = before->next;
610
611 link->prev->next = link;
612
613 if (link->next)
614 link->next->prev = link;
615 else
616 parent->item_list_end = link;
617 }
618 return TRUE(!(0));
619}
620
621
622/**
623 * eel_canvas_item_raise:
624 * @item: A canvas item.
625 * @positions: Number of steps to raise the item.
626 *
627 * Raises the item in its parent's stack by the specified number of positions.
628 * If the number of positions is greater than the distance to the top of the
629 * stack, then the item is put at the top.
630 **/
631void
632eel_canvas_item_raise (EelCanvasItem *item, int positions)
633{
634 GList *link, *before;
635 EelCanvasGroup *parent;
636
637 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_209
= 1; else _g_boolean_var_209 = 0; _g_boolean_var_209; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
638 g_return_if_fail (positions >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if (positions >= 0) _g_boolean_var_210 = 1; else _g_boolean_var_210
= 0; _g_boolean_var_210; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "positions >= 0"); return
; } } while (0)
;
639
640 if (!item->parent || positions == 0)
641 return;
642
643 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
644 link = g_list_find (parent->item_list, item);
645 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (link != ((void*)0)) _g_boolean_var_211 = 1; else _g_boolean_var_211
= 0; _g_boolean_var_211; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 645, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
646
647 for (before = link; positions && before; positions--)
648 before = before->next;
649
650 if (!before)
651 before = parent->item_list_end;
652
653 if (put_item_after (link, before))
654 {
655 redraw_and_repick_if_mapped (item);
656 }
657}
658
659
660/**
661 * eel_canvas_item_lower:
662 * @item: A canvas item.
663 * @positions: Number of steps to lower the item.
664 *
665 * Lowers the item in its parent's stack by the specified number of positions.
666 * If the number of positions is greater than the distance to the bottom of the
667 * stack, then the item is put at the bottom.
668 **/
669void
670eel_canvas_item_lower (EelCanvasItem *item, int positions)
671{
672 GList *link, *before;
673 EelCanvasGroup *parent;
674
675 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_212
= 1; else _g_boolean_var_212 = 0; _g_boolean_var_212; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
676 g_return_if_fail (positions >= 1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if (positions >= 1) _g_boolean_var_213 = 1; else _g_boolean_var_213
= 0; _g_boolean_var_213; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "positions >= 1"); return
; } } while (0)
;
677
678 if (!item->parent || positions == 0)
679 return;
680
681 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
682 link = g_list_find (parent->item_list, item);
683 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if (link != ((void*)0)) _g_boolean_var_214 = 1; else _g_boolean_var_214
= 0; _g_boolean_var_214; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 683, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
684
685 if (link->prev)
686 for (before = link->prev; positions && before; positions--)
687 before = before->prev;
688 else
689 before = NULL((void*)0);
690
691 if (put_item_after (link, before))
692 {
693 redraw_and_repick_if_mapped (item);
694 }
695}
696
697
698/**
699 * eel_canvas_item_raise_to_top:
700 * @item: A canvas item.
701 *
702 * Raises an item to the top of its parent's stack.
703 **/
704void
705eel_canvas_item_raise_to_top (EelCanvasItem *item)
706{
707 GList *link;
708 EelCanvasGroup *parent;
709
710 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_215
= 1; else _g_boolean_var_215 = 0; _g_boolean_var_215; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
11
Taking false branch
12
Assuming the condition is true
13
Taking true branch
14
Taking true branch
15
Loop condition is false. Exiting loop
711
712 if (!item->parent)
16
Assuming field 'parent' is non-null
17
Taking false branch
713 return;
714
715 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
716 link = g_list_find (parent->item_list, item);
717 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if (link != ((void*)0)) _g_boolean_var_216 = 1; else _g_boolean_var_216
= 0; _g_boolean_var_216; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 717, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
18
Assuming 'link' is not equal to null
19
Taking true branch
20
Taking true branch
21
Loop condition is false. Exiting loop
718
719 if (put_item_after (link, parent->item_list_end))
22
Calling 'put_item_after'
720 {
721 redraw_and_repick_if_mapped (item);
722 }
723}
724
725
726/**
727 * eel_canvas_item_lower_to_bottom:
728 * @item: A canvas item.
729 *
730 * Lowers an item to the bottom of its parent's stack.
731 **/
732void
733eel_canvas_item_lower_to_bottom (EelCanvasItem *item)
734{
735 GList *link;
736 EelCanvasGroup *parent;
737
738 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_217
= 1; else _g_boolean_var_217 = 0; _g_boolean_var_217; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
739
740 if (!item->parent)
741 return;
742
743 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
744 link = g_list_find (parent->item_list, item);
745 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_218
; if (link != ((void*)0)) _g_boolean_var_218 = 1; else _g_boolean_var_218
= 0; _g_boolean_var_218; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 745, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
746
747 if (put_item_after (link, NULL((void*)0)))
748 {
749 redraw_and_repick_if_mapped (item);
750 }
751}
752
753/**
754 * eel_canvas_item_send_behind:
755 * @item: A canvas item.
756 * @behind_item: The canvas item to put item behind, or NULL
757 *
758 * Moves item to a in the position in the stacking order so that
759 * it is placed immediately below behind_item, or at the top if
760 * behind_item is NULL.
761 **/
762void
763eel_canvas_item_send_behind (EelCanvasItem *item,
764 EelCanvasItem *behind_item)
765{
766 GList *item_list;
767 int item_position, behind_position;
768
769 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_219
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_219
= 1; else _g_boolean_var_219 = 0; _g_boolean_var_219; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } 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
770
771 if (behind_item == NULL((void*)0))
8
Assuming 'behind_item' is equal to NULL
9
Taking true branch
772 {
773 eel_canvas_item_raise_to_top (item);
10
Calling 'eel_canvas_item_raise_to_top'
774 return;
775 }
776
777 g_return_if_fail (EEL_IS_CANVAS_ITEM (behind_item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_220
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((behind_item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_220 = 1; else _g_boolean_var_220 =
0; _g_boolean_var_220; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_CANVAS_ITEM (behind_item)"
); return; } } while (0)
;
778 g_return_if_fail (item->parent == behind_item->parent)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_221
; if (item->parent == behind_item->parent) _g_boolean_var_221
= 1; else _g_boolean_var_221 = 0; _g_boolean_var_221; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "item->parent == behind_item->parent"); return
; } } while (0)
;
779
780 item_list = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))))->item_list;
781
782 item_position = g_list_index (item_list, item);
783 g_assert (item_position != -1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if (item_position != -1) _g_boolean_var_222 = 1; else _g_boolean_var_222
= 0; _g_boolean_var_222; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 783, ((const char*) (__func__)), "item_position != -1"
); } while (0)
;
784 behind_position = g_list_index (item_list, behind_item);
785 g_assert (behind_position != -1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_223
; if (behind_position != -1) _g_boolean_var_223 = 1; else _g_boolean_var_223
= 0; _g_boolean_var_223; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 785, ((const char*) (__func__)), "behind_position != -1"
); } while (0)
;
786 g_assert (item_position != behind_position)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_224
; if (item_position != behind_position) _g_boolean_var_224 = 1
; else _g_boolean_var_224 = 0; _g_boolean_var_224; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-canvas.c", 786, ((const
char*) (__func__)), "item_position != behind_position"); } while
(0)
;
787
788 if (item_position == behind_position - 1)
789 {
790 return;
791 }
792
793 if (item_position < behind_position)
794 {
795 eel_canvas_item_raise (item, (behind_position - 1) - item_position);
796 }
797 else
798 {
799 eel_canvas_item_lower (item, item_position - behind_position);
800 }
801}
802
803/**
804 * eel_canvas_item_show:
805 * @item: A canvas item.
806 *
807 * Shows a canvas item. If the item was already shown, then no action is taken.
808 **/
809void
810eel_canvas_item_show (EelCanvasItem *item)
811{
812 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_225
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_225
= 1; else _g_boolean_var_225 = 0; _g_boolean_var_225; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
813
814 if (!(item->flags & EEL_CANVAS_ITEM_VISIBLE))
815 {
816 item->flags |= EEL_CANVAS_ITEM_VISIBLE;
817
818 if (!(item->flags & EEL_CANVAS_ITEM_REALIZED))
819 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->realize) (item);
820
821 if (item->parent != NULL((void*)0))
822 {
823 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED) &&
824 item->parent->flags & EEL_CANVAS_ITEM_MAPPED)
825 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->map) (item);
826 }
827 else
828 {
829 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED) &&
830 gtk_widget_get_mapped (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))))))
831 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->map) (item);
832 }
833
834 redraw_and_repick_if_mapped (item);
835 eel_canvas_queue_resize (item->canvas);
836 }
837}
838
839
840/**
841 * eel_canvas_item_hide:
842 * @item: A canvas item.
843 *
844 * Hides a canvas item. If the item was already hidden, then no action is
845 * taken.
846 **/
847void
848eel_canvas_item_hide (EelCanvasItem *item)
849{
850 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_226
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_226
= 1; else _g_boolean_var_226 = 0; _g_boolean_var_226; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
851
852 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
853 {
854 item->flags &= ~EEL_CANVAS_ITEM_VISIBLE;
855
856 redraw_and_repick_if_mapped (item);
857
858 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
859 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
860
861 eel_canvas_queue_resize (item->canvas);
862
863 /* No need to unrealize when we just want to hide */
864 }
865}
866
867/*
868 * Prepare the window for grabbing, i.e. show it.
869 */
870static void
871seat_grab_prepare_window (GdkSeat *seat,
872 GdkWindow *window,
873 gpointer user_data)
874{
875 gdk_window_show (window);
876}
877
878/**
879 * eel_canvas_item_grab:
880 * @item: A canvas item.
881 * @event_mask: Mask of events that will be sent to this item.
882 * @cursor: If non-NULL, the cursor that will be used while the grab is active.
883 * @event: The event, triggering the grab, if any.
884 *
885 * Specifies that all events that match the specified event mask should be sent
886 * to the specified item, and also grabs the seat by calling gdk_seat_grab().
887 * If @cursor is not NULL, then that cursor is used while the grab is active.
888 *
889 * Return value: If an item was already grabbed, it returns %GDK_GRAB_ALREADY_GRABBED. If
890 * the specified item was hidden by calling eel_canvas_item_hide(), then it
891 * returns %GDK_GRAB_NOT_VIEWABLE. Else, it returns the result of calling
892 * gdk_seat_grab().
893 **/
894GdkGrabStatus
895eel_canvas_item_grab (EelCanvasItem *item,
896 GdkEventMask event_mask,
897 GdkCursor *cursor,
898 const GdkEvent *event)
899{
900 GdkGrabStatus retval;
901 GdkDisplay *display;
902 GdkSeat *seat;
903
904 g_return_val_if_fail (EEL_IS_CANVAS_ITEM (item), GDK_GRAB_NOT_VIEWABLE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_227
= 1; else _g_boolean_var_227 = 0; _g_boolean_var_227; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return (GDK_GRAB_NOT_VIEWABLE
); } } while (0)
;
905 g_return_val_if_fail (gtk_widget_get_mapped (GTK_WIDGET (item->canvas)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if (gtk_widget_get_mapped (((((GtkWidget*) (void *) ((item->
canvas))))))) _g_boolean_var_228 = 1; else _g_boolean_var_228
= 0; _g_boolean_var_228; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "gtk_widget_get_mapped (GTK_WIDGET (item->canvas))"
); return (GDK_GRAB_NOT_VIEWABLE); } } while (0)
906 GDK_GRAB_NOT_VIEWABLE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if (gtk_widget_get_mapped (((((GtkWidget*) (void *) ((item->
canvas))))))) _g_boolean_var_228 = 1; else _g_boolean_var_228
= 0; _g_boolean_var_228; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "gtk_widget_get_mapped (GTK_WIDGET (item->canvas))"
); return (GDK_GRAB_NOT_VIEWABLE); } } while (0)
;
907
908 if (item->canvas->grabbed_item)
909 return GDK_GRAB_ALREADY_GRABBED;
910
911 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED))
912 return GDK_GRAB_NOT_VIEWABLE;
913
914 display = gtk_widget_get_display (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
915 seat = gdk_display_get_default_seat (display);
916
917 retval = gdk_seat_grab (seat,
918 gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)((((GtkLayout*) (void *) ((item->canvas)))))),
919 GDK_SEAT_CAPABILITY_ALL_POINTING,
920 FALSE(0),
921 cursor,
922 event,
923 seat_grab_prepare_window,
924 NULL((void*)0));
925
926 if (retval != GDK_GRAB_SUCCESS)
927 return retval;
928
929 item->canvas->grabbed_item = item;
930 item->canvas->grabbed_event_mask = event_mask;
931 item->canvas->current_item = item; /* So that events go to the grabbed item */
932
933 return retval;
934}
935
936/**
937 * eel_canvas_item_ungrab:
938 * @item: A canvas item that holds a grab.
939 *
940 * Ungrabs the item, which must have been grabbed in the canvas, and ungrabs the
941 * seat.
942 **/
943void
944eel_canvas_item_ungrab (EelCanvasItem *item)
945{
946 GdkDisplay *display;
947 GdkSeat *seat;
948
949 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_229
= 1; else _g_boolean_var_229 = 0; _g_boolean_var_229; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
950
951 if (item->canvas->grabbed_item != item)
952 return;
953
954 display = gtk_widget_get_display (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
955 seat = gdk_display_get_default_seat (display);
956
957 item->canvas->grabbed_item = NULL((void*)0);
958 gdk_seat_ungrab (seat);
959}
960
961/**
962 * eel_canvas_item_w2i:
963 * @item: A canvas item.
964 * @x: X coordinate to convert (input/output value).
965 * @y: Y coordinate to convert (input/output value).
966 *
967 * Converts a coordinate pair from world coordinates to item-relative
968 * coordinates.
969 **/
970void
971eel_canvas_item_w2i (EelCanvasItem *item, double *x, double *y)
972{
973 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_230
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_230
= 1; else _g_boolean_var_230 = 0; _g_boolean_var_230; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
974 g_return_if_fail (x != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (x != ((void*)0)) _g_boolean_var_231 = 1; else _g_boolean_var_231
= 0; _g_boolean_var_231; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "x != NULL"); return; } }
while (0)
;
975 g_return_if_fail (y != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_232
; if (y != ((void*)0)) _g_boolean_var_232 = 1; else _g_boolean_var_232
= 0; _g_boolean_var_232; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "y != NULL"); return; } }
while (0)
;
976
977 item = item->parent;
978 while (item)
979 {
980 if (EEL_IS_CANVAS_GROUP (item)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(item)); GType __t = ((eel_canvas_group_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; }))))
)
981 {
982 *x -= EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->xpos;
983 *y -= EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->ypos;
984 }
985
986 item = item->parent;
987 }
988}
989
990
991/**
992 * eel_canvas_item_i2w:
993 * @item: A canvas item.
994 * @x: X coordinate to convert (input/output value).
995 * @y: Y coordinate to convert (input/output value).
996 *
997 * Converts a coordinate pair from item-relative coordinates to world
998 * coordinates.
999 **/
1000void
1001eel_canvas_item_i2w (EelCanvasItem *item, double *x, double *y)
1002{
1003 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_233
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_233
= 1; else _g_boolean_var_233 = 0; _g_boolean_var_233; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1004 g_return_if_fail (x != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_234
; if (x != ((void*)0)) _g_boolean_var_234 = 1; else _g_boolean_var_234
= 0; _g_boolean_var_234; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "x != NULL"); return; } }
while (0)
;
1005 g_return_if_fail (y != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_235
; if (y != ((void*)0)) _g_boolean_var_235 = 1; else _g_boolean_var_235
= 0; _g_boolean_var_235; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "y != NULL"); return; } }
while (0)
;
1006
1007 item = item->parent;
1008 while (item)
1009 {
1010 if (EEL_IS_CANVAS_GROUP (item)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(item)); GType __t = ((eel_canvas_group_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; }))))
)
1011 {
1012 *x += EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->xpos;
1013 *y += EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->ypos;
1014 }
1015
1016 item = item->parent;
1017 }
1018}
1019
1020/* Returns whether the item is an inferior of or is equal to the parent. */
1021static int
1022is_descendant (EelCanvasItem *item, EelCanvasItem *parent)
1023{
1024 for (; item; item = item->parent)
1025 if (item == parent)
1026 return TRUE(!(0));
1027
1028 return FALSE(0);
1029}
1030
1031/**
1032 * eel_canvas_item_reparent:
1033 * @item: A canvas item.
1034 * @new_group: A canvas group.
1035 *
1036 * Changes the parent of the specified item to be the new group. The item keeps
1037 * its group-relative coordinates as for its old parent, so the item may change
1038 * its absolute position within the canvas.
1039 **/
1040void
1041eel_canvas_item_reparent (EelCanvasItem *item, EelCanvasGroup *new_group)
1042{
1043 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_236
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_236
= 1; else _g_boolean_var_236 = 0; _g_boolean_var_236; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1044 g_return_if_fail (EEL_IS_CANVAS_GROUP (new_group))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_237
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_group)); GType __t = ((eel_canvas_group_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
("Eel", ((const char*) (__func__)), "EEL_IS_CANVAS_GROUP (new_group)"
); return; } } while (0)
;
1045
1046 /* Both items need to be in the same canvas */
1047 g_return_if_fail (item->canvas == EEL_CANVAS_ITEM (new_group)->canvas)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_238
; if (item->canvas == ((((EelCanvasItem*) (void *) ((new_group
)))))->canvas) _g_boolean_var_238 = 1; else _g_boolean_var_238
= 0; _g_boolean_var_238; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "item->canvas == EEL_CANVAS_ITEM (new_group)->canvas"
); return; } } while (0)
;
1048
1049 /* The group cannot be an inferior of the item or be the item itself --
1050 * this also takes care of the case where the item is the root item of
1051 * the canvas. */
1052 g_return_if_fail (!is_descendant (EEL_CANVAS_ITEM (new_group), item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_239
; if (!is_descendant (((((EelCanvasItem*) (void *) ((new_group
))))), item)) _g_boolean_var_239 = 1; else _g_boolean_var_239
= 0; _g_boolean_var_239; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "!is_descendant (EEL_CANVAS_ITEM (new_group), item)"
); return; } } while (0)
;
1053
1054 /* Everything is ok, now actually reparent the item */
1055
1056 g_object_ref (G_OBJECT (item))((__typeof__ (((((GObject*) (void *) ((item))))))) (g_object_ref
) (((((GObject*) (void *) ((item)))))))
; /* protect it from the unref in group_remove */
1057
1058 eel_canvas_item_request_redraw (item);
1059
1060 group_remove (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent))))), item);
1061 item->parent = EEL_CANVAS_ITEM (new_group)((((EelCanvasItem*) (void *) ((new_group)))));
1062 /* item->canvas is unchanged. */
1063 group_add (new_group, item);
1064
1065 /* Redraw and repick */
1066
1067 redraw_and_repick_if_mapped (item);
1068
1069 g_object_unref (G_OBJECT (item)((((GObject*) (void *) ((item))))));
1070}
1071
1072/**
1073 * eel_canvas_item_grab_focus:
1074 * @item: A canvas item.
1075 *
1076 * Makes the specified item take the keyboard focus, so all keyboard events will
1077 * be sent to it. If the canvas widget itself did not have the focus, it grabs
1078 * it as well.
1079 **/
1080void
1081eel_canvas_item_grab_focus (EelCanvasItem *item)
1082{
1083 EelCanvasItem *focused_item;
1084 GdkEvent ev;
1085
1086 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_240
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_240
= 1; else _g_boolean_var_240 = 0; _g_boolean_var_240; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1087 g_return_if_fail (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas)))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_241
; if (gtk_widget_get_can_focus (((((GtkWidget*) (void *) ((item
->canvas))))))) _g_boolean_var_241 = 1; else _g_boolean_var_241
= 0; _g_boolean_var_241; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "gtk_widget_get_can_focus (GTK_WIDGET (item->canvas))"
); return; } } while (0)
;
1088
1089 focused_item = item->canvas->focused_item;
1090
1091 if (focused_item)
1092 {
1093 ev.focus_change.type = GDK_FOCUS_CHANGE;
1094 ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)((((GtkLayout*) (void *) ((item->canvas))))));
1095 ev.focus_change.send_event = FALSE(0);
1096 ev.focus_change.in = FALSE(0);
1097
1098 emit_event (item->canvas, &ev);
1099 }
1100
1101 item->canvas->focused_item = item;
1102 gtk_widget_grab_focus (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
1103
1104 if (focused_item)
1105 {
1106 ev.focus_change.type = GDK_FOCUS_CHANGE;
1107 ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)((((GtkLayout*) (void *) ((item->canvas))))));
1108 ev.focus_change.send_event = FALSE(0);
1109 ev.focus_change.in = TRUE(!(0));
1110
1111 emit_event (item->canvas, &ev);
1112 }
1113}
1114
1115
1116/**
1117 * eel_canvas_item_get_bounds:
1118 * @item: A canvas item.
1119 * @x1: Leftmost edge of the bounding box (return value).
1120 * @y1: Upper edge of the bounding box (return value).
1121 * @x2: Rightmost edge of the bounding box (return value).
1122 * @y2: Lower edge of the bounding box (return value).
1123 *
1124 * Queries the bounding box of a canvas item. The bounds are returned in the
1125 * coordinate system of the item's parent.
1126 **/
1127void
1128eel_canvas_item_get_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
1129{
1130 double tx1, ty1, tx2, ty2;
1131
1132 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_242
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_242
= 1; else _g_boolean_var_242 = 0; _g_boolean_var_242; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1133
1134 tx1 = ty1 = tx2 = ty2 = 0.0;
1135
1136 /* Get the item's bounds in its coordinate system */
1137
1138 if (EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->bounds)
1139 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->bounds) (item, &tx1, &ty1, &tx2, &ty2);
1140
1141 /* Return the values */
1142
1143 if (x1)
1144 *x1 = tx1;
1145
1146 if (y1)
1147 *y1 = ty1;
1148
1149 if (x2)
1150 *x2 = tx2;
1151
1152 if (y2)
1153 *y2 = ty2;
1154}
1155
1156
1157/**
1158 * eel_canvas_item_request_update
1159 * @item: A canvas item.
1160 *
1161 * To be used only by item implementations. Requests that the canvas queue an
1162 * update for the specified item.
1163 **/
1164void
1165eel_canvas_item_request_update (EelCanvasItem *item)
1166{
1167 if (NULL((void*)0) == item->canvas)
1168 return;
1169
1170 g_return_if_fail (!item->canvas->doing_update)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_243
; if (!item->canvas->doing_update) _g_boolean_var_243 =
1; else _g_boolean_var_243 = 0; _g_boolean_var_243; }), 1)))
{ } else { g_return_if_fail_warning ("Eel", ((const char*) (
__func__)), "!item->canvas->doing_update"); return; } }
while (0)
;
1171
1172 if (item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)
1173 return;
1174
1175 item->flags |= EEL_CANVAS_ITEM_NEED_UPDATE;
1176
1177 if (item->parent != NULL((void*)0))
1178 {
1179 /* Recurse up the tree */
1180 eel_canvas_item_request_update (item->parent);
1181 }
1182 else
1183 {
1184 /* Have reached the top of the tree, make sure the update call gets scheduled. */
1185 eel_canvas_request_update (item->canvas);
1186 }
1187}
1188
1189/**
1190 * eel_canvas_item_request_update
1191 * @item: A canvas item.
1192 *
1193 * Convenience function that informs a canvas that the specified item needs
1194 * to be repainted. To be used by item implementations
1195 **/
1196void
1197eel_canvas_item_request_redraw (EelCanvasItem *item)
1198{
1199 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
1200 eel_canvas_request_redraw (item->canvas,
1201 item->x1, item->y1,
1202 item->x2 + 1, item->y2 + 1);
1203}
1204
1205
1206
1207/*** EelCanvasGroup ***/
1208
1209
1210enum
1211{
1212 GROUP_PROP_0,
1213 GROUP_PROP_X,
1214 GROUP_PROP_Y
1215};
1216
1217
1218static void eel_canvas_group_class_init (EelCanvasGroupClass *klass);
1219static void eel_canvas_group_init (EelCanvasGroup *group);
1220static void eel_canvas_group_set_property(GObject *object,
1221 guint param_id,
1222 const GValue *value,
1223 GParamSpec *pspec);
1224static void eel_canvas_group_get_property(GObject *object,
1225 guint param_id,
1226 GValue *value,
1227 GParamSpec *pspec);
1228
1229static void eel_canvas_group_destroy (EelCanvasItem *object);
1230
1231static void eel_canvas_group_update (EelCanvasItem *item,
1232 double i2w_dx,
1233 double i2w_dy,
1234 int flags);
1235static void eel_canvas_group_unrealize (EelCanvasItem *item);
1236static void eel_canvas_group_map (EelCanvasItem *item);
1237static void eel_canvas_group_unmap (EelCanvasItem *item);
1238static void eel_canvas_group_draw (EelCanvasItem *item,
1239 cairo_t *cr,
1240 cairo_region_t *region);
1241static double eel_canvas_group_point (EelCanvasItem *item, double x, double y,
1242 int cx, int cy,
1243 EelCanvasItem **actual_item);
1244static void eel_canvas_group_translate (EelCanvasItem *item, double dx, double dy);
1245static void eel_canvas_group_bounds (EelCanvasItem *item, double *x1, double *y1,
1246 double *x2, double *y2);
1247
1248
1249static EelCanvasItemClass *group_parent_class;
1250
1251
1252/**
1253 * eel_canvas_group_get_type:
1254 *
1255 * Registers the &EelCanvasGroup class if necessary, and returns the type ID
1256 * associated to it.
1257 *
1258 * Return value: The type ID of the &EelCanvasGroup class.
1259 **/
1260GType
1261eel_canvas_group_get_type (void)
1262{
1263 static GType group_type = 0;
1264
1265 if (!group_type)
1266 {
1267 static const GTypeInfo group_info =
1268 {
1269 sizeof (EelCanvasGroupClass),
1270 (GBaseInitFunc) NULL((void*)0),
1271 (GBaseFinalizeFunc) NULL((void*)0),
1272 (GClassInitFunc) eel_canvas_group_class_init,
1273 NULL((void*)0), /* class_finalize */
1274 NULL((void*)0), /* class_data */
1275 sizeof (EelCanvasGroup),
1276 0, /* n_preallocs */
1277 (GInstanceInitFunc) eel_canvas_group_init
1278
1279
1280 };
1281
1282 group_type = g_type_register_static (eel_canvas_item_get_type (),
1283 "EelCanvasGroup",
1284 &group_info,
1285 0);
1286 }
1287
1288 return group_type;
1289}
1290
1291/* Class initialization function for EelCanvasGroupClass */
1292static void
1293eel_canvas_group_class_init (EelCanvasGroupClass *klass)
1294{
1295 GObjectClass *gobject_class;
1296 EelCanvasItemClass *item_class;
1297
1298 gobject_class = (GObjectClass *) klass;
1299 item_class = (EelCanvasItemClass *) klass;
1300
1301 group_parent_class = g_type_class_peek_parent (klass);
1302
1303 gobject_class->set_property = eel_canvas_group_set_property;
1304 gobject_class->get_property = eel_canvas_group_get_property;
1305
1306 g_object_class_install_property
1307 (gobject_class, GROUP_PROP_X,
1308 g_param_spec_double ("x",
1309 _("X")((char *) g_dgettext ("caja", "X")),
1310 _("X")((char *) g_dgettext ("caja", "X")),
1311 -G_MAXDOUBLE1.7976931348623157e+308, G_MAXDOUBLE1.7976931348623157e+308, 0.0,
1312 G_PARAM_READWRITE));
1313 g_object_class_install_property
1314 (gobject_class, GROUP_PROP_Y,
1315 g_param_spec_double ("y",
1316 _("Y")((char *) g_dgettext ("caja", "Y")),
1317 _("Y")((char *) g_dgettext ("caja", "Y")),
1318 -G_MAXDOUBLE1.7976931348623157e+308, G_MAXDOUBLE1.7976931348623157e+308, 0.0,
1319 G_PARAM_READWRITE));
1320
1321 item_class->destroy = eel_canvas_group_destroy;
1322 item_class->update = eel_canvas_group_update;
1323 item_class->unrealize = eel_canvas_group_unrealize;
1324 item_class->map = eel_canvas_group_map;
1325 item_class->unmap = eel_canvas_group_unmap;
1326 item_class->draw = eel_canvas_group_draw;
1327 item_class->point = eel_canvas_group_point;
1328 item_class->translate = eel_canvas_group_translate;
1329 item_class->bounds = eel_canvas_group_bounds;
1330}
1331
1332/* Object initialization function for EelCanvasGroup */
1333static void
1334eel_canvas_group_init (EelCanvasGroup *group)
1335{
1336 group->xpos = 0.0;
1337 group->ypos = 0.0;
1338}
1339
1340/* Set_property handler for canvas groups */
1341static void
1342eel_canvas_group_set_property (GObject *gobject, guint param_id,
1343 const GValue *value, GParamSpec *pspec)
1344{
1345 EelCanvasItem *item;
1346 EelCanvasGroup *group;
1347 double old;
1348 gboolean moved;
1349
1350 g_return_if_fail (EEL_IS_CANVAS_GROUP (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_group_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 ("Eel", ((const
char*) (__func__)), "EEL_IS_CANVAS_GROUP (gobject)"); return
; } } while (0)
;
1351
1352 item = EEL_CANVAS_ITEM (gobject)((((EelCanvasItem*) (void *) ((gobject)))));
1353 group = EEL_CANVAS_GROUP (gobject)((((EelCanvasGroup*) (void *) ((gobject)))));
1354
1355 moved = FALSE(0);
1356 switch (param_id)
1357 {
1358 case GROUP_PROP_X:
1359 old = group->xpos;
1360 group->xpos = g_value_get_double (value);
1361 if (old != group->xpos)
1362 moved = TRUE(!(0));
1363 break;
1364
1365 case GROUP_PROP_Y:
1366 old = group->ypos;
1367 group->ypos = g_value_get_double (value);
1368 if (old != group->ypos)
1369 moved = TRUE(!(0));
1370 break;
1371
1372 default:
1373 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 1373, ("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)
;
1374 break;
1375 }
1376
1377 if (moved)
1378 {
1379 item->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
1380 if (item->parent != NULL((void*)0))
1381 eel_canvas_item_request_update (item->parent);
1382 else
1383 eel_canvas_request_update (item->canvas);
1384 }
1385}
1386
1387/* Get_property handler for canvas groups */
1388static void
1389eel_canvas_group_get_property (GObject *gobject, guint param_id,
1390 GValue *value, GParamSpec *pspec)
1391{
1392 EelCanvasGroup *group;
1393
1394 g_return_if_fail (EEL_IS_CANVAS_GROUP (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_245
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_group_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 ("Eel", ((const
char*) (__func__)), "EEL_IS_CANVAS_GROUP (gobject)"); return
; } } while (0)
;
1395
1396 group = EEL_CANVAS_GROUP (gobject)((((EelCanvasGroup*) (void *) ((gobject)))));
1397
1398 switch (param_id)
1399 {
1400 case GROUP_PROP_X:
1401 g_value_set_double (value, group->xpos);
1402 break;
1403
1404 case GROUP_PROP_Y:
1405 g_value_set_double (value, group->ypos);
1406 break;
1407
1408 default:
1409 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 1409, ("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)
;
1410 break;
1411 }
1412}
1413
1414/* Destroy handler for canvas groups */
1415static void
1416eel_canvas_group_destroy (EelCanvasItem *object)
1417{
1418 EelCanvasGroup *group;
1419 GList *list;
1420 EelCanvasItem *child = NULL((void*)0);
1421
1422 g_return_if_fail (EEL_IS_CANVAS_GROUP (object))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_246
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eel_canvas_group_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (object)"); return; } } while
(0)
;
1423
1424 group = EEL_CANVAS_GROUP (object)((((EelCanvasGroup*) (void *) ((object)))));
1425
1426 list = group->item_list;
1427 while (list)
1428 {
1429 child = list->data;
1430 list = list->next;
1431
1432 eel_canvas_item_destroy (child);
1433 }
1434
1435 if (EEL_CANVAS_ITEM_CLASS (group_parent_class)((((EelCanvasItemClass*) (void *) ((group_parent_class)))))->destroy)
1436 (* EEL_CANVAS_ITEM_CLASS (group_parent_class)((((EelCanvasItemClass*) (void *) ((group_parent_class)))))->destroy) (object);
1437}
1438
1439/* Update handler for canvas groups */
1440static void
1441eel_canvas_group_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags)
1442{
1443 EelCanvasGroup *group;
1444 GList *list;
1445 EelCanvasItem *i;
1446 double bbox_x0, bbox_y0, bbox_x1, bbox_y1;
1447 gboolean first = TRUE(!(0));
1448
1449 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1450
1451 (* group_parent_class->update) (item, i2w_dx, i2w_dy, flags);
1452
1453 bbox_x0 = 0;
1454 bbox_y0 = 0;
1455 bbox_x1 = 0;
1456 bbox_y1 = 0;
1457
1458 for (list = group->item_list; list; list = list->next)
1459 {
1460 i = list->data;
1461
1462 eel_canvas_item_invoke_update (i, i2w_dx + group->xpos, i2w_dy + group->ypos, flags);
1463
1464 if (first)
1465 {
1466 first = FALSE(0);
1467 bbox_x0 = i->x1;
1468 bbox_y0 = i->y1;
1469 bbox_x1 = i->x2;
1470 bbox_y1 = i->y2;
1471 }
1472 else
1473 {
1474 bbox_x0 = MIN (bbox_x0, i->x1)(((bbox_x0) < (i->x1)) ? (bbox_x0) : (i->x1));
1475 bbox_y0 = MIN (bbox_y0, i->y1)(((bbox_y0) < (i->y1)) ? (bbox_y0) : (i->y1));
1476 bbox_x1 = MAX (bbox_x1, i->x2)(((bbox_x1) > (i->x2)) ? (bbox_x1) : (i->x2));
1477 bbox_y1 = MAX (bbox_y1, i->y2)(((bbox_y1) > (i->y2)) ? (bbox_y1) : (i->y2));
1478 }
1479 }
1480 item->x1 = bbox_x0;
1481 item->y1 = bbox_y0;
1482 item->x2 = bbox_x1;
1483 item->y2 = bbox_y1;
1484}
1485
1486/* Unrealize handler for canvas groups */
1487static void
1488eel_canvas_group_unrealize (EelCanvasItem *item)
1489{
1490 EelCanvasGroup *group;
1491 GList *list;
1492 EelCanvasItem *i = NULL((void*)0);
1493
1494 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1495
1496 /* Unmap group before children to avoid flash */
1497 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
1498 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
1499
1500 for (list = group->item_list; list; list = list->next)
1501 {
1502 i = list->data;
1503
1504 if (i->flags & EEL_CANVAS_ITEM_REALIZED)
1505 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->unrealize) (i);
1506 }
1507
1508 (* group_parent_class->unrealize) (item);
1509}
1510
1511/* Map handler for canvas groups */
1512static void
1513eel_canvas_group_map (EelCanvasItem *item)
1514{
1515 EelCanvasGroup *group;
1516 GList *list;
1517 EelCanvasItem *i = NULL((void*)0);
1518
1519 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1520
1521 for (list = group->item_list; list; list = list->next)
1522 {
1523 i = list->data;
1524
1525 if (i->flags & EEL_CANVAS_ITEM_VISIBLE &&
1526 !(i->flags & EEL_CANVAS_ITEM_MAPPED))
1527 {
1528 if (!(i->flags & EEL_CANVAS_ITEM_REALIZED))
1529 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->realize) (i);
1530
1531 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->map) (i);
1532 }
1533 }
1534
1535 (* group_parent_class->map) (item);
1536}
1537
1538/* Unmap handler for canvas groups */
1539static void
1540eel_canvas_group_unmap (EelCanvasItem *item)
1541{
1542 EelCanvasGroup *group;
1543 GList *list;
1544 EelCanvasItem *i = NULL((void*)0);
1545
1546 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1547
1548 for (list = group->item_list; list; list = list->next)
1549 {
1550 i = list->data;
1551
1552 if (i->flags & EEL_CANVAS_ITEM_MAPPED)
1553 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->unmap) (i);
1554 }
1555
1556 (* group_parent_class->unmap) (item);
1557}
1558
1559/* Draw handler for canvas groups */
1560static void
1561eel_canvas_group_draw (EelCanvasItem *item,
1562 cairo_t *cr,
1563 cairo_region_t *region)
1564{
1565 EelCanvasGroup *group;
1566 GList *list;
1567 EelCanvasItem *child = NULL((void*)0);
1568
1569 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1570
1571 for (list = group->item_list; list; list = list->next)
1572 {
1573 child = list->data;
1574
1575 if ((child->flags & EEL_CANVAS_ITEM_MAPPED) &&
1576 (EEL_CANVAS_ITEM_GET_CLASS (child)((((EelCanvasItemClass*) (((GTypeInstance*) ((child)))->g_class
))))
->draw))
1577 {
1578 GdkRectangle child_rect;
1579
1580 child_rect.x = child->x1;
1581 child_rect.y = child->y1;
1582 child_rect.width = child->x2 - child->x1 + 1;
1583 child_rect.height = child->y2 - child->y1 + 1;
1584
1585 if (cairo_region_contains_rectangle (region, &child_rect) != CAIRO_REGION_OVERLAP_OUT)
1586 EEL_CANVAS_ITEM_GET_CLASS (child)((((EelCanvasItemClass*) (((GTypeInstance*) ((child)))->g_class
))))
->draw (child, cr, region);
1587 }
1588 }
1589}
1590
1591/* Point handler for canvas groups */
1592static double
1593eel_canvas_group_point (EelCanvasItem *item, double x, double y, int cx, int cy,
1594 EelCanvasItem **actual_item)
1595{
1596 int x1, y1, x2, y2;
1597 double gx, gy;
1598 double dist, best;
1599 int has_point;
1600 EelCanvasGroup *group;
1601 GList *list;
1602 EelCanvasItem *point_item;
1603 EelCanvasItem *child = NULL((void*)0);
1604
1605 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1606
1607 x1 = cx - item->canvas->close_enough;
1608 y1 = cy - item->canvas->close_enough;
1609 x2 = cx + item->canvas->close_enough;
1610 y2 = cy + item->canvas->close_enough;
1611
1612 best = 0.0;
1613 *actual_item = NULL((void*)0);
1614
1615 gx = x - group->xpos;
1616 gy = y - group->ypos;
1617
1618 dist = 0.0; /* keep gcc happy */
1619
1620 for (list = group->item_list; list; list = list->next)
1621 {
1622 child = list->data;
1623
1624 if ((child->x1 > x2) || (child->y1 > y2) || (child->x2 < x1) || (child->y2 < y1))
1625 continue;
1626
1627 point_item = NULL((void*)0); /* cater for incomplete item implementations */
1628
1629 if ((child->flags & EEL_CANVAS_ITEM_MAPPED)
1630 && EEL_CANVAS_ITEM_GET_CLASS (child)((((EelCanvasItemClass*) (((GTypeInstance*) ((child)))->g_class
))))
->point)
1631 {
1632 dist = eel_canvas_item_invoke_point (child, gx, gy, cx, cy, &point_item);
1633 has_point = TRUE(!(0));
1634 }
1635 else
1636 has_point = FALSE(0);
1637
1638 if (has_point
1639 && point_item
1640 && ((int) (dist * item->canvas->pixels_per_unit + 0.5)
1641 <= item->canvas->close_enough))
1642 {
1643 best = dist;
1644 *actual_item = point_item;
1645 }
1646 }
1647
1648 return best;
1649}
1650
1651void
1652eel_canvas_group_translate (EelCanvasItem *item, double dx, double dy)
1653{
1654 EelCanvasGroup *group;
1655
1656 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1657
1658 group->xpos += dx;
1659 group->ypos += dy;
1660}
1661
1662/* Bounds handler for canvas groups */
1663static void
1664eel_canvas_group_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
1665{
1666 EelCanvasGroup *group;
1667 EelCanvasItem *child;
1668 GList *list;
1669 double tx1, ty1, tx2, ty2;
1670 double minx, miny, maxx, maxy;
1671 int set;
1672
1673 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1674
1675 /* Get the bounds of the first visible item */
1676
1677 child = NULL((void*)0); /* Unnecessary but eliminates a warning. */
1678
1679 set = FALSE(0);
1680
1681 for (list = group->item_list; list; list = list->next)
1682 {
1683 child = list->data;
1684
1685 if (child->flags & EEL_CANVAS_ITEM_MAPPED)
1686 {
1687 set = TRUE(!(0));
1688 eel_canvas_item_get_bounds (child, &minx, &miny, &maxx, &maxy);
1689 break;
1690 }
1691 }
1692
1693 /* If there were no visible items, return an empty bounding box */
1694
1695 if (!set)
1696 {
1697 *x1 = *y1 = *x2 = *y2 = 0.0;
1698 return;
1699 }
1700
1701 /* Now we can grow the bounds using the rest of the items */
1702
1703 list = list->next;
1704
1705 for (; list; list = list->next)
1706 {
1707 child = list->data;
1708
1709 if (!(child->flags & EEL_CANVAS_ITEM_MAPPED))
1710 continue;
1711
1712 eel_canvas_item_get_bounds (child, &tx1, &ty1, &tx2, &ty2);
1713
1714 if (tx1 < minx)
1715 minx = tx1;
1716
1717 if (ty1 < miny)
1718 miny = ty1;
1719
1720 if (tx2 > maxx)
1721 maxx = tx2;
1722
1723 if (ty2 > maxy)
1724 maxy = ty2;
1725 }
1726
1727 /* Make the bounds be relative to our parent's coordinate system */
1728
1729 if (item->parent)
1730 {
1731 minx += group->xpos;
1732 miny += group->ypos;
1733 maxx += group->xpos;
1734 maxy += group->ypos;
1735 }
1736
1737 *x1 = minx;
1738 *y1 = miny;
1739 *x2 = maxx;
1740 *y2 = maxy;
1741}
1742
1743/* Adds an item to a group */
1744static void
1745group_add (EelCanvasGroup *group, EelCanvasItem *item)
1746{
1747 g_object_ref_sink (item)((__typeof__ (item)) (g_object_ref_sink) (item));
1748
1749 if (!group->item_list)
1750 {
1751 group->item_list = g_list_append (group->item_list, item);
1752 group->item_list_end = group->item_list;
1753 }
1754 else
1755 group->item_list_end = g_list_append (group->item_list_end, item)->next;
1756
1757 if (item->flags & EEL_CANVAS_ITEM_VISIBLE &&
1758 group->item.flags & EEL_CANVAS_ITEM_MAPPED)
1759 {
1760 if (!(item->flags & EEL_CANVAS_ITEM_REALIZED))
1761 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->realize) (item);
1762
1763 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED))
1764 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->map) (item);
1765 }
1766
1767 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
1768 eel_canvas_queue_resize (EEL_CANVAS_ITEM (group)((((EelCanvasItem*) (void *) ((group)))))->canvas);
1769}
1770
1771/* Removes an item from a group */
1772static void
1773group_remove (EelCanvasGroup *group, EelCanvasItem *item)
1774{
1775 GList *children;
1776
1777 g_return_if_fail (EEL_IS_CANVAS_GROUP (group))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_247
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((group)); GType __t = ((eel_canvas_group_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (group)"); return; } } while
(0)
;
1778 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_248
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_248
= 1; else _g_boolean_var_248 = 0; _g_boolean_var_248; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1779
1780 for (children = group->item_list; children; children = children->next)
1781 if (children->data == item)
1782 {
1783 if (item->flags & EEL_CANVAS_ITEM_MAPPED) {
1784 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
1785 }
1786
1787 if (item->flags & EEL_CANVAS_ITEM_REALIZED)
1788 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unrealize) (item);
1789
1790 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
1791 eel_canvas_queue_resize (item->canvas);
1792
1793 /* Unparent the child */
1794
1795 item->parent = NULL((void*)0);
1796 /* item->canvas = NULL; */
1797 g_object_unref (G_OBJECT (item)((((GObject*) (void *) ((item))))));
1798
1799 /* Remove it from the list */
1800
1801 if (children == group->item_list_end)
1802 group->item_list_end = children->prev;
1803
1804 group->item_list = g_list_remove_link (group->item_list, children);
1805 g_list_free (children);
1806 break;
1807 }
1808}
1809
1810
1811/*** EelCanvas ***/
1812
1813
1814enum
1815{
1816 DRAW_BACKGROUND,
1817 LAST_SIGNAL
1818};
1819
1820static void eel_canvas_class_init (EelCanvasClass *klass);
1821static void eel_canvas_init (EelCanvas *canvas);
1822static void eel_canvas_destroy (GtkWidget *object);
1823static void eel_canvas_map (GtkWidget *widget);
1824static void eel_canvas_unmap (GtkWidget *widget);
1825static void eel_canvas_realize (GtkWidget *widget);
1826static void eel_canvas_unrealize (GtkWidget *widget);
1827static void eel_canvas_size_allocate (GtkWidget *widget,
1828 GtkAllocation *allocation);
1829static gint eel_canvas_button (GtkWidget *widget,
1830 GdkEventButton *event);
1831static gint eel_canvas_motion (GtkWidget *widget,
1832 GdkEventMotion *event);
1833static gint eel_canvas_draw (GtkWidget *widget,
1834 cairo_t *cr);
1835static gint eel_canvas_key (GtkWidget *widget,
1836 GdkEventKey *event);
1837static gint eel_canvas_crossing (GtkWidget *widget,
1838 GdkEventCrossing *event);
1839static gint eel_canvas_focus_in (GtkWidget *widget,
1840 GdkEventFocus *event);
1841static gint eel_canvas_focus_out (GtkWidget *widget,
1842 GdkEventFocus *event);
1843static void eel_canvas_request_update_real (EelCanvas *canvas);
1844static void eel_canvas_draw_background (EelCanvas *canvas,
1845 cairo_t *cr);
1846
1847static GtkLayoutClass *canvas_parent_class;
1848
1849static guint canvas_signals[LAST_SIGNAL] = { 0 };
1850
1851/**
1852 * eel_canvas_get_type:
1853 *
1854 * Registers the &EelCanvas class if necessary, and returns the type ID
1855 * associated to it.
1856 *
1857 * Return value: The type ID of the &EelCanvas class.
1858 **/
1859GType
1860eel_canvas_get_type (void)
1861{
1862 static GType canvas_type = 0;
1863
1864 if (!canvas_type)
1865 {
1866 static const GTypeInfo canvas_info =
1867 {
1868 sizeof (EelCanvasClass),
1869 (GBaseInitFunc) NULL((void*)0),
1870 (GBaseFinalizeFunc) NULL((void*)0),
1871 (GClassInitFunc) eel_canvas_class_init,
1872 NULL((void*)0), /* class_finalize */
1873 NULL((void*)0), /* class_data */
1874 sizeof (EelCanvas),
1875 0, /* n_preallocs */
1876 (GInstanceInitFunc) eel_canvas_init
1877 };
1878
1879 canvas_type = g_type_register_static (gtk_layout_get_type (),
1880 "EelCanvas",
1881 &canvas_info,
1882 0);
1883 }
1884
1885 return canvas_type;
1886}
1887
1888static void
1889eel_canvas_get_property (GObject *object,
1890 guint prop_id,
1891 GValue *value,
1892 GParamSpec *pspec)
1893{
1894 switch (prop_id)
1895 {
1896 default:
1897 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'"
, "eel-canvas.c", 1897, ("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)
;
1898 break;
1899 }
1900}
1901
1902static void
1903eel_canvas_set_property (GObject *object,
1904 guint prop_id,
1905 const GValue *value,
1906 GParamSpec *pspec)
1907{
1908 switch (prop_id)
1909 {
1910 default:
1911 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'"
, "eel-canvas.c", 1911, ("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)
;
1912 break;
1913 }
1914}
1915
1916static void
1917eel_canvas_accessible_adjustment_changed (GtkAdjustment *adjustment,
1918 gpointer data)
1919{
1920 AtkObject *atk_obj;
1921
1922 /* The scrollbars have changed */
1923 atk_obj = ATK_OBJECT (data)((((AtkObject*) (void *) ((data)))));
1924
1925 g_signal_emit_by_name (atk_obj, "visible_data_changed");
1926}
1927
1928static void
1929eel_canvas_accessible_initialize (AtkObject *obj,
1930 gpointer data)
1931{
1932 EelCanvas *canvas;
1933
1934 if (ATK_OBJECT_CLASS (accessible_parent_class)((((AtkObjectClass*) (void *) ((accessible_parent_class)))))->initialize != NULL((void*)0))
1935 ATK_OBJECT_CLASS (accessible_parent_class)((((AtkObjectClass*) (void *) ((accessible_parent_class)))))->initialize (obj, data);
1936
1937 canvas = EEL_CANVAS (data)((((EelCanvas*) (void *) ((data)))));
1938 g_signal_connect (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)),g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1939 "value_changed",g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1940 G_CALLBACK (eel_canvas_accessible_adjustment_changed),g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1941 obj)g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
;
1942 g_signal_connect (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)),g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1943 "value_changed",g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1944 G_CALLBACK (eel_canvas_accessible_adjustment_changed),g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1945 obj)g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
;
1946
1947 obj->role = ATK_ROLE_LAYERED_PANE;
1948}
1949
1950static gint
1951eel_canvas_accessible_get_n_children (AtkObject* obj)
1952{
1953 GtkAccessible *accessible;
1954 GtkWidget *widget;
1955 EelCanvas *canvas;
1956 EelCanvasGroup *root_group;
1957
1958 accessible = GTK_ACCESSIBLE (obj)((((GtkAccessible*) (void *) ((obj)))));
1959 widget = gtk_accessible_get_widget (accessible);
1960 if (widget == NULL((void*)0))
1961 {
1962 /* State is defunct */
1963 return 0;
1964 }
1965
1966 g_return_val_if_fail (EEL_IS_CANVAS (widget), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_249
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_249
= 1; else _g_boolean_var_249 = 0; _g_boolean_var_249; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return (0); } } while
(0)
;
1967
1968 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
1969 root_group = eel_canvas_root (canvas);
1970 g_return_val_if_fail (root_group, 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_250
; if (root_group) _g_boolean_var_250 = 1; else _g_boolean_var_250
= 0; _g_boolean_var_250; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "root_group"); return (0
); } } while (0)
;
1971 return 1;
1972}
1973
1974static AtkObject*
1975eel_canvas_accessible_ref_child (AtkObject *obj,
1976 gint i)
1977{
1978 GtkAccessible *accessible;
1979 GtkWidget *widget;
1980 EelCanvas *canvas;
1981 EelCanvasGroup *root_group;
1982 AtkObject *atk_object;
1983
1984 /* Canvas only has one child, so return NULL if index is non zero */
1985 if (i != 0)
1986 {
1987 return NULL((void*)0);
1988 }
1989
1990 accessible = GTK_ACCESSIBLE (obj)((((GtkAccessible*) (void *) ((obj)))));
1991 widget = gtk_accessible_get_widget (accessible);
1992 if (widget == NULL((void*)0))
1993 {
1994 /* State is defunct */
1995 return NULL((void*)0);
1996 }
1997
1998 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
1999 root_group = eel_canvas_root (canvas);
2000 g_return_val_if_fail (root_group, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_251
; if (root_group) _g_boolean_var_251 = 1; else _g_boolean_var_251
= 0; _g_boolean_var_251; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "root_group"); return ((
(void*)0)); } } while (0)
;
2001 atk_object = atk_gobject_accessible_for_object (G_OBJECT (root_group)((((GObject*) (void *) ((root_group))))));
2002 g_object_ref (atk_object)((__typeof__ (atk_object)) (g_object_ref) (atk_object));
2003
2004 g_warning ("Accessible support for FooGroup needs to be implemented");
2005
2006 return atk_object;
2007}
2008
2009G_DEFINE_TYPE (EelCanvasAccessible, eel_canvas_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE)static void eel_canvas_accessible_init (EelCanvasAccessible *
self); static void eel_canvas_accessible_class_init (EelCanvasAccessibleClass
*klass); static GType eel_canvas_accessible_get_type_once (void
); static gpointer eel_canvas_accessible_parent_class = ((void
*)0); static gint EelCanvasAccessible_private_offset; static void
eel_canvas_accessible_class_intern_init (gpointer klass) { eel_canvas_accessible_parent_class
= g_type_class_peek_parent (klass); if (EelCanvasAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelCanvasAccessible_private_offset
); eel_canvas_accessible_class_init ((EelCanvasAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_canvas_accessible_get_instance_private (EelCanvasAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelCanvasAccessible_private_offset
)))); } GType eel_canvas_accessible_get_type (void) { static GType
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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_accessible_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType eel_canvas_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelCanvasAccessible"), sizeof (EelCanvasAccessibleClass), (
GClassInitFunc)(void (*)(void)) eel_canvas_accessible_class_intern_init
, sizeof (EelCanvasAccessible), (GInstanceInitFunc)(void (*)(
void)) eel_canvas_accessible_init, (GTypeFlags) 0); { {{};} }
return g_define_type_id; }
2010
2011static void
2012eel_canvas_accessible_class_init (EelCanvasAccessibleClass *klass)
2013{
2014 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
2015 accessible_parent_class = g_type_class_peek_parent (atk_class);
2016
2017 atk_class->initialize = eel_canvas_accessible_initialize;
2018 atk_class->get_n_children = eel_canvas_accessible_get_n_children;
2019 atk_class->ref_child = eel_canvas_accessible_ref_child;
2020}
2021
2022static void
2023eel_canvas_accessible_init (EelCanvasAccessible *accessible)
2024{
2025}
2026
2027/* Class initialization function for EelCanvasClass */
2028static void
2029eel_canvas_class_init (EelCanvasClass *klass)
2030{
2031 GObjectClass *gobject_class;
2032 GtkWidgetClass *widget_class;
2033
2034 gobject_class = (GObjectClass *)klass;
2035 widget_class = (GtkWidgetClass *) klass;
2036
2037 canvas_parent_class = g_type_class_peek_parent (klass);
2038
2039 gobject_class->set_property = eel_canvas_set_property;
2040 gobject_class->get_property = eel_canvas_get_property;
2041
2042 widget_class->destroy = eel_canvas_destroy;
2043 widget_class->map = eel_canvas_map;
2044 widget_class->unmap = eel_canvas_unmap;
2045 widget_class->realize = eel_canvas_realize;
2046 widget_class->unrealize = eel_canvas_unrealize;
2047 widget_class->size_allocate = eel_canvas_size_allocate;
2048 widget_class->button_press_event = eel_canvas_button;
2049 widget_class->button_release_event = eel_canvas_button;
2050 widget_class->motion_notify_event = eel_canvas_motion;
2051 widget_class->draw = eel_canvas_draw;
2052 widget_class->key_press_event = eel_canvas_key;
2053 widget_class->key_release_event = eel_canvas_key;
2054 widget_class->enter_notify_event = eel_canvas_crossing;
2055 widget_class->leave_notify_event = eel_canvas_crossing;
2056 widget_class->focus_in_event = eel_canvas_focus_in;
2057 widget_class->focus_out_event = eel_canvas_focus_out;
2058
2059 klass->draw_background = eel_canvas_draw_background;
2060 klass->request_update = eel_canvas_request_update_real;
2061
2062 canvas_signals[DRAW_BACKGROUND] =
2063 g_signal_new ("draw_background",
2064 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
2065 G_SIGNAL_RUN_LAST,
2066 G_STRUCT_OFFSET (EelCanvasClass, draw_background)((glong) __builtin_offsetof(EelCanvasClass, draw_background)),
2067 NULL((void*)0), NULL((void*)0),
2068 g_cclosure_marshal_VOID__BOXED,
2069 G_TYPE_NONE((GType) ((1) << (2))), 1,
2070 CAIRO_GOBJECT_TYPE_CONTEXTcairo_gobject_context_get_type ());
2071
2072 gtk_widget_class_set_accessible_type (widget_class, eel_canvas_accessible_get_type ());
2073}
2074
2075/* Callback used when the root item of a canvas is destroyed. The user should
2076 * never ever do this, so we panic if this happens.
2077 */
2078static void
2079panic_root_destroyed (GtkWidget *object, gpointer data)
2080{
2081 g_error ("Eeeek, root item %p of canvas %p was destroyed!", object, data);
2082}
2083
2084/* Object initialization function for EelCanvas */
2085static void
2086eel_canvas_init (EelCanvas *canvas)
2087{
2088 guint width, height;
2089 gtk_widget_set_can_focus (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))), TRUE(!(0)));
2090
2091 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))), FALSE(0));
2092
2093 canvas->scroll_x1 = 0.0;
2094 canvas->scroll_y1 = 0.0;
2095 gtk_layout_get_size (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas))))),
2096 &width, &height);
2097 canvas->scroll_x2 = width;
2098 canvas->scroll_y2 = height;
2099
2100 canvas->pixels_per_unit = 1.0;
2101
2102 canvas->pick_event.type = GDK_LEAVE_NOTIFY;
2103 canvas->pick_event.crossing.x = 0;
2104 canvas->pick_event.crossing.y = 0;
2105
2106 gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))), NULL((void*)0));
2107 gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))), NULL((void*)0));
2108
2109 /* Create the root item as a special case */
2110
2111 canvas->root = EEL_CANVAS_ITEM (g_object_new (eel_canvas_group_get_type (), NULL))((((EelCanvasItem*) (void *) ((g_object_new (eel_canvas_group_get_type
(), ((void*)0)))))))
;
2112 canvas->root->canvas = canvas;
2113
2114 g_object_ref_sink (canvas->root)((__typeof__ (canvas->root)) (g_object_ref_sink) (canvas->
root))
;
2115
2116 canvas->root_destroy_id = g_signal_connect (G_OBJECT (canvas->root),g_signal_connect_data ((((((GObject*) (void *) ((canvas->root
)))))), ("destroy"), (((GCallback) (panic_root_destroyed))), (
canvas), ((void*)0), (GConnectFlags) 0)
2117 "destroy", G_CALLBACK (panic_root_destroyed), canvas)g_signal_connect_data ((((((GObject*) (void *) ((canvas->root
)))))), ("destroy"), (((GCallback) (panic_root_destroyed))), (
canvas), ((void*)0), (GConnectFlags) 0)
;
2118
2119 canvas->need_repick = TRUE(!(0));
2120 canvas->doing_update = FALSE(0);
2121}
2122
2123/* Convenience function to remove the idle handler of a canvas */
2124static void
2125remove_idle (EelCanvas *canvas)
2126{
2127 if (canvas->idle_id == 0)
2128 return;
2129
2130 g_source_remove (canvas->idle_id);
2131 canvas->idle_id = 0;
2132}
2133
2134/* Removes the transient state of the canvas (idle handler, grabs). */
2135static void
2136shutdown_transients (EelCanvas *canvas)
2137{
2138 /* We turn off the need_redraw flag, since if the canvas is mapped again
2139 * it will request a redraw anyways. We do not turn off the need_update
2140 * flag, though, because updates are not queued when the canvas remaps
2141 * itself.
2142 */
2143 if (canvas->need_redraw)
2144 {
2145 canvas->need_redraw = FALSE(0);
2146 }
2147
2148 if (canvas->grabbed_item)
2149 {
2150 eel_canvas_item_ungrab (canvas->grabbed_item);
2151 }
2152
2153 remove_idle (canvas);
2154}
2155
2156/* Destroy handler for EelCanvas */
2157static void
2158eel_canvas_destroy (GtkWidget *object)
2159{
2160 EelCanvas *canvas;
2161
2162 g_return_if_fail (EEL_IS_CANVAS (object))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_252
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eel_canvas_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_252
= 1; else _g_boolean_var_252 = 0; _g_boolean_var_252; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (object)"); return; } } while (0
)
;
2163
2164 /* remember, destroy can be run multiple times! */
2165
2166 canvas = EEL_CANVAS (object)((((EelCanvas*) (void *) ((object)))));
2167
2168 if (canvas->root_destroy_id)
2169 {
2170 g_signal_handler_disconnect (G_OBJECT (canvas->root)((((GObject*) (void *) ((canvas->root))))), canvas->root_destroy_id);
2171 canvas->root_destroy_id = 0;
2172 }
2173 if (canvas->root)
2174 {
2175 EelCanvasItem *root = canvas->root;
2176 canvas->root = NULL((void*)0);
2177 eel_canvas_item_destroy (root);
2178 g_object_unref (root);
2179 }
2180
2181 shutdown_transients (canvas);
2182
2183 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->destroy)
2184 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->destroy) (object);
2185}
2186
2187/**
2188 * eel_canvas_new:
2189 * @void:
2190 *
2191 * Creates a new empty canvas. If you wish to use the
2192 * &EelCanvasImage item inside this canvas, then you must push the gdk_imlib
2193 * visual and colormap before calling this function, and they can be popped
2194 * afterwards.
2195 *
2196 * Return value: A newly-created canvas.
2197 **/
2198GtkWidget *
2199eel_canvas_new (void)
2200{
2201 return GTK_WIDGET (g_object_new (eel_canvas_get_type (), NULL))((((GtkWidget*) (void *) ((g_object_new (eel_canvas_get_type (
), ((void*)0)))))))
;
2202}
2203
2204/* Map handler for the canvas */
2205static void
2206eel_canvas_map (GtkWidget *widget)
2207{
2208 EelCanvas *canvas;
2209
2210 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_253
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2211
2212 /* Normal widget mapping stuff */
2213
2214 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->map)
2215 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->map) (widget);
2216
2217 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2218
2219 /* Map items */
2220
2221 if (canvas->root->flags & EEL_CANVAS_ITEM_VISIBLE &&
2222 !(canvas->root->flags & EEL_CANVAS_ITEM_MAPPED) &&
2223 EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->map)
2224 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->map) (canvas->root);
2225}
2226
2227/* Unmap handler for the canvas */
2228static void
2229eel_canvas_unmap (GtkWidget *widget)
2230{
2231 EelCanvas *canvas;
2232
2233 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_254
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2234
2235 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2236
2237 shutdown_transients (canvas);
2238
2239 /* Unmap items */
2240
2241 if (EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->unmap)
2242 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->unmap) (canvas->root);
2243
2244 /* Normal widget unmapping stuff */
2245
2246 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unmap)
2247 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unmap) (widget);
2248}
2249
2250/* Realize handler for the canvas */
2251static void
2252eel_canvas_realize (GtkWidget *widget)
2253{
2254 EelCanvas *canvas;
2255
2256 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_255
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2257
2258 /* Normal widget realization stuff */
2259
2260 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->realize)
2261 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->realize) (widget);
2262
2263 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2264
2265 gdk_window_set_events (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))),
2266 (gdk_window_get_events (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2267 | GDK_EXPOSURE_MASK
2268 | GDK_BUTTON_PRESS_MASK
2269 | GDK_BUTTON_RELEASE_MASK
2270 | GDK_POINTER_MOTION_MASK
2271 | GDK_KEY_PRESS_MASK
2272 | GDK_KEY_RELEASE_MASK
2273 | GDK_ENTER_NOTIFY_MASK
2274 | GDK_LEAVE_NOTIFY_MASK
2275 | GDK_FOCUS_CHANGE_MASK));
2276
2277 /* Create our own temporary pixmap gc and realize all the items */
2278
2279 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->realize) (canvas->root);
2280}
2281
2282/* Unrealize handler for the canvas */
2283static void
2284eel_canvas_unrealize (GtkWidget *widget)
2285{
2286 EelCanvas *canvas;
2287
2288 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_256
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2289
2290 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2291
2292 shutdown_transients (canvas);
2293
2294 /* Unrealize items and parent widget */
2295
2296 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->unrealize) (canvas->root);
2297
2298 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unrealize)
2299 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unrealize) (widget);
2300}
2301
2302/* Handles scrolling of the canvas. Adjusts the scrolling and zooming offset to
2303 * keep as much as possible of the canvas scrolling region in view.
2304 */
2305static void
2306scroll_to (EelCanvas *canvas, int cx, int cy)
2307{
2308 int scroll_width, scroll_height;
2309 int right_limit, bottom_limit;
2310 int old_zoom_xofs, old_zoom_yofs;
2311 int changed_x = FALSE(0), changed_y = FALSE(0);
2312 int canvas_width, canvas_height;
2313 GtkAllocation allocation;
2314 GtkAdjustment *vadjustment, *hadjustment;
2315 guint width, height;
2316
2317 gtk_widget_get_allocation (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))), &allocation);
2318 canvas_width = allocation.width;
2319 canvas_height = allocation.height;
2320
2321 scroll_width = floor ((canvas->scroll_x2 - canvas->scroll_x1) * canvas->pixels_per_unit + 0.5);
2322 scroll_height = floor ((canvas->scroll_y2 - canvas->scroll_y1) * canvas->pixels_per_unit + 0.5);
2323
2324 right_limit = scroll_width - canvas_width;
2325 bottom_limit = scroll_height - canvas_height;
2326
2327 old_zoom_xofs = canvas->zoom_xofs;
2328 old_zoom_yofs = canvas->zoom_yofs;
2329
2330 if (right_limit < 0)
2331 {
2332 cx = 0;
2333 if (canvas->center_scroll_region)
2334 {
2335 canvas->zoom_xofs = (canvas_width - scroll_width) / 2;
2336 scroll_width = canvas_width;
2337 }
2338 else
2339 {
2340 canvas->zoom_xofs = 0;
2341 }
2342 }
2343 else if (cx < 0)
2344 {
2345 cx = 0;
2346 canvas->zoom_xofs = 0;
2347 }
2348 else if (cx > right_limit)
2349 {
2350 cx = right_limit;
2351 canvas->zoom_xofs = 0;
2352 }
2353 else
2354 canvas->zoom_xofs = 0;
2355
2356 if (bottom_limit < 0)
2357 {
2358 cy = 0;
2359 if (canvas->center_scroll_region)
2360 {
2361 canvas->zoom_yofs = (canvas_height - scroll_height) / 2;
2362 scroll_height = canvas_height;
2363 }
2364 else
2365 {
2366 canvas->zoom_yofs = 0;
2367 }
2368 }
2369 else if (cy < 0)
2370 {
2371 cy = 0;
2372 canvas->zoom_yofs = 0;
2373 }
2374 else if (cy > bottom_limit)
2375 {
2376 cy = bottom_limit;
2377 canvas->zoom_yofs = 0;
2378 }
2379 else
2380 canvas->zoom_yofs = 0;
2381
2382 if ((canvas->zoom_xofs != old_zoom_xofs) || (canvas->zoom_yofs != old_zoom_yofs))
2383 {
2384 /* This can only occur, if either canvas size or widget size changes */
2385 /* So I think we can request full redraw here */
2386 /* More stuff - we have to mark root as needing fresh affine (Lauris) */
2387 if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
2388 {
2389 canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
2390 eel_canvas_request_update (canvas);
2391 }
2392 gtk_widget_queue_draw (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))));
2393 }
2394
2395 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2396 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2397
2398 if (((int) gtk_adjustment_get_value (hadjustment)) != cx)
2399 {
2400 gtk_adjustment_set_value (hadjustment, cx);
2401 changed_x = TRUE(!(0));
2402 }
2403
2404 if (((int) gtk_adjustment_get_value (vadjustment)) != cy)
2405 {
2406 gtk_adjustment_set_value (vadjustment, cy);
2407 changed_y = TRUE(!(0));
2408 }
2409
2410 gtk_layout_get_size (&canvas->layout, &width, &height);
2411 if ((scroll_width != (int) width )|| (scroll_height != (int) height))
2412 {
2413 gtk_layout_set_size (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas))))), scroll_width, scroll_height);
2414 }
2415
2416 /* Signal GtkLayout that it should do a redraw. */
2417 if (changed_x)
2418 g_signal_emit_by_name (hadjustment, "value_changed");
2419 if (changed_y)
2420 g_signal_emit_by_name (vadjustment, "value_changed");
2421}
2422
2423/* Size allocation handler for the canvas */
2424static void
2425eel_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
2426{
2427 EelCanvas *canvas;
2428 GtkAdjustment *vadjustment, *hadjustment;
2429
2430 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_257
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_257
= 1; else _g_boolean_var_257 = 0; _g_boolean_var_257; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2431 g_return_if_fail (allocation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_258
; if (allocation != ((void*)0)) _g_boolean_var_258 = 1; else _g_boolean_var_258
= 0; _g_boolean_var_258; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "allocation != NULL"); return
; } } while (0)
;
2432
2433 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->size_allocate)
2434 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->size_allocate) (widget, allocation);
2435
2436 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2437
2438 /* Recenter the view, if appropriate */
2439
2440 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2441 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2442
2443 gtk_adjustment_set_page_size (hadjustment, allocation->width);
2444 gtk_adjustment_set_page_increment (hadjustment, allocation->width / 2);
2445
2446 gtk_adjustment_set_page_size (vadjustment, allocation->height);
2447 gtk_adjustment_set_page_increment (vadjustment, allocation->height / 2);
2448
2449 scroll_to (canvas,
2450 gtk_adjustment_get_value (hadjustment),
2451 gtk_adjustment_get_value (vadjustment));
2452
2453 g_signal_emit_by_name (hadjustment, "changed");
2454 g_signal_emit_by_name (vadjustment, "changed");
2455}
2456
2457/* Emits an event for an item in the canvas, be it the current item, grabbed
2458 * item, or focused item, as appropriate.
2459 */
2460
2461static int
2462emit_event (EelCanvas *canvas, GdkEvent *event)
2463{
2464 GdkEvent ev;
2465 gint finished;
2466 EelCanvasItem *item;
2467 EelCanvasItem *parent;
2468 guint mask;
2469
2470 /* Could be an old pick event */
2471 if (!gtk_widget_get_realized (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas)))))))
2472 {
2473 return FALSE(0);
2474 }
2475
2476 /* Perform checks for grabbed items */
2477
2478 if (canvas->grabbed_item &&
2479 !is_descendant (canvas->current_item, canvas->grabbed_item))
2480 {
2481 return FALSE(0);
2482 }
2483
2484 if (canvas->grabbed_item)
2485 {
2486 switch (event->type)
2487 {
2488 case GDK_ENTER_NOTIFY:
2489 mask = GDK_ENTER_NOTIFY_MASK;
2490 break;
2491
2492 case GDK_LEAVE_NOTIFY:
2493 mask = GDK_LEAVE_NOTIFY_MASK;
2494 break;
2495
2496 case GDK_MOTION_NOTIFY:
2497 mask = GDK_POINTER_MOTION_MASK;
2498 break;
2499
2500 case GDK_BUTTON_PRESS:
2501 case GDK_2BUTTON_PRESS:
2502 case GDK_3BUTTON_PRESS:
2503 mask = GDK_BUTTON_PRESS_MASK;
2504 break;
2505
2506 case GDK_BUTTON_RELEASE:
2507 mask = GDK_BUTTON_RELEASE_MASK;
2508 break;
2509
2510 case GDK_KEY_PRESS:
2511 mask = GDK_KEY_PRESS_MASK;
2512 break;
2513
2514 case GDK_KEY_RELEASE:
2515 mask = GDK_KEY_RELEASE_MASK;
2516 break;
2517
2518 default:
2519 mask = 0;
2520 break;
2521 }
2522
2523 if (!(mask & canvas->grabbed_event_mask))
2524 return FALSE(0);
2525 }
2526
2527 /* Convert to world coordinates -- we have two cases because of diferent
2528 * offsets of the fields in the event structures.
2529 */
2530
2531 ev = *event;
2532
2533 switch (ev.type)
2534 {
2535 case GDK_ENTER_NOTIFY:
2536 case GDK_LEAVE_NOTIFY:
2537 eel_canvas_window_to_world (canvas,
2538 ev.crossing.x, ev.crossing.y,
2539 &ev.crossing.x, &ev.crossing.y);
2540 break;
2541
2542 case GDK_MOTION_NOTIFY:
2543 case GDK_BUTTON_PRESS:
2544 case GDK_2BUTTON_PRESS:
2545 case GDK_3BUTTON_PRESS:
2546 case GDK_BUTTON_RELEASE:
2547 eel_canvas_window_to_world (canvas,
2548 ev.motion.x, ev.motion.y,
2549 &ev.motion.x, &ev.motion.y);
2550 break;
2551
2552 default:
2553 break;
2554 }
2555
2556 /* Choose where we send the event */
2557
2558 item = canvas->current_item;
2559
2560 if (canvas->focused_item
2561 && ((event->type == GDK_KEY_PRESS) ||
2562 (event->type == GDK_KEY_RELEASE) ||
2563 (event->type == GDK_FOCUS_CHANGE)))
2564 item = canvas->focused_item;
2565
2566 /* The event is propagated up the hierarchy (for if someone connected to
2567 * a group instead of a leaf event), and emission is stopped if a
2568 * handler returns TRUE, just like for GtkWidget events.
2569 */
2570
2571 finished = FALSE(0);
2572
2573 while (item && !finished)
2574 {
2575 g_object_ref (item)((__typeof__ (item)) (g_object_ref) (item));
2576
2577 g_signal_emit (
2578 G_OBJECT (item)((((GObject*) (void *) ((item))))), item_signals[ITEM_EVENT], 0,
2579 &ev, &finished);
2580
2581 parent = item->parent;
2582 g_object_unref (item);
2583
2584 item = parent;
2585 }
2586
2587 return finished;
2588}
2589
2590/* Re-picks the current item in the canvas, based on the event's coordinates.
2591 * Also emits enter/leave events for items as appropriate.
2592 */
2593static int
2594pick_current_item (EelCanvas *canvas, GdkEvent *event)
2595{
2596 int button_down;
2597 double x, y;
2598 int retval;
2599
2600 retval = FALSE(0);
2601
2602 /* If a button is down, we'll perform enter and leave events on the
2603 * current item, but not enter on any other item. This is more or less
2604 * like X pointer grabbing for canvas items.
2605 */
2606 button_down = canvas->state & (GDK_BUTTON1_MASK
2607 | GDK_BUTTON2_MASK
2608 | GDK_BUTTON3_MASK
2609 | GDK_BUTTON4_MASK
2610 | GDK_BUTTON5_MASK);
2611 if (!button_down)
2612 canvas->left_grabbed_item = FALSE(0);
2613
2614 /* Save the event in the canvas. This is used to synthesize enter and
2615 * leave events in case the current item changes. It is also used to
2616 * re-pick the current item if the current one gets deleted. Also,
2617 * synthesize an enter event.
2618 */
2619 if (event != &canvas->pick_event)
2620 {
2621 if ((event->type == GDK_MOTION_NOTIFY) || (event->type == GDK_BUTTON_RELEASE))
2622 {
2623 /* these fields have the same offsets in both types of events */
2624
2625 canvas->pick_event.crossing.type = GDK_ENTER_NOTIFY;
2626 canvas->pick_event.crossing.window = event->motion.window;
2627 canvas->pick_event.crossing.send_event = event->motion.send_event;
2628 canvas->pick_event.crossing.subwindow = NULL((void*)0);
2629 canvas->pick_event.crossing.x = event->motion.x;
2630 canvas->pick_event.crossing.y = event->motion.y;
2631 canvas->pick_event.crossing.mode = GDK_CROSSING_NORMAL;
2632 canvas->pick_event.crossing.detail = GDK_NOTIFY_NONLINEAR;
2633 canvas->pick_event.crossing.focus = FALSE(0);
2634 canvas->pick_event.crossing.state = event->motion.state;
2635
2636 /* these fields don't have the same offsets in both types of events */
2637
2638 if (event->type == GDK_MOTION_NOTIFY)
2639 {
2640 canvas->pick_event.crossing.x_root = event->motion.x_root;
2641 canvas->pick_event.crossing.y_root = event->motion.y_root;
2642 }
2643 else
2644 {
2645 canvas->pick_event.crossing.x_root = event->button.x_root;
2646 canvas->pick_event.crossing.y_root = event->button.y_root;
2647 }
2648 }
2649 else
2650 canvas->pick_event = *event;
2651 }
2652
2653 /* Don't do anything else if this is a recursive call */
2654
2655 if (canvas->in_repick)
2656 return retval;
2657
2658 /* LeaveNotify means that there is no current item, so we don't look for one */
2659
2660 if (canvas->pick_event.type != GDK_LEAVE_NOTIFY)
2661 {
2662 /* these fields don't have the same offsets in both types of events */
2663
2664 if (canvas->pick_event.type == GDK_ENTER_NOTIFY)
2665 {
2666 x = canvas->pick_event.crossing.x;
2667 y = canvas->pick_event.crossing.y;
2668 }
2669 else
2670 {
2671 x = canvas->pick_event.motion.x;
2672 y = canvas->pick_event.motion.y;
2673 }
2674
2675 /* canvas pixel coords */
2676 int cx, cy;
2677
2678 cx = (int) (x + 0.5);
2679 cy = (int) (y + 0.5);
2680
2681 /* world coords */
2682 eel_canvas_c2w (canvas, cx, cy, &x, &y);
2683
2684 /* find the closest item */
2685 if (canvas->root->flags & EEL_CANVAS_ITEM_MAPPED)
2686 eel_canvas_item_invoke_point (canvas->root, x, y, cx, cy,
2687 &canvas->new_current_item);
2688 else
2689 canvas->new_current_item = NULL((void*)0);
2690 }
2691 else
2692 canvas->new_current_item = NULL((void*)0);
2693
2694 if ((canvas->new_current_item == canvas->current_item) && !canvas->left_grabbed_item)
2695 return retval; /* current item did not change */
2696
2697 /* Synthesize events for old and new current items */
2698
2699 if ((canvas->new_current_item != canvas->current_item)
2700 && (canvas->current_item != NULL((void*)0))
2701 && !canvas->left_grabbed_item)
2702 {
2703 GdkEvent new_event;
2704
2705 new_event = canvas->pick_event;
2706 new_event.type = GDK_LEAVE_NOTIFY;
2707
2708 new_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
2709 new_event.crossing.subwindow = NULL((void*)0);
2710 canvas->in_repick = TRUE(!(0));
2711 retval = emit_event (canvas, &new_event);
2712 canvas->in_repick = FALSE(0);
2713 }
2714
2715 /* new_current_item may have been set to NULL during the call to emit_event() above */
2716
2717 if ((canvas->new_current_item != canvas->current_item) && button_down)
2718 {
2719 canvas->current_item = canvas->new_current_item;
2720 canvas->left_grabbed_item = TRUE(!(0));
2721 return retval;
2722 }
2723
2724 /* Handle the rest of cases */
2725
2726 canvas->left_grabbed_item = FALSE(0);
2727 canvas->current_item = canvas->new_current_item;
2728
2729 if (canvas->current_item != NULL((void*)0))
2730 {
2731 GdkEvent new_event;
2732
2733 new_event = canvas->pick_event;
2734 new_event.type = GDK_ENTER_NOTIFY;
2735 new_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
2736 new_event.crossing.subwindow = NULL((void*)0);
2737 retval = emit_event (canvas, &new_event);
2738 }
2739
2740 return retval;
2741}
2742
2743/* Button event handler for the canvas */
2744static gint
2745eel_canvas_button (GtkWidget *widget, GdkEventButton *event)
2746{
2747 EelCanvas *canvas;
2748 int mask;
2749 int retval;
2750
2751 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_259
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_259
= 1; else _g_boolean_var_259 = 0; _g_boolean_var_259; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2752 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_260
; if (event != ((void*)0)) _g_boolean_var_260 = 1; else _g_boolean_var_260
= 0; _g_boolean_var_260; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2753
2754 retval = FALSE(0);
2755
2756 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2757
2758 /* Don't handle extra mouse button events */
2759 if (event->button > 5)
2760 return FALSE(0);
2761
2762 /*
2763 * dispatch normally regardless of the event's window if an item has
2764 * has a pointer grab in effect
2765 */
2766 if (!canvas->grabbed_item && event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2767 return retval;
2768
2769 switch (event->button)
2770 {
2771 case 1:
2772 mask = GDK_BUTTON1_MASK;
2773 break;
2774 case 2:
2775 mask = GDK_BUTTON2_MASK;
2776 break;
2777 case 3:
2778 mask = GDK_BUTTON3_MASK;
2779 break;
2780 case 4:
2781 mask = GDK_BUTTON4_MASK;
2782 break;
2783 case 5:
2784 mask = GDK_BUTTON5_MASK;
2785 break;
2786 default:
2787 mask = 0;
2788 }
2789
2790 switch (event->type)
2791 {
2792 case GDK_BUTTON_PRESS:
2793 case GDK_2BUTTON_PRESS:
2794 case GDK_3BUTTON_PRESS:
2795 /* Pick the current item as if the button were not pressed, and
2796 * then process the event.
2797 */
2798 event->state ^= mask;
2799 canvas->state = event->state;
2800 pick_current_item (canvas, (GdkEvent *) event);
2801 event->state ^= mask;
2802 canvas->state = event->state;
2803 retval = emit_event (canvas, (GdkEvent *) event);
2804 break;
2805
2806 case GDK_BUTTON_RELEASE:
2807 /* Process the event as if the button were pressed, then repick
2808 * after the button has been released
2809 */
2810 canvas->state = event->state;
2811 retval = emit_event (canvas, (GdkEvent *) event);
2812 event->state ^= mask;
2813 canvas->state = event->state;
2814 pick_current_item (canvas, (GdkEvent *) event);
2815 event->state ^= mask;
2816 break;
2817
2818 default:
2819 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-canvas.c", 2819, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
2820 }
2821
2822 return retval;
2823}
2824
2825/* Motion event handler for the canvas */
2826static gint
2827eel_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
2828{
2829 EelCanvas *canvas;
2830
2831 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_261
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2832 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_262
; if (event != ((void*)0)) _g_boolean_var_262 = 1; else _g_boolean_var_262
= 0; _g_boolean_var_262; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2833
2834 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2835
2836 if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2837 return FALSE(0);
2838
2839 canvas->state = event->state;
2840 pick_current_item (canvas, (GdkEvent *) event);
2841 return emit_event (canvas, (GdkEvent *) event);
2842}
2843
2844/* Key event handler for the canvas */
2845static gint
2846eel_canvas_key (GtkWidget *widget, GdkEventKey *event)
2847{
2848 EelCanvas *canvas;
2849
2850 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_263
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_263
= 1; else _g_boolean_var_263 = 0; _g_boolean_var_263; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2851 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_264
; if (event != ((void*)0)) _g_boolean_var_264 = 1; else _g_boolean_var_264
= 0; _g_boolean_var_264; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2852
2853 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2854
2855 if (emit_event (canvas, (GdkEvent *) event))
2856 return TRUE(!(0));
2857 if (event->type == GDK_KEY_RELEASE)
2858 return GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->key_release_event (widget, event);
2859 else
2860 return GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->key_press_event (widget, event);
2861}
2862
2863
2864/* Crossing event handler for the canvas */
2865static gint
2866eel_canvas_crossing (GtkWidget *widget, GdkEventCrossing *event)
2867{
2868 EelCanvas *canvas;
2869
2870 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_265
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_265
= 1; else _g_boolean_var_265 = 0; _g_boolean_var_265; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2871 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_266
; if (event != ((void*)0)) _g_boolean_var_266 = 1; else _g_boolean_var_266
= 0; _g_boolean_var_266; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2872
2873 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2874
2875 if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2876 return FALSE(0);
2877
2878 canvas->state = event->state;
2879 return pick_current_item (canvas, (GdkEvent *) event);
2880}
2881
2882/* Focus in handler for the canvas */
2883static gint
2884eel_canvas_focus_in (GtkWidget *widget, GdkEventFocus *event)
2885{
2886 EelCanvas *canvas;
2887
2888 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2889
2890 if (canvas->focused_item)
2891 return emit_event (canvas, (GdkEvent *) event);
2892 else
2893 return FALSE(0);
2894}
2895
2896/* Focus out handler for the canvas */
2897static gint
2898eel_canvas_focus_out (GtkWidget *widget, GdkEventFocus *event)
2899{
2900 EelCanvas *canvas;
2901
2902 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2903
2904 if (canvas->focused_item)
2905 return emit_event (canvas, (GdkEvent *) event);
2906 else
2907 return FALSE(0);
2908}
2909
2910static cairo_region_t *
2911eel_cairo_get_clip_region (cairo_t *cr)
2912{
2913 cairo_rectangle_list_t *list;
2914 cairo_region_t *region;
2915 int i;
2916
2917 list = cairo_copy_clip_rectangle_list (cr);
2918 if (list->status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) {
2919 cairo_rectangle_int_t clip_rect;
2920
2921 cairo_rectangle_list_destroy (list);
2922
2923 if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
2924 return NULL((void*)0);
2925 return cairo_region_create_rectangle (&clip_rect);
2926 }
2927
2928
2929 region = cairo_region_create ();
2930 for (i = list->num_rectangles - 1; i >= 0; --i) {
2931 cairo_rectangle_t *rect = &list->rectangles[i];
2932 cairo_rectangle_int_t clip_rect;
2933
2934 clip_rect.x = floor (rect->x);
2935 clip_rect.y = floor (rect->y);
2936 clip_rect.width = ceil (rect->x + rect->width) - clip_rect.x;
2937 clip_rect.height = ceil (rect->y + rect->height) - clip_rect.y;
2938
2939 if (cairo_region_union_rectangle (region, &clip_rect) != CAIRO_STATUS_SUCCESS) {
2940 cairo_region_destroy (region);
2941 region = NULL((void*)0);
2942 break;
2943 }
2944 }
2945
2946 cairo_rectangle_list_destroy (list);
2947 return region;
2948}
2949
2950/* Expose handler for the canvas */
2951static gboolean
2952eel_canvas_draw (GtkWidget *widget, cairo_t *cr)
2953{
2954 EelCanvas *canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2955 GdkWindow *bin_window;
2956 cairo_region_t *region;
2957
2958 if (!gdk_cairo_get_clip_rectangle (cr, NULL((void*)0)))
2959 return FALSE(0);
2960
2961 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (widget)((((GtkLayout*) (void *) ((widget))))));
2962
2963 if (!gtk_cairo_should_draw_window (cr, bin_window))
2964 return FALSE(0);
2965
2966 cairo_save (cr);
2967
2968 gtk_cairo_transform_to_window (cr, widget, bin_window);
2969
2970 region = eel_cairo_get_clip_region (cr);
2971 if (region == NULL((void*)0)) {
2972 cairo_restore (cr);
2973 return FALSE(0);
2974 }
2975
2976#if defined VERBOSE
2977 g_print ("Draw\n");
2978#endif
2979 /* If there are any outstanding items that need updating, do them now */
2980 if (canvas->idle_id)
2981 {
2982 g_source_remove (canvas->idle_id);
2983 canvas->idle_id = 0;
2984 }
2985 if (canvas->need_update)
2986 {
2987 g_return_val_if_fail (!canvas->doing_update, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (!canvas->doing_update) _g_boolean_var_267 = 1; else _g_boolean_var_267
= 0; _g_boolean_var_267; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "!canvas->doing_update"
); return ((0)); } } while (0)
;
2988
2989 canvas->doing_update = TRUE(!(0));
2990 eel_canvas_item_invoke_update (canvas->root, 0, 0, 0);
2991
2992 g_return_val_if_fail (canvas->doing_update, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_268
; if (canvas->doing_update) _g_boolean_var_268 = 1; else _g_boolean_var_268
= 0; _g_boolean_var_268; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "canvas->doing_update"
); return ((0)); } } while (0)
;
2993
2994 canvas->doing_update = FALSE(0);
2995
2996 canvas->need_update = FALSE(0);
2997 }
2998
2999 /* Hmmm. Would like to queue antiexposes if the update marked
3000 anything that is gonna get redrawn as invalid */
3001
3002 g_signal_emit (G_OBJECT (canvas)((((GObject*) (void *) ((canvas))))), canvas_signals[DRAW_BACKGROUND], 0,
3003 cr);
3004
3005 if (canvas->root->flags & EEL_CANVAS_ITEM_MAPPED)
3006 EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->draw (canvas->root,
3007 cr, region);
3008
3009 /* Chain up to get exposes on child widgets */
3010 cairo_restore (cr);
3011
3012 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->draw)
3013 GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->draw (widget, cr);
3014
3015 cairo_region_destroy (region);
3016
3017 return FALSE(0);
3018}
3019
3020static void
3021eel_canvas_draw_background (EelCanvas *canvas,
3022 cairo_t *cr)
3023{
3024 cairo_rectangle_int_t rect;
3025 GtkStyleContext *style_context;
3026 GdkRGBA color;
3027 GdkRGBA *c;
3028
3029 if (!gdk_cairo_get_clip_rectangle (cr, &rect))
3030 return;
3031
3032 cairo_save (cr);
3033 /* By default, we use the style background. */
3034 style_context = gtk_widget_get_style_context (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))));
3035
3036 gtk_style_context_get (style_context, GTK_STATE_FLAG_NORMAL,
3037 GTK_STYLE_PROPERTY_BACKGROUND_COLOR"background-color",
3038 &c, NULL((void*)0));
3039 color = *c;
3040 gdk_rgba_free (c);
3041
3042 gdk_cairo_set_source_rgba (cr, &color);
3043 gdk_cairo_rectangle (cr, &rect);
3044 cairo_fill (cr);
3045 cairo_restore (cr);
3046}
3047
3048static void
3049do_update (EelCanvas *canvas)
3050{
3051 /* Cause the update if necessary */
3052
3053update_again:
3054 if (canvas->need_update)
3055 {
3056 g_return_if_fail (!canvas->doing_update)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_269
; if (!canvas->doing_update) _g_boolean_var_269 = 1; else _g_boolean_var_269
= 0; _g_boolean_var_269; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "!canvas->doing_update"
); return; } } while (0)
;
3057
3058 canvas->doing_update = TRUE(!(0));
3059 eel_canvas_item_invoke_update (canvas->root, 0, 0, 0);
3060
3061 g_return_if_fail (canvas->doing_update)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_270
; if (canvas->doing_update) _g_boolean_var_270 = 1; else _g_boolean_var_270
= 0; _g_boolean_var_270; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "canvas->doing_update"
); return; } } while (0)
;
3062
3063 canvas->doing_update = FALSE(0);
3064
3065 canvas->need_update = FALSE(0);
3066 }
3067
3068 /* Pick new current item */
3069
3070 while (canvas->need_repick)
3071 {
3072 canvas->need_repick = FALSE(0);
3073 pick_current_item (canvas, &canvas->pick_event);
3074 }
3075
3076 /* it is possible that during picking we emitted an event in which
3077 the user then called some function which then requested update
3078 of something. Without this we'd be left in a state where
3079 need_update would have been left TRUE and the canvas would have
3080 been left unpainted. */
3081 if (canvas->need_update)
3082 {
3083 goto update_again;
3084 }
3085}
3086
3087/* Idle handler for the canvas. It deals with pending updates and redraws. */
3088static gint
3089idle_handler (gpointer data)
3090{
3091 EelCanvas *canvas;
3092
3093 canvas = EEL_CANVAS (data)((((EelCanvas*) (void *) ((data)))));
3094 do_update (canvas);
3095
3096 /* Reset idle id */
3097 canvas->idle_id = 0;
3098
3099 return FALSE(0);
3100}
3101
3102/* Convenience function to add an idle handler to a canvas */
3103static void
3104add_idle (EelCanvas *canvas)
3105{
3106 if (!canvas->idle_id)
3107 {
3108 /* We let the update idle handler have higher priority
3109 * than the redraw idle handler so the canvas state
3110 * will be updated during the expose event. canvas in
3111 * expose_event.
3112 */
3113 canvas->idle_id = g_idle_add_full (GDK_PRIORITY_REDRAW(100 + 20) - 20,
3114 idle_handler, canvas, NULL((void*)0));
3115 }
3116}
3117
3118/**
3119 * eel_canvas_root:
3120 * @canvas: A canvas.
3121 *
3122 * Queries the root group of a canvas.
3123 *
3124 * Return value: The root group of the specified canvas.
3125 **/
3126EelCanvasGroup *
3127eel_canvas_root (EelCanvas *canvas)
3128{
3129 g_return_val_if_fail (EEL_IS_CANVAS (canvas), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_271
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_271
= 1; else _g_boolean_var_271 = 0; _g_boolean_var_271; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return (((void*)0));
} } while (0)
;
3130
3131 return EEL_CANVAS_GROUP (canvas->root)((((EelCanvasGroup*) (void *) ((canvas->root)))));
3132}
3133
3134
3135/**
3136 * eel_canvas_set_scroll_region:
3137 * @canvas: A canvas.
3138 * @x1: Leftmost limit of the scrolling region.
3139 * @y1: Upper limit of the scrolling region.
3140 * @x2: Rightmost limit of the scrolling region.
3141 * @y2: Lower limit of the scrolling region.
3142 *
3143 * Sets the scrolling region of a canvas to the specified rectangle. The canvas
3144 * will then be able to scroll only within this region. The view of the canvas
3145 * is adjusted as appropriate to display as much of the new region as possible.
3146 **/
3147void
3148eel_canvas_set_scroll_region (EelCanvas *canvas, double x1, double y1, double x2, double y2)
3149{
3150 double wxofs, wyofs;
3151 int xofs, yofs;
3152 GtkAdjustment *vadjustment, *hadjustment;
3153
3154 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_272
= 1; else _g_boolean_var_272 = 0; _g_boolean_var_272; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3155
3156 if ((canvas->scroll_x1 == x1) && (canvas->scroll_y1 == y1) &&
3157 (canvas->scroll_x2 == x2) && (canvas->scroll_y2 == y2))
3158 {
3159 return;
3160 }
3161
3162 /*
3163 * Set the new scrolling region. If possible, do not move the visible contents of the
3164 * canvas.
3165 */
3166 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3167 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3168
3169 eel_canvas_c2w (canvas,
3170 gtk_adjustment_get_value (hadjustment) + canvas->zoom_xofs,
3171 gtk_adjustment_get_value (vadjustment) + canvas->zoom_yofs,
3172 /*canvas->zoom_xofs,
3173 canvas->zoom_yofs,*/
3174 &wxofs, &wyofs);
3175
3176 canvas->scroll_x1 = x1;
3177 canvas->scroll_y1 = y1;
3178 canvas->scroll_x2 = x2;
3179 canvas->scroll_y2 = y2;
3180
3181 eel_canvas_w2c (canvas, wxofs, wyofs, &xofs, &yofs);
3182
3183 scroll_to (canvas, xofs, yofs);
3184
3185 canvas->need_repick = TRUE(!(0));
3186
3187 if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
3188 {
3189 canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
3190 eel_canvas_request_update (canvas);
3191 }
3192}
3193
3194
3195/**
3196 * eel_canvas_get_scroll_region:
3197 * @canvas: A canvas.
3198 * @x1: Leftmost limit of the scrolling region (return value).
3199 * @y1: Upper limit of the scrolling region (return value).
3200 * @x2: Rightmost limit of the scrolling region (return value).
3201 * @y2: Lower limit of the scrolling region (return value).
3202 *
3203 * Queries the scrolling region of a canvas.
3204 **/
3205void
3206eel_canvas_get_scroll_region (EelCanvas *canvas, double *x1, double *y1, double *x2, double *y2)
3207{
3208 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_273
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_273
= 1; else _g_boolean_var_273 = 0; _g_boolean_var_273; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3209
3210 if (x1)
3211 *x1 = canvas->scroll_x1;
3212
3213 if (y1)
3214 *y1 = canvas->scroll_y1;
3215
3216 if (x2)
3217 *x2 = canvas->scroll_x2;
3218
3219 if (y2)
3220 *y2 = canvas->scroll_y2;
3221}
3222
3223void
3224eel_canvas_set_center_scroll_region (EelCanvas *canvas,
3225 gboolean center_scroll_region)
3226{
3227 GtkAdjustment *vadjustment, *hadjustment;
3228
3229 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_274
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3230
3231 canvas->center_scroll_region = center_scroll_region != 0;
3232
3233 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (&canvas->layout)((((GtkScrollable*) (void *) ((&canvas->layout))))));
3234 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (&canvas->layout)((((GtkScrollable*) (void *) ((&canvas->layout))))));
3235
3236 scroll_to (canvas,
3237 gtk_adjustment_get_value (hadjustment),
3238 gtk_adjustment_get_value (vadjustment));
3239}
3240
3241
3242/**
3243 * eel_canvas_set_pixels_per_unit:
3244 * @canvas: A canvas.
3245 * @n: The number of pixels that correspond to one canvas unit.
3246 *
3247 * Sets the zooming factor of a canvas by specifying the number of pixels that
3248 * correspond to one canvas unit.
3249 **/
3250void
3251eel_canvas_set_pixels_per_unit (EelCanvas *canvas, double n)
3252{
3253 GtkWidget *widget;
3254 double cx, cy;
3255 int x1, y1;
3256 int center_x, center_y;
3257 GdkWindow *window;
3258 GdkWindowAttr attributes;
3259 gint attributes_mask;
3260 GtkAllocation allocation;
3261 GtkAdjustment *vadjustment, *hadjustment;
3262
3263 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_275
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3264 g_return_if_fail (n > EEL_CANVAS_EPSILON)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_276
; if (n > 1e-10) _g_boolean_var_276 = 1; else _g_boolean_var_276
= 0; _g_boolean_var_276; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "n > EEL_CANVAS_EPSILON"
); return; } } while (0)
;
3265
3266 widget = GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas)))));
3267
3268 gtk_widget_get_allocation (widget, &allocation);
3269 center_x = allocation.width / 2;
3270 center_y = allocation.height / 2;
3271
3272 /* Find the coordinates of the screen center in units. */
3273 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3274 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3275 cx = (gtk_adjustment_get_value (hadjustment) + center_x) / canvas->pixels_per_unit + canvas->scroll_x1 + canvas->zoom_xofs;
3276 cy = (gtk_adjustment_get_value (vadjustment) + center_y) / canvas->pixels_per_unit + canvas->scroll_y1 + canvas->zoom_yofs;
3277
3278 /* Now calculate the new offset of the upper left corner. (round not truncate) */
3279 x1 = ((cx - canvas->scroll_x1) * n) - center_x + .5;
3280 y1 = ((cy - canvas->scroll_y1) * n) - center_y + .5;
3281
3282 canvas->pixels_per_unit = n;
3283
3284 if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
3285 {
3286 canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
3287 eel_canvas_request_update (canvas);
3288 }
3289
3290 /* Map a background None window over the bin_window to avoid
3291 * scrolling the window scroll causing exposes.
3292 */
3293 window = NULL((void*)0);
3294 if (gtk_widget_get_mapped (widget))
3295 {
3296 attributes.window_type = GDK_WINDOW_CHILD;
3297 gtk_widget_get_allocation (widget, &allocation);
3298 attributes.x = allocation.x;
3299 attributes.y = allocation.y;
3300 attributes.width = allocation.width;
3301 attributes.height = allocation.height;
3302 attributes.wclass = GDK_INPUT_OUTPUT;
3303 attributes.visual = gtk_widget_get_visual (widget);
3304 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
3305
3306 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
3307
3308 window = gdk_window_new (gtk_widget_get_parent_window (widget),
3309 &attributes, attributes_mask);
3310
3311 gdk_window_set_user_data (window, widget);
3312
3313 gdk_window_show (window);
3314 }
3315
3316 scroll_to (canvas, x1, y1);
3317
3318 /* If we created a an overlapping background None window, remove it how.
3319 *
3320 * TODO: We would like to temporarily set the bin_window background to
3321 * None to avoid clearing the bin_window to the background, but gdk doesn't
3322 * expose enought to let us do this, so we get a flash-effect here. At least
3323 * it looks better than scroll + expose.
3324 */
3325 if (window != NULL((void*)0))
3326 {
3327 gdk_window_hide (window);
3328 gdk_window_set_user_data (window, NULL((void*)0));
3329 gdk_window_destroy (window);
3330 }
3331
3332 canvas->need_repick = TRUE(!(0));
3333}
3334
3335/**
3336 * eel_canvas_scroll_to:
3337 * @canvas: A canvas.
3338 * @cx: Horizontal scrolling offset in canvas pixel units.
3339 * @cy: Vertical scrolling offset in canvas pixel units.
3340 *
3341 * Makes a canvas scroll to the specified offsets, given in canvas pixel units.
3342 * The canvas will adjust the view so that it is not outside the scrolling
3343 * region. This function is typically not used, as it is better to hook
3344 * scrollbars to the canvas layout's scrolling adjusments.
3345 **/
3346void
3347eel_canvas_scroll_to (EelCanvas *canvas, int cx, int cy)
3348{
3349 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_277
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_277
= 1; else _g_boolean_var_277 = 0; _g_boolean_var_277; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3350
3351 scroll_to (canvas, cx, cy);
3352}
3353
3354/**
3355 * eel_canvas_get_scroll_offsets:
3356 * @canvas: A canvas.
3357 * @cx: Horizontal scrolling offset (return value).
3358 * @cy: Vertical scrolling offset (return value).
3359 *
3360 * Queries the scrolling offsets of a canvas. The values are returned in canvas
3361 * pixel units.
3362 **/
3363void
3364eel_canvas_get_scroll_offsets (EelCanvas *canvas, int *cx, int *cy)
3365{
3366 GtkAdjustment *vadjustment, *hadjustment;
3367
3368 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_278
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3369
3370 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3371 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3372
3373 if (cx)
3374 *cx = gtk_adjustment_get_value (hadjustment);
3375
3376 if (cy)
3377 *cy = gtk_adjustment_get_value (vadjustment);
3378}
3379
3380/**
3381 * eel_canvas_update_now:
3382 * @canvas: A canvas.
3383 *
3384 * Forces an immediate update and redraw of a canvas. If the canvas does not
3385 * have any pending update or redraw requests, then no action is taken. This is
3386 * typically only used by applications that need explicit control of when the
3387 * display is updated, like games. It is not needed by normal applications.
3388 */
3389void
3390eel_canvas_update_now (EelCanvas *canvas)
3391{
3392 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_279
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_279
= 1; else _g_boolean_var_279 = 0; _g_boolean_var_279; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3393
3394 if (!(canvas->need_update || canvas->need_redraw))
3395 return;
3396 remove_idle (canvas);
3397 do_update (canvas);
3398}
3399
3400/**
3401 * eel_canvas_get_item_at:
3402 * @canvas: A canvas.
3403 * @x: X position in world coordinates.
3404 * @y: Y position in world coordinates.
3405 *
3406 * Looks for the item that is under the specified position, which must be
3407 * specified in world coordinates.
3408 *
3409 * Return value: The sought item, or NULL if no item is at the specified
3410 * coordinates.
3411 **/
3412EelCanvasItem *
3413eel_canvas_get_item_at (EelCanvas *canvas, double x, double y)
3414{
3415 EelCanvasItem *item = NULL((void*)0);
3416 double dist;
3417 int cx, cy;
3418
3419 g_return_val_if_fail (EEL_IS_CANVAS (canvas), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_280
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return (((void*)0));
} } while (0)
;
3420
3421 eel_canvas_w2c (canvas, x, y, &cx, &cy);
3422
3423 dist = eel_canvas_item_invoke_point (canvas->root, x, y, cx, cy, &item);
3424 if ((int) (dist * canvas->pixels_per_unit + 0.5) <= canvas->close_enough)
3425 return item;
3426 else
3427 return NULL((void*)0);
3428}
3429
3430/* Queues an update of the canvas */
3431static void
3432eel_canvas_request_update (EelCanvas *canvas)
3433{
3434 EEL_CANVAS_GET_CLASS (canvas)((((EelCanvasClass*) (((GTypeInstance*) ((canvas)))->g_class
))))
->request_update (canvas);
3435}
3436
3437static void
3438eel_canvas_request_update_real (EelCanvas *canvas)
3439{
3440 canvas->need_update = TRUE(!(0));
3441 add_idle (canvas);
3442}
3443
3444/**
3445 * eel_canvas_request_redraw:
3446 * @canvas: A canvas.
3447 * @x1: Leftmost coordinate of the rectangle to be redrawn.
3448 * @y1: Upper coordinate of the rectangle to be redrawn.
3449 * @x2: Rightmost coordinate of the rectangle to be redrawn, plus 1.
3450 * @y2: Lower coordinate of the rectangle to be redrawn, plus 1.
3451 *
3452 * Convenience function that informs a canvas that the specified rectangle needs
3453 * to be repainted. The rectangle includes @x1 and @y1, but not @x2 and @y2.
3454 * To be used only by item implementations.
3455 **/
3456void
3457eel_canvas_request_redraw (EelCanvas *canvas, int x1, int y1, int x2, int y2)
3458{
3459 GdkRectangle bbox;
3460
3461 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_281
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_281
= 1; else _g_boolean_var_281 = 0; _g_boolean_var_281; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3462
3463 if (!gtk_widget_is_drawable (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))))
3464 || (x1 >= x2) || (y1 >= y2)) return;
3465
3466 bbox.x = x1;
3467 bbox.y = y1;
3468 bbox.width = x2 - x1;
3469 bbox.height = y2 - y1;
3470
3471 gdk_window_invalidate_rect (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))),
3472 &bbox, FALSE(0));
3473}
3474
3475/**
3476 * eel_canvas_w2c:
3477 * @canvas: A canvas.
3478 * @wx: World X coordinate.
3479 * @wy: World Y coordinate.
3480 * @cx: X pixel coordinate (return value).
3481 * @cy: Y pixel coordinate (return value).
3482 *
3483 * Converts world coordinates into canvas pixel coordinates.
3484 **/
3485void
3486eel_canvas_w2c (EelCanvas *canvas, double wx, double wy, int *cx, int *cy)
3487{
3488 double zoom;
3489
3490 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_282
= 1; else _g_boolean_var_282 = 0; _g_boolean_var_282; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3491
3492 zoom = canvas->pixels_per_unit;
3493
3494 if (cx)
3495 *cx = floor ((wx - canvas->scroll_x1)*zoom + canvas->zoom_xofs + 0.5);
3496 if (cy)
3497 *cy = floor ((wy - canvas->scroll_y1)*zoom + canvas->zoom_yofs + 0.5);
3498}
3499
3500/**
3501 * eel_canvas_w2c:
3502 * @canvas: A canvas.
3503 * @world: rectangle in world coordinates.
3504 * @canvas: rectangle in canvase coordinates.
3505 *
3506 * Converts rectangles in world coordinates into canvas pixel coordinates.
3507 **/
3508void
3509eel_canvas_w2c_rect_d (EelCanvas *canvas,
3510 double *x1, double *y1,
3511 double *x2, double *y2)
3512{
3513 eel_canvas_w2c_d (canvas,
3514 *x1, *y1,
3515 x1, y1);
3516 eel_canvas_w2c_d (canvas,
3517 *x2, *y2,
3518 x2, y2);
3519}
3520
3521
3522
3523/**
3524 * eel_canvas_w2c_d:
3525 * @canvas: A canvas.
3526 * @wx: World X coordinate.
3527 * @wy: World Y coordinate.
3528 * @cx: X pixel coordinate (return value).
3529 * @cy: Y pixel coordinate (return value).
3530 *
3531 * Converts world coordinates into canvas pixel coordinates. This version
3532 * produces coordinates in floating point coordinates, for greater precision.
3533 **/
3534void
3535eel_canvas_w2c_d (EelCanvas *canvas, double wx, double wy, double *cx, double *cy)
3536{
3537 double zoom;
3538
3539 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_283
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3540
3541 zoom = canvas->pixels_per_unit;
3542
3543 if (cx)
3544 *cx = (wx - canvas->scroll_x1)*zoom + canvas->zoom_xofs;
3545 if (cy)
3546 *cy = (wy - canvas->scroll_y1)*zoom + canvas->zoom_yofs;
3547}
3548
3549
3550/**
3551 * eel_canvas_c2w:
3552 * @canvas: A canvas.
3553 * @cx: Canvas pixel X coordinate.
3554 * @cy: Canvas pixel Y coordinate.
3555 * @wx: X world coordinate (return value).
3556 * @wy: Y world coordinate (return value).
3557 *
3558 * Converts canvas pixel coordinates to world coordinates.
3559 **/
3560void
3561eel_canvas_c2w (EelCanvas *canvas, int cx, int cy, double *wx, double *wy)
3562{
3563 double zoom;
3564
3565 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_284
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_284
= 1; else _g_boolean_var_284 = 0; _g_boolean_var_284; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3566
3567 zoom = canvas->pixels_per_unit;
3568
3569 if (wx)
3570 *wx = (cx - canvas->zoom_xofs)/zoom + canvas->scroll_x1;
3571 if (wy)
3572 *wy = (cy - canvas->zoom_yofs)/zoom + canvas->scroll_y1;
3573}
3574
3575
3576/**
3577 * eel_canvas_window_to_world:
3578 * @canvas: A canvas.
3579 * @winx: Window-relative X coordinate.
3580 * @winy: Window-relative Y coordinate.
3581 * @worldx: X world coordinate (return value).
3582 * @worldy: Y world coordinate (return value).
3583 *
3584 * Converts window-relative coordinates into world coordinates. You can use
3585 * this when you need to convert mouse coordinates into world coordinates, for
3586 * example.
3587 * Window coordinates are really the same as canvas coordinates now, but this
3588 * function is here for backwards compatibility reasons.
3589 **/
3590void
3591eel_canvas_window_to_world (EelCanvas *canvas, double winx, double winy,
3592 double *worldx, double *worldy)
3593{
3594 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_285
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_285
= 1; else _g_boolean_var_285 = 0; _g_boolean_var_285; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3595
3596 if (worldx)
3597 *worldx = canvas->scroll_x1 + ((winx - canvas->zoom_xofs)
3598 / canvas->pixels_per_unit);
3599
3600 if (worldy)
3601 *worldy = canvas->scroll_y1 + ((winy - canvas->zoom_yofs)
3602 / canvas->pixels_per_unit);
3603}
3604
3605
3606/**
3607 * eel_canvas_world_to_window:
3608 * @canvas: A canvas.
3609 * @worldx: World X coordinate.
3610 * @worldy: World Y coordinate.
3611 * @winx: X window-relative coordinate.
3612 * @winy: Y window-relative coordinate.
3613 *
3614 * Converts world coordinates into window-relative coordinates.
3615 * Window coordinates are really the same as canvas coordinates now, but this
3616 * function is here for backwards compatibility reasons.
3617 **/
3618void
3619eel_canvas_world_to_window (EelCanvas *canvas, double worldx, double worldy,
3620 double *winx, double *winy)
3621{
3622 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_286
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3623
3624 if (winx)
3625 *winx = (canvas->pixels_per_unit)*(worldx - canvas->scroll_x1) + canvas->zoom_xofs;
3626
3627 if (winy)
3628 *winy = (canvas->pixels_per_unit)*(worldy - canvas->scroll_y1) + canvas->zoom_yofs;
3629}
3630
3631static gboolean
3632boolean_handled_accumulator (GSignalInvocationHint *ihint,
3633 GValue *return_accu,
3634 const GValue *handler_return,
3635 gpointer dummy)
3636{
3637 gboolean continue_emission;
3638 gboolean signal_handled;
3639
3640 signal_handled = g_value_get_boolean (handler_return);
3641 g_value_set_boolean (return_accu, signal_handled);
3642 continue_emission = !signal_handled;
3643
3644 return continue_emission;
3645}
3646
3647static guint
3648eel_canvas_item_accessible_add_focus_handler (AtkComponent *component,
3649 AtkFocusHandler handler)
3650{
3651 GSignalMatchType match_type;
3652 guint signal_id;
3653
3654 match_type = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC;
3655 signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT(atk_object_get_type ()));
3656
3657 if (!g_signal_handler_find (component, match_type, signal_id, 0, NULL((void*)0),
3658 (gpointer) handler, NULL((void*)0)))
3659 {
3660 return g_signal_connect_closure_by_id (component,
3661 signal_id, 0,
3662 g_cclosure_new (
3663 G_CALLBACK (handler)((GCallback) (handler)), NULL((void*)0),
3664 (GClosureNotify) NULL((void*)0)),
3665 FALSE(0));
3666 }
3667 return 0;
3668}
3669
3670static void
3671eel_canvas_item_accessible_get_item_extents (EelCanvasItem *item,
3672 GdkRectangle *rect)
3673{
3674 double bx1, bx2, by1, by2;
3675 gint scroll_x, scroll_y;
3676 gint x1, x2, y1, y2;
3677
3678 eel_canvas_item_get_bounds (item, &bx1, &by1, &bx2, &by2);
3679 eel_canvas_w2c_rect_d (item->canvas, &bx1, &by1, &bx2, &by2);
3680 eel_canvas_get_scroll_offsets (item->canvas, &scroll_x, &scroll_y);
3681 x1 = floor (bx1 + .5);
3682 y1 = floor (by1 + .5);
3683 x2 = floor (bx2 + .5);
3684 y2 = floor (by2 + .5);
3685 rect->x = x1 - scroll_x;
3686 rect->y = y1 - scroll_y;
3687 rect->width = x2 - x1;
3688 rect->height = y2 - y1;
3689}
3690
3691static gboolean
3692eel_canvas_item_accessible_is_item_in_window (EelCanvasItem *item,
3693 GdkRectangle *rect)
3694{
3695 GtkWidget *widget;
3696 gboolean retval;
3697
3698 widget = GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))));
3699 if (gtk_widget_get_window (widget))
3700 {
3701 int window_width, window_height;
3702
3703 gdk_window_get_geometry (gtk_widget_get_window (widget), NULL((void*)0), NULL((void*)0),
3704 &window_width, &window_height);
3705 /*
3706 * Check whether rectangles intersect
3707 */
3708 if (rect->x + rect->width < 0 ||
3709 rect->y + rect->height < 0 ||
3710 rect->x > window_width ||
3711 rect->y > window_height)
3712 {
3713 retval = FALSE(0);
3714 }
3715 else
3716 {
3717 retval = TRUE(!(0));
3718 }
3719 }
3720 else
3721 {
3722 retval = FALSE(0);
3723 }
3724 return retval;
3725}
3726
3727
3728static void
3729eel_canvas_item_accessible_get_extents (AtkComponent *component,
3730 gint *x,
3731 gint *y,
3732 gint *width,
3733 gint *height,
3734 AtkCoordType coord_type)
3735{
3736 AtkGObjectAccessible *atk_gobj;
3737 GObject *obj;
3738 EelCanvasItem *item;
3739 gint window_x, window_y;
3740 gint toplevel_x, toplevel_y;
3741 GdkRectangle rect;
3742 GdkWindow *window;
3743 GtkWidget *canvas;
3744
3745 atk_gobj = ATK_GOBJECT_ACCESSIBLE (component)((((AtkGObjectAccessible*) (void *) ((component)))));
3746 obj = atk_gobject_accessible_get_object (atk_gobj);
3747
3748 if (obj == NULL((void*)0))
3749 {
3750 /* item is defunct */
3751 return;
3752 }
3753
3754 /* Get the CanvasItem */
3755 item = EEL_CANVAS_ITEM (obj)((((EelCanvasItem*) (void *) ((obj)))));
3756
3757 /* If this item has no parent canvas, something's broken */
3758 g_return_if_fail (GTK_IS_WIDGET (item->canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_287
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item->canvas)); GType __t = ((gtk_widget_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_287 = 1; else _g_boolean_var_287 =
0; _g_boolean_var_287; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "GTK_IS_WIDGET (item->canvas)"
); return; } } while (0)
;
3759
3760 eel_canvas_item_accessible_get_item_extents (item, &rect);
3761 *width = rect.width;
3762 *height = rect.height;
3763 if (!eel_canvas_item_accessible_is_item_in_window (item, &rect))
3764 {
3765 *x = G_MININT(-2147483647 -1);
3766 *y = G_MININT(-2147483647 -1);
3767 return;
3768 }
3769
3770 canvas = GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))));
3771 window = gtk_widget_get_parent_window (canvas);
3772 gdk_window_get_origin (window, &window_x, &window_y);
3773 *x = rect.x + window_x;
3774 *y = rect.y + window_y;
3775 if (coord_type == ATK_XY_WINDOW)
3776 {
3777 window = gdk_window_get_toplevel (gtk_widget_get_window (canvas));
3778 gdk_window_get_origin (window, &toplevel_x, &toplevel_y);
3779 *x -= toplevel_x;
3780 *y -= toplevel_y;
3781 }
3782 return;
3783}
3784
3785static gint
3786eel_canvas_item_accessible_get_mdi_zorder (AtkComponent *component)
3787{
3788 AtkGObjectAccessible *atk_gobj;
3789 GObject *g_obj;
3790 EelCanvasItem *item;
3791
3792 atk_gobj = ATK_GOBJECT_ACCESSIBLE (component)((((AtkGObjectAccessible*) (void *) ((component)))));
3793 g_obj = atk_gobject_accessible_get_object (atk_gobj);
3794 if (g_obj == NULL((void*)0))
3795 {
3796 /* Object is defunct */
3797 return -1;
3798 }
3799
3800 item = EEL_CANVAS_ITEM (g_obj)((((EelCanvasItem*) (void *) ((g_obj)))));
3801 if (item->parent)
3802 {
3803 return g_list_index (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))))->item_list, item);
3804 }
3805 else
3806 {
3807 g_return_val_if_fail (item->canvas->root == item, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_288
; if (item->canvas->root == item) _g_boolean_var_288 = 1
; else _g_boolean_var_288 = 0; _g_boolean_var_288; }), 1))) {
} else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "item->canvas->root == item"); return (-1); } } while
(0)
;
3808 return 0;
3809 }
3810}
3811
3812static gboolean
3813eel_canvas_item_accessible_grab_focus (AtkComponent *component)
3814{
3815 AtkGObjectAccessible *atk_gobj;
3816 GObject *obj;
3817 EelCanvasItem *item;
3818 GtkWidget *toplevel;
3819
3820 atk_gobj = ATK_GOBJECT_ACCESSIBLE (component)((((AtkGObjectAccessible*) (void *) ((component)))));
3821 obj = atk_gobject_accessible_get_object (atk_gobj);
3822
3823 item = EEL_CANVAS_ITEM (obj)((((EelCanvasItem*) (void *) ((obj)))));
3824 if (item == NULL((void*)0))
3825 {
3826 /* item is defunct */
3827 return FALSE(0);
3828 }
3829
3830 eel_canvas_item_grab_focus (item);
3831 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
3832 if (gtk_widget_is_toplevel (toplevel))
3833 {
3834 gtk_window_present (GTK_WINDOW (toplevel)((((GtkWindow*) (void *) ((toplevel))))));
3835 }
3836
3837 return TRUE(!(0));
3838}
3839
3840static void
3841eel_canvas_item_accessible_remove_focus_handler (AtkComponent *component,
3842 guint handler_id)
3843{
3844 g_signal_handler_disconnect (component, handler_id);
3845}
3846
3847static void
3848eel_canvas_item_accessible_component_interface_init (AtkComponentIface *iface)
3849{
3850 g_return_if_fail (iface != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_289
; if (iface != ((void*)0)) _g_boolean_var_289 = 1; else _g_boolean_var_289
= 0; _g_boolean_var_289; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "iface != NULL"); return
; } } while (0)
;
3851
3852 iface->add_focus_handler = eel_canvas_item_accessible_add_focus_handler;
3853 iface->get_extents = eel_canvas_item_accessible_get_extents;
3854 iface->get_mdi_zorder = eel_canvas_item_accessible_get_mdi_zorder;
3855 iface->grab_focus = eel_canvas_item_accessible_grab_focus;
3856 iface->remove_focus_handler = eel_canvas_item_accessible_remove_focus_handler;
3857}
3858
3859static gboolean
3860eel_canvas_item_accessible_is_item_on_screen (EelCanvasItem *item)
3861{
3862 GdkRectangle rect;
3863
3864 eel_canvas_item_accessible_get_item_extents (item, &rect);
3865 return eel_canvas_item_accessible_is_item_in_window (item, &rect);
3866}
3867
3868static void
3869eel_canvas_item_accessible_initialize (AtkObject *obj, gpointer data)
3870{
3871 if (ATK_OBJECT_CLASS (accessible_item_parent_class)((((AtkObjectClass*) (void *) ((accessible_item_parent_class)
))))
->initialize != NULL((void*)0))
3872 ATK_OBJECT_CLASS (accessible_item_parent_class)((((AtkObjectClass*) (void *) ((accessible_item_parent_class)
))))
->initialize (obj, data);
3873 g_object_set_data (G_OBJECT (obj)((((GObject*) (void *) ((obj))))), "atk-component-layer",
3874 GINT_TO_POINTER (ATK_LAYER_MDI)((gpointer) (glong) (ATK_LAYER_MDI)));
3875}
3876
3877static AtkStateSet*
3878eel_canvas_item_accessible_ref_state_set (AtkObject *accessible)
3879{
3880 AtkGObjectAccessible *atk_gobj;
3881 GObject *obj;
3882 EelCanvasItem *item;
3883 AtkStateSet *state_set;
3884
3885 state_set = ATK_OBJECT_CLASS (accessible_item_parent_class)((((AtkObjectClass*) (void *) ((accessible_item_parent_class)
))))
->ref_state_set (accessible);
3886 atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible)((((AtkGObjectAccessible*) (void *) ((accessible)))));
3887 obj = atk_gobject_accessible_get_object (atk_gobj);
3888
3889 item = EEL_CANVAS_ITEM (obj)((((EelCanvasItem*) (void *) ((obj)))));
3890 if (item == NULL((void*)0))
3891 {
3892 atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
3893 }
3894 else
3895 {
3896 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
3897 {
3898 atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
3899
3900 if (eel_canvas_item_accessible_is_item_on_screen (item))
3901 {
3902 atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
3903 }
3904 }
3905 if (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))))))
3906 {
3907 atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
3908
3909 if (item->canvas->focused_item == item)
3910 {
3911 atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
3912 }
3913 }
3914 }
3915
3916 return state_set;
3917}
3918
3919G_DEFINE_TYPE_WITH_CODE (EelCanvasItemAccessible,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3920 eel_canvas_item_accessible,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3921 ATK_TYPE_GOBJECT_ACCESSIBLE,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3922 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3923 eel_canvas_item_accessible_component_interface_init))static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
3924
3925static void
3926eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass *klass)
3927{
3928 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
3929 accessible_item_parent_class = g_type_class_peek_parent (atk_class);
3930
3931 atk_class->initialize = eel_canvas_item_accessible_initialize;
3932 atk_class->ref_state_set = eel_canvas_item_accessible_ref_state_set;
3933}
3934
3935static void
3936eel_canvas_item_accessible_init (EelCanvasItemAccessible *accessible)
3937{
3938}
3939
3940static AtkObject *
3941eel_canvas_item_accessible_create (GObject *for_object)
3942{
3943 GType type;
3944 AtkObject *accessible;
3945 EelCanvasItem *item;
3946
3947 item = EEL_CANVAS_ITEM (for_object)((((EelCanvasItem*) (void *) ((for_object)))));
3948 g_return_val_if_fail (item != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_290
; if (item != ((void*)0)) _g_boolean_var_290 = 1; else _g_boolean_var_290
= 0; _g_boolean_var_290; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "item != NULL"); return (
((void*)0)); } } while (0)
;
3949
3950 type = eel_canvas_item_accessible_get_type ();
3951 if (type == G_TYPE_INVALID((GType) ((0) << (2))))
3952 {
3953 return atk_no_op_object_new (for_object);
3954 }
3955
3956 accessible = g_object_new (type, NULL((void*)0));
3957 atk_object_initialize (accessible, for_object);
3958 return accessible;
3959}
3960
3961static GType
3962eel_canvas_item_accessible_factory_get_accessible_type (void)
3963{
3964 return eel_canvas_item_accessible_get_type ();
3965}
3966
3967static AtkObject*
3968eel_canvas_item_accessible_factory_create_accessible (GObject *obj)
3969{
3970 AtkObject *accessible;
3971
3972 g_return_val_if_fail (G_IS_OBJECT (obj), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_291
; if ((((g_type_check_instance_is_fundamentally_a ((GTypeInstance
*) ((obj)), (((GType) ((20) << (2))))))))) _g_boolean_var_291
= 1; else _g_boolean_var_291 = 0; _g_boolean_var_291; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "G_IS_OBJECT (obj)"); return (((void*)0)); } } while
(0)
;
3973
3974 accessible = eel_canvas_item_accessible_create (obj);
3975
3976 return accessible;
3977}
3978
3979static GType eel_canvas_item_accessible_factory_get_type (void);
3980
3981typedef AtkObjectFactory EelCanvasItemAccessibleFactory;
3982typedef AtkObjectFactoryClass EelCanvasItemAccessibleFactoryClass;
3983G_DEFINE_TYPE (EelCanvasItemAccessibleFactory, eel_canvas_item_accessible_factory,static void eel_canvas_item_accessible_factory_init (EelCanvasItemAccessibleFactory
*self); static void eel_canvas_item_accessible_factory_class_init
(EelCanvasItemAccessibleFactoryClass *klass); static GType eel_canvas_item_accessible_factory_get_type_once
(void); static gpointer eel_canvas_item_accessible_factory_parent_class
= ((void*)0); static gint EelCanvasItemAccessibleFactory_private_offset
; static void eel_canvas_item_accessible_factory_class_intern_init
(gpointer klass) { eel_canvas_item_accessible_factory_parent_class
= g_type_class_peek_parent (klass); if (EelCanvasItemAccessibleFactory_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelCanvasItemAccessibleFactory_private_offset
); eel_canvas_item_accessible_factory_class_init ((EelCanvasItemAccessibleFactoryClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_canvas_item_accessible_factory_get_instance_private (EelCanvasItemAccessibleFactory
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelCanvasItemAccessibleFactory_private_offset
)))); } GType eel_canvas_item_accessible_factory_get_type (void
) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_factory_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_factory_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_object_factory_get_type ()), g_intern_static_string ("EelCanvasItemAccessibleFactory"
), sizeof (EelCanvasItemAccessibleFactoryClass), (GClassInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_class_intern_init
, sizeof (EelCanvasItemAccessibleFactory), (GInstanceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_init, (GTypeFlags
) 0); { {{};} } return g_define_type_id; }
3984 ATK_TYPE_OBJECT_FACTORY)static void eel_canvas_item_accessible_factory_init (EelCanvasItemAccessibleFactory
*self); static void eel_canvas_item_accessible_factory_class_init
(EelCanvasItemAccessibleFactoryClass *klass); static GType eel_canvas_item_accessible_factory_get_type_once
(void); static gpointer eel_canvas_item_accessible_factory_parent_class
= ((void*)0); static gint EelCanvasItemAccessibleFactory_private_offset
; static void eel_canvas_item_accessible_factory_class_intern_init
(gpointer klass) { eel_canvas_item_accessible_factory_parent_class
= g_type_class_peek_parent (klass); if (EelCanvasItemAccessibleFactory_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelCanvasItemAccessibleFactory_private_offset
); eel_canvas_item_accessible_factory_class_init ((EelCanvasItemAccessibleFactoryClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_canvas_item_accessible_factory_get_instance_private (EelCanvasItemAccessibleFactory
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelCanvasItemAccessibleFactory_private_offset
)))); } GType eel_canvas_item_accessible_factory_get_type (void
) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_factory_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_factory_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_object_factory_get_type ()), g_intern_static_string ("EelCanvasItemAccessibleFactory"
), sizeof (EelCanvasItemAccessibleFactoryClass), (GClassInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_class_intern_init
, sizeof (EelCanvasItemAccessibleFactory), (GInstanceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_init, (GTypeFlags
) 0); { {{};} } return g_define_type_id; }
3985
3986static void
3987eel_canvas_item_accessible_factory_class_init (AtkObjectFactoryClass *klass)
3988{
3989 klass->create_accessible = eel_canvas_item_accessible_factory_create_accessible;
3990 klass->get_accessible_type = eel_canvas_item_accessible_factory_get_accessible_type;
3991}
3992
3993static void
3994eel_canvas_item_accessible_factory_init (EelCanvasItemAccessibleFactory *accessible)
3995{
3996}
3997
3998/* Class initialization function for EelCanvasItemClass */
3999static void
4000eel_canvas_item_class_init (EelCanvasItemClass *klass)
4001{
4002 GObjectClass *gobject_class = (GObjectClass *) klass;
4003
4004 item_parent_class = g_type_class_peek_parent (klass);
4005
4006 gobject_class->set_property = eel_canvas_item_set_property;
4007 gobject_class->get_property = eel_canvas_item_get_property;
4008 gobject_class->dispose = eel_canvas_item_dispose;
4009
4010 g_object_class_install_property
4011 (gobject_class, ITEM_PROP_PARENT,
4012 g_param_spec_object ("parent", NULL((void*)0), NULL((void*)0),
4013 EEL_TYPE_CANVAS_ITEM(eel_canvas_item_get_type ()),
4014 G_PARAM_READWRITE));
4015
4016 g_object_class_install_property
4017 (gobject_class, ITEM_PROP_VISIBLE,
4018 g_param_spec_boolean ("visible", NULL((void*)0), NULL((void*)0),
4019 TRUE(!(0)),
4020 G_PARAM_READWRITE));
4021
4022 item_signals[ITEM_EVENT] =
4023 g_signal_new ("event",
4024 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
4025 G_SIGNAL_RUN_LAST,
4026 G_STRUCT_OFFSET (EelCanvasItemClass, event)((glong) __builtin_offsetof(EelCanvasItemClass, event)),
4027 boolean_handled_accumulator, NULL((void*)0),
4028 eel_marshal_BOOLEAN__BOXED,
4029 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1,
4030 GDK_TYPE_EVENT(gdk_event_get_type ()) | G_SIGNAL_TYPE_STATIC_SCOPE(((GType) (1 << 0))));
4031
4032 item_signals[ITEM_DESTROY] =
4033 g_signal_new ("destroy",
4034 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
4035 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
4036 G_STRUCT_OFFSET (EelCanvasItemClass, destroy)((glong) __builtin_offsetof(EelCanvasItemClass, destroy)),
4037 NULL((void*)0), NULL((void*)0),
4038 g_cclosure_marshal_VOID__VOID,
4039 G_TYPE_NONE((GType) ((1) << (2))), 0);
4040
4041 klass->realize = eel_canvas_item_realize;
4042 klass->unrealize = eel_canvas_item_unrealize;
4043 klass->map = eel_canvas_item_map;
4044 klass->unmap = eel_canvas_item_unmap;
4045 klass->update = eel_canvas_item_update;
4046
4047 atk_registry_set_factory_type (atk_get_default_registry (),
4048 EEL_TYPE_CANVAS_ITEM(eel_canvas_item_get_type ()),
4049 eel_canvas_item_accessible_factory_get_type ());
4050}
diff --git a/2024-07-29-023715-6438-1/report-2c7ed7.html b/2024-07-29-023715-6438-1/report-2c7ed7.html new file mode 100644 index 000000000..b7f828689 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-2c7ed7.html @@ -0,0 +1,1459 @@ + + + +caja-debug-log.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-debug-log.c
Warning:line 248, column 17
Value stored to 'p' 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 caja-debug-log.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-debug-log.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-debug-log.c: Ring buffer for logging debug messages
4
5 Copyright (C) 2006 Novell, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Federico Mena-Quintero <federico@novell.com>
23*/
24#include <config.h>
25#include <errno(*__errno_location ()).h>
26#include <stdio.h>
27#include <string.h>
28#include "caja-debug-log.h"
29#include "caja-file.h"
30
31#if !GLIB_CHECK_VERSION(2,65,2)(2 > (2) || (2 == (2) && 80 > (65)) || (2 == (2
) && 80 == (65) && 3 >= (2)))
32#include <time.h>
33#include <sys/time.h>
34#endif
35
36#define DEFAULT_RING_BUFFER_NUM_LINES1000 1000
37
38#define KEY_FILE_GROUP"debug log" "debug log"
39#define KEY_FILE_DOMAINS_KEY"enable domains" "enable domains"
40#define KEY_FILE_MAX_LINES_KEY"max lines" "max lines"
41
42#define MAX_URI_COUNT20 20
43
44static GMutex log_mutex;
45
46static GHashTable *domains_hash;
47static char **ring_buffer;
48static int ring_buffer_next_index;
49static int ring_buffer_num_lines;
50static int ring_buffer_max_lines = DEFAULT_RING_BUFFER_NUM_LINES1000;
51
52static GSList *milestones_head;
53static GSList *milestones_tail;
54
55static void
56lock (void)
57{
58 g_mutex_lock (&log_mutex);
59}
60
61static void
62unlock (void)
63{
64 g_mutex_unlock (&log_mutex);
65}
66
67void
68caja_debug_log (gboolean is_milestone, const char *domain, const char *format, ...)
69{
70 va_list args;
71
72 va_start (args, format)__builtin_va_start(args, format);
73 caja_debug_logv (is_milestone, domain, NULL((void*)0), format, args);
74 va_end (args)__builtin_va_end(args);
75}
76
77static gboolean
78is_domain_enabled (const char *domain)
79{
80 /* User actions are always logged */
81 if (strcmp (domain, CAJA_DEBUG_LOG_DOMAIN_USER"USER") == 0)
82 return TRUE(!(0));
83
84 if (!domains_hash)
85 return FALSE(0);
86
87 return (g_hash_table_lookup (domains_hash, domain) != NULL((void*)0));
88}
89
90static void
91ensure_ring (void)
92{
93 if (ring_buffer)
94 return;
95
96 ring_buffer = g_new0 (char *, ring_buffer_max_lines)(char * *) (__extension__ ({ gsize __n = (gsize) (ring_buffer_max_lines
); gsize __s = sizeof (char *); 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; }))
;
97 ring_buffer_next_index = 0;
98 ring_buffer_num_lines = 0;
99}
100
101static void
102add_to_ring (char *str)
103{
104 ensure_ring ();
105
106 g_assert (str != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_28
; if (str != ((void*)0)) _g_boolean_var_28 = 1; else _g_boolean_var_28
= 0; _g_boolean_var_28; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 106, ((const char*) (__func__
)), "str != NULL"); } while (0)
;
107
108 if (ring_buffer_num_lines == ring_buffer_max_lines)
109 {
110 /* We have an overlap, and the ring_buffer_next_index points to
111 * the "first" item. Free it to make room for the new item.
112 */
113
114 g_assert (ring_buffer[ring_buffer_next_index] != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if (ring_buffer[ring_buffer_next_index] != ((void*)0)) _g_boolean_var_29
= 1; else _g_boolean_var_29 = 0; _g_boolean_var_29; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-debug-log.c"
, 114, ((const char*) (__func__)), "ring_buffer[ring_buffer_next_index] != NULL"
); } while (0)
;
115 g_free (ring_buffer[ring_buffer_next_index]);
116 }
117 else
118 ring_buffer_num_lines++;
119
120 g_assert (ring_buffer_num_lines <= ring_buffer_max_lines)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if (ring_buffer_num_lines <= ring_buffer_max_lines) _g_boolean_var_30
= 1; else _g_boolean_var_30 = 0; _g_boolean_var_30; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-debug-log.c"
, 120, ((const char*) (__func__)), "ring_buffer_num_lines <= ring_buffer_max_lines"
); } while (0)
;
121
122 ring_buffer[ring_buffer_next_index] = str;
123
124 ring_buffer_next_index++;
125 if (ring_buffer_next_index == ring_buffer_max_lines)
126 {
127 ring_buffer_next_index = 0;
128 g_assert (ring_buffer_num_lines == ring_buffer_max_lines)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if (ring_buffer_num_lines == ring_buffer_max_lines) _g_boolean_var_31
= 1; else _g_boolean_var_31 = 0; _g_boolean_var_31; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-debug-log.c"
, 128, ((const char*) (__func__)), "ring_buffer_num_lines == ring_buffer_max_lines"
); } while (0)
;
129 }
130}
131
132static void
133add_to_milestones (const char *str)
134{
135 char *str_copy;
136
137 str_copy = g_strdup (str)g_strdup_inline (str);
138
139 if (milestones_tail)
140 {
141 milestones_tail = g_slist_append (milestones_tail, str_copy);
142 milestones_tail = milestones_tail->next;
143 }
144 else
145 {
146 milestones_head = milestones_tail = g_slist_append (NULL((void*)0), str_copy);
147 }
148
149 g_assert (milestones_head != NULL && milestones_tail != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if (milestones_head != ((void*)0) && milestones_tail
!= ((void*)0)) _g_boolean_var_32 = 1; else _g_boolean_var_32
= 0; _g_boolean_var_32; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 149, ((const char*) (__func__
)), "milestones_head != NULL && milestones_tail != NULL"
); } while (0)
;
150}
151
152void
153caja_debug_logv (gboolean is_milestone, const char *domain, const GList *uris, const char *format, va_list args)
154{
155 char *str;
156 char *debug_str;
157#if GLIB_CHECK_VERSION(2,65,2)(2 > (2) || (2 == (2) && 80 > (65)) || (2 == (2
) && 80 == (65) && 3 >= (2)))
158 char *date_str;
159 GDateTime* datetime;
160#else
161 struct timeval tv;
162 struct tm tm;
163#endif
164
165 lock ();
166
167 if (!(is_milestone || is_domain_enabled (domain)))
168 goto out;
169
170 str = g_strdup_vprintf (format, args);
171
172#if GLIB_CHECK_VERSION(2,65,2)(2 > (2) || (2 == (2) && 80 > (65)) || (2 == (2
) && 80 == (65) && 3 >= (2)))
173 datetime = g_date_time_new_now_local ();
174 date_str = g_date_time_format (datetime, "%Y/%m/%d %H:%M:%S.%f");
175 g_date_time_unref (datetime);
176 debug_str = g_strdup_printf ("%p %s (%s): %s",
177 g_thread_self (),
178 date_str,
179 domain,
180 str);
181 g_free (date_str);
182#else
183 gettimeofday (&tv, NULL((void*)0));
184 tm = *localtime (&tv.tv_sec);
185 debug_str = g_strdup_printf ("%p %04d/%02d/%02d %02d:%02d:%02d.%04d (%s): %s",
186 g_thread_self (),
187 tm.tm_year + 1900,
188 tm.tm_mon + 1,
189 tm.tm_mday,
190 tm.tm_hour,
191 tm.tm_min,
192 tm.tm_sec,
193 (int) (tv.tv_usec / 100),
194 domain,
195 str);
196#endif
197 g_free (str);
198
199 if (uris)
200 {
201 int debug_str_len;
202 int uris_len;
203 const GList *l;
204 char *new_str;
205 char *p;
206 int count;
207
208 uris_len = 0;
209
210 count = 0;
211 for (l = uris; l; l = l->next)
212 {
213 const char *uri;
214
215 uri = l->data;
216 uris_len += strlen (uri) + 2; /* plus 2 for a tab and the newline */
217
218 if (count++ > MAX_URI_COUNT20)
219 {
220 uris_len += 4; /* "...\n" */
221 break;
222 }
223
224 }
225
226 debug_str_len = strlen (debug_str);
227 new_str = g_new (char, debug_str_len + 1 + uris_len + 1)(char *) (__extension__ ({ gsize __n = (gsize) (debug_str_len
+ 1 + uris_len + 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; }))
; /* plus 1 for newline & zero */
228
229 p = g_stpcpy (new_str, debug_str);
230 *p++ = '\n';
231
232 count = 0;
233 for (l = uris; l; l = l->next)
234 {
235 const char *uri;
236
237 uri = l->data;
238
239 *p++ = '\t';
240
241 p = g_stpcpy (p, uri);
242
243 if (l->next)
244 *p++ = '\n';
245
246 if (count++ > MAX_URI_COUNT20)
247 {
248 p = g_stpcpy (p, "...\n");
Value stored to 'p' is never read
249 break;
250 }
251 }
252
253 g_free (debug_str);
254 debug_str = new_str;
255 }
256
257 add_to_ring (debug_str);
258 if (is_milestone)
259 add_to_milestones (debug_str);
260
261out:
262 unlock ();
263}
264
265void
266caja_debug_log_with_uri_list (gboolean is_milestone, const char *domain, const GList *uris,
267 const char *format, ...)
268{
269 va_list args;
270
271 va_start (args, format)__builtin_va_start(args, format);
272 caja_debug_logv (is_milestone, domain, uris, format, args);
273 va_end (args)__builtin_va_end(args);
274}
275
276void
277caja_debug_log_with_file_list (gboolean is_milestone, const char *domain, GList *files,
278 const char *format, ...)
279{
280 va_list args;
281 GList *uris;
282 GList *l;
283 int count;
284
285 /* Avoid conversion if debugging disabled */
286 if (!(is_milestone ||
287 caja_debug_log_is_domain_enabled (domain)))
288 {
289 return;
290 }
291
292 uris = NULL((void*)0);
293
294 count = 0;
295 for (l = files; l; l = l->next)
296 {
297 CajaFile *file;
298 char *uri;
299
300 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
301 uri = caja_file_get_uri (file);
302
303 if (caja_file_is_gone (file))
304 {
305 char *new_uri;
306
307 /* Hack: this will create an invalid URI, but it's for
308 * display purposes only.
309 */
310 new_uri = g_strconcat (uri ? uri : "", " (gone)", NULL((void*)0));
311 g_free (uri);
312 uri = new_uri;
313 }
314 uris = g_list_prepend (uris, uri);
315
316 /* Avoid doing to much work, more than MAX_URI_COUNT uris
317 won't be shown anyway */
318 if (count++ > MAX_URI_COUNT20 + 1)
319 {
320 break;
321 }
322 }
323
324 uris = g_list_reverse (uris);
325
326 va_start (args, format)__builtin_va_start(args, format);
327 caja_debug_logv (is_milestone, domain, uris, format, args);
328 va_end (args)__builtin_va_end(args);
329
330 g_list_free_full (uris, g_free);
331}
332
333gboolean
334caja_debug_log_load_configuration (const char *filename, GError **error)
335{
336 GKeyFile *key_file;
337 char **strings;
338 gsize num_strings;
339 int num;
340 GError *my_error;
341
342 g_assert (filename != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if (filename != ((void*)0)) _g_boolean_var_33 = 1; else _g_boolean_var_33
= 0; _g_boolean_var_33; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 342, ((const char*) (__func__
)), "filename != NULL"); } while (0)
;
343 g_assert (error == NULL || *error == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_34
= 1; else _g_boolean_var_34 = 0; _g_boolean_var_34; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-debug-log.c"
, 343, ((const char*) (__func__)), "error == NULL || *error == NULL"
); } while (0)
;
344
345 key_file = g_key_file_new ();
346
347 if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error))
348 {
349 g_key_file_free (key_file);
350 return FALSE(0);
351 }
352
353 /* Domains */
354
355 my_error = NULL((void*)0);
356 strings = g_key_file_get_string_list (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_DOMAINS_KEY"enable domains", &num_strings, &my_error);
357 if (my_error)
358 g_error_free (my_error);
359 else
360 {
361 int i;
362
363 for (i = 0; i < num_strings; i++)
364 strings[i] = g_strstrip (strings[i])g_strchomp (g_strchug (strings[i]));
365
366 caja_debug_log_enable_domains ((const char **) strings, num_strings);
367 g_strfreev (strings);
368 }
369
370 /* Number of lines */
371
372 my_error = NULL((void*)0);
373 num = g_key_file_get_integer (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_MAX_LINES_KEY"max lines", &my_error);
374 if (my_error)
375 g_error_free (my_error);
376 else
377 caja_debug_log_set_max_lines (num);
378
379 g_key_file_free (key_file);
380 return TRUE(!(0));
381}
382
383void
384caja_debug_log_enable_domains (const char **domains, int n_domains)
385{
386 int i;
387
388 g_assert (domains != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if (domains != ((void*)0)) _g_boolean_var_35 = 1; else _g_boolean_var_35
= 0; _g_boolean_var_35; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 388, ((const char*) (__func__
)), "domains != NULL"); } while (0)
;
389 g_assert (n_domains >= 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if (n_domains >= 0) _g_boolean_var_36 = 1; else _g_boolean_var_36
= 0; _g_boolean_var_36; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 389, ((const char*) (__func__
)), "n_domains >= 0"); } while (0)
;
390
391 lock ();
392
393 if (!domains_hash)
394 domains_hash = g_hash_table_new (g_str_hash, g_str_equal);
395
396 for (i = 0; i < n_domains; i++)
397 {
398 g_assert (domains[i] != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if (domains[i] != ((void*)0)) _g_boolean_var_37 = 1; else _g_boolean_var_37
= 0; _g_boolean_var_37; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 398, ((const char*) (__func__
)), "domains[i] != NULL"); } while (0)
;
399
400 if (strcmp (domains[i], CAJA_DEBUG_LOG_DOMAIN_USER"USER") == 0)
401 continue; /* user actions are always enabled */
402
403 if (g_hash_table_lookup (domains_hash, domains[i]) == NULL((void*)0))
404 {
405 char *domain;
406
407 domain = g_strdup (domains[i])g_strdup_inline (domains[i]);
408 g_hash_table_insert (domains_hash, domain, domain);
409 }
410 }
411
412 unlock ();
413}
414
415void
416caja_debug_log_disable_domains (const char **domains, int n_domains)
417{
418 g_assert (domains != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if (domains != ((void*)0)) _g_boolean_var_38 = 1; else _g_boolean_var_38
= 0; _g_boolean_var_38; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 418, ((const char*) (__func__
)), "domains != NULL"); } while (0)
;
419 g_assert (n_domains >= 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if (n_domains >= 0) _g_boolean_var_39 = 1; else _g_boolean_var_39
= 0; _g_boolean_var_39; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 419, ((const char*) (__func__
)), "n_domains >= 0"); } while (0)
;
420
421 lock ();
422
423 if (domains_hash)
424 {
425 int i;
426
427 for (i = 0; i < n_domains; i++)
428 {
429 char *domain;
430
431 g_assert (domains[i] != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_40
; if (domains[i] != ((void*)0)) _g_boolean_var_40 = 1; else _g_boolean_var_40
= 0; _g_boolean_var_40; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 431, ((const char*) (__func__
)), "domains[i] != NULL"); } while (0)
;
432
433 if (strcmp (domains[i], CAJA_DEBUG_LOG_DOMAIN_USER"USER") == 0)
434 continue; /* user actions are always enabled */
435
436 domain = g_hash_table_lookup (domains_hash, domains[i]);
437 if (domain)
438 {
439 g_hash_table_remove (domains_hash, domain);
440 g_free (domain);
441 }
442 }
443 } /* else, there is nothing to disable */
444
445 unlock ();
446}
447
448gboolean
449caja_debug_log_is_domain_enabled (const char *domain)
450{
451 gboolean retval;
452
453 g_assert (domain != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_41
; if (domain != ((void*)0)) _g_boolean_var_41 = 1; else _g_boolean_var_41
= 0; _g_boolean_var_41; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 453, ((const char*) (__func__
)), "domain != NULL"); } while (0)
;
454
455 lock ();
456 retval = is_domain_enabled (domain);
457 unlock ();
458
459 return retval;
460}
461
462struct domains_dump_closure
463{
464 char **domains;
465 int num_domains;
466};
467
468static void
469domains_foreach_dump_cb (gpointer key, gpointer value, gpointer data)
470{
471 struct domains_dump_closure *closure;
472 char *domain;
473
474 closure = data;
475 domain = key;
476
477 closure->domains[closure->num_domains] = domain;
478 closure->num_domains++;
479}
480
481static GKeyFile *
482make_key_file_from_configuration (void)
483{
484 GKeyFile *key_file;
485 struct domains_dump_closure closure;
486
487 key_file = g_key_file_new ();
488
489 /* domains */
490
491 if (domains_hash)
492 {
493 int num_domains;
494
495 num_domains = g_hash_table_size (domains_hash);
496 if (num_domains != 0)
497 {
498 closure.domains = g_new (char *, num_domains)(char * *) (__extension__ ({ gsize __n = (gsize) (num_domains
); 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; }))
;
499 closure.num_domains = 0;
500
501 g_hash_table_foreach (domains_hash, domains_foreach_dump_cb, &closure);
502 g_assert (num_domains == closure.num_domains)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_42
; if (num_domains == closure.num_domains) _g_boolean_var_42 =
1; else _g_boolean_var_42 = 0; _g_boolean_var_42; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-debug-log.c", 502
, ((const char*) (__func__)), "num_domains == closure.num_domains"
); } while (0)
;
503
504 g_key_file_set_string_list (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_DOMAINS_KEY"enable domains",
505 (const gchar * const *) closure.domains, closure.num_domains);
506 g_free (closure.domains);
507 }
508 }
509
510 /* max lines */
511
512 g_key_file_set_integer (key_file, KEY_FILE_GROUP"debug log", KEY_FILE_MAX_LINES_KEY"max lines", ring_buffer_max_lines);
513
514 return key_file;
515}
516
517static gboolean
518write_string (const char *filename, FILE *file, const char *str, GError **error)
519{
520 if (fputs (str, file) == EOF(-1))
521 {
522 int saved_errno;
523
524 saved_errno = errno(*__errno_location ());
525 g_set_error (error,
526 G_FILE_ERRORg_file_error_quark (),
527 g_file_error_from_errno (saved_errno),
528 "error when writing to log file %s", filename);
529
530 return FALSE(0);
531 }
532
533 return TRUE(!(0));
534}
535
536static gboolean
537dump_configuration (const char *filename, FILE *file, GError **error)
538{
539 GKeyFile *key_file;
540 char *data;
541 gsize length;
542 gboolean success;
543
544 if (!write_string (filename, file,
545 "\n\n"
546 "This configuration for the debug log can be re-created\n"
547 "by putting the following in ~/caja-debug-log.conf\n"
548 "(use ';' to separate domain names):\n\n",
549 error))
550 {
551 return FALSE(0);
552 }
553
554 success = FALSE(0);
555
556 key_file = make_key_file_from_configuration ();
557
558 data = g_key_file_to_data (key_file, &length, error);
559 if (!data)
560 goto out;
561
562 if (!write_string (filename, file, data, error))
563 {
564 goto out;
565 }
566
567 success = TRUE(!(0));
568out:
569 g_key_file_free (key_file);
570 return success;
571}
572
573static gboolean
574dump_milestones (const char *filename, FILE *file, GError **error)
575{
576 GSList *l;
577
578 if (!write_string (filename, file, "===== BEGIN MILESTONES =====\n", error))
579 return FALSE(0);
580
581 for (l = milestones_head; l; l = l->next)
582 {
583 const char *str;
584
585 str = l->data;
586 if (!(write_string (filename, file, str, error)
587 && write_string (filename, file, "\n", error)))
588 return FALSE(0);
589 }
590
591 if (!write_string (filename, file, "===== END MILESTONES =====\n", error))
592 return FALSE(0);
593
594 return TRUE(!(0));
595}
596
597static gboolean
598dump_ring_buffer (const char *filename, FILE *file, GError **error)
599{
600 int start_index;
601 int i;
602
603 if (!write_string (filename, file, "===== BEGIN RING BUFFER =====\n", error))
604 return FALSE(0);
605
606 if (ring_buffer_num_lines == ring_buffer_max_lines)
607 start_index = ring_buffer_next_index;
608 else
609 start_index = 0;
610
611 for (i = 0; i < ring_buffer_num_lines; i++)
612 {
613 int idx;
614
615 idx = (start_index + i) % ring_buffer_max_lines;
616
617 if (!(write_string (filename, file, ring_buffer[idx], error)
618 && write_string (filename, file, "\n", error)))
619 {
620 return FALSE(0);
621 }
622 }
623
624 if (!write_string (filename, file, "===== END RING BUFFER =====\n", error))
625 return FALSE(0);
626
627 return TRUE(!(0));
628}
629
630gboolean
631caja_debug_log_dump (const char *filename, GError **error)
632{
633 FILE *file;
634 gboolean success;
635
636 g_assert (error == NULL || *error == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_43
; if (error == ((void*)0) || *error == ((void*)0)) _g_boolean_var_43
= 1; else _g_boolean_var_43 = 0; _g_boolean_var_43; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-debug-log.c"
, 636, ((const char*) (__func__)), "error == NULL || *error == NULL"
); } while (0)
;
637
638 lock ();
639
640 success = FALSE(0);
641
642 file = fopen (filename, "w");
643 if (!file)
644 {
645 int saved_errno;
646
647 saved_errno = errno(*__errno_location ());
648 g_set_error (error,
649 G_FILE_ERRORg_file_error_quark (),
650 g_file_error_from_errno (saved_errno),
651 "could not open log file %s", filename);
652 goto out;
653 }
654
655 if (!(dump_milestones (filename, file, error)
656 && dump_ring_buffer (filename, file, error)
657 && dump_configuration (filename, file, error)))
658 {
659 goto do_close;
660 }
661
662 success = TRUE(!(0));
663
664do_close:
665
666 if (fclose (file) != 0)
667 {
668 int saved_errno;
669
670 saved_errno = errno(*__errno_location ());
671
672 if (error && *error)
673 {
674 g_error_free (*error);
675 *error = NULL((void*)0);
676 }
677
678 g_set_error (error,
679 G_FILE_ERRORg_file_error_quark (),
680 g_file_error_from_errno (saved_errno),
681 "error when closing log file %s", filename);
682 success = FALSE(0);
683 }
684
685out:
686
687 unlock ();
688 return success;
689}
690
691void
692caja_debug_log_set_max_lines (int num_lines)
693{
694 char **new_buffer;
695 int lines_to_copy;
696
697 g_assert (num_lines > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_44
; if (num_lines > 0) _g_boolean_var_44 = 1; else _g_boolean_var_44
= 0; _g_boolean_var_44; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-debug-log.c", 697, ((const char*) (__func__
)), "num_lines > 0"); } while (0)
;
698
699 lock ();
700
701 if (num_lines == ring_buffer_max_lines)
702 goto out;
703
704 new_buffer = g_new0 (char *, num_lines)(char * *) (__extension__ ({ gsize __n = (gsize) (num_lines);
gsize __s = sizeof (char *); 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; }))
;
705
706 lines_to_copy = MIN (num_lines, ring_buffer_num_lines)(((num_lines) < (ring_buffer_num_lines)) ? (num_lines) : (
ring_buffer_num_lines))
;
707
708 if (ring_buffer)
709 {
710 int start_index;
711 int i;
712
713 if (ring_buffer_num_lines == ring_buffer_max_lines)
714 start_index = (ring_buffer_next_index + ring_buffer_max_lines - lines_to_copy) % ring_buffer_max_lines;
715 else
716 start_index = ring_buffer_num_lines - lines_to_copy;
717
718 g_assert (start_index >= 0 && start_index < ring_buffer_max_lines)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_45
; if (start_index >= 0 && start_index < ring_buffer_max_lines
) _g_boolean_var_45 = 1; else _g_boolean_var_45 = 0; _g_boolean_var_45
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-debug-log.c"
, 718, ((const char*) (__func__)), "start_index >= 0 && start_index < ring_buffer_max_lines"
); } while (0)
;
719
720 for (i = 0; i < lines_to_copy; i++)
721 {
722 int idx;
723
724 idx = (start_index + i) % ring_buffer_max_lines;
725
726 new_buffer[i] = ring_buffer[idx];
727 ring_buffer[idx] = NULL((void*)0);
728 }
729
730 for (i = 0; i < ring_buffer_max_lines; i++)
731 g_free (ring_buffer[i]);
732
733 g_free (ring_buffer);
734 }
735
736 ring_buffer = new_buffer;
737 ring_buffer_next_index = lines_to_copy;
738 ring_buffer_num_lines = lines_to_copy;
739 ring_buffer_max_lines = num_lines;
740
741out:
742
743 unlock ();
744}
745
746int
747caja_debug_log_get_max_lines (void)
748{
749 int retval;
750
751 lock ();
752 retval = ring_buffer_max_lines;
753 unlock ();
754
755 return retval;
756}
757
758void
759caja_debug_log_clear (void)
760{
761 int i;
762
763 lock ();
764
765 if (!ring_buffer)
766 goto out;
767
768 for (i = 0; i < ring_buffer_max_lines; i++)
769 {
770 g_free (ring_buffer[i]);
771 ring_buffer[i] = NULL((void*)0);
772 }
773
774 ring_buffer_next_index = 0;
775 ring_buffer_num_lines = 0;
776
777out:
778 unlock ();
779}
diff --git a/2024-07-29-023715-6438-1/report-337a86.html b/2024-07-29-023715-6438-1/report-337a86.html new file mode 100644 index 000000000..c48fa5a33 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-337a86.html @@ -0,0 +1,761 @@ + + + +test-eel-labeled-image.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test/test-eel-labeled-image.c
Warning:line 75, column 28
This statement is never executed
+ +

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 test-eel-labeled-image.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 -fdebug-compilation-dir=/rootdir/test -fcoverage-compilation-dir=/rootdir/test -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D VERSION="1.26.4" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local//locale" -D PIXBUFDIR="/usr/local/share/pixmaps" -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c test-eel-labeled-image.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <eel/eel-labeled-image.h>
2
3#include "test.h"
4
5static const char icon_name[] = "gnome-globe";
6
7static void
8button_callback (GtkWidget *button,
9 gpointer callback_data)
10{
11 const char *info = callback_data;
12 g_return_if_fail (GTK_IS_BUTTON (button))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_11
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); 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; }))))) _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__)), "GTK_IS_BUTTON (button)"); return; } } while (
0)
;
13
14 g_print ("%s(%p)\n", info, button);
15}
16
17static GtkWidget *
18labeled_image_button_window_new (const char *title,
19 GdkPixbuf *pixbuf)
20{
21 GtkWidget *window;
22 GtkWidget *vbox;
23 GtkWidget *button;
24 GtkWidget *toggle_button;
25 GtkWidget *check_button;
26 GtkWidget *plain;
27
28 window = test_window_new (title, 20);
29 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
30 gtk_container_add (GTK_CONTAINER (window)((((GtkContainer*) (void *) ((window))))), vbox);
31
32 if (1) button = eel_labeled_image_button_new ("GtkButton with LabeledImage", pixbuf);
33 if (1) toggle_button = eel_labeled_image_toggle_button_new ("GtkToggleButton with LabeledImage", pixbuf);
34 if (1) check_button = eel_labeled_image_check_button_new ("GtkCheckButton with LabeledImage", pixbuf);
35 if (1) {
36 plain = eel_labeled_image_new ("Plain LabeledImage", pixbuf);
37 eel_labeled_image_set_can_focus (EEL_LABELED_IMAGE (plain)((((EelLabeledImage*) (void *) ((plain))))), TRUE(!(0)));
38 }
39
40 if (button) gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), button, TRUE(!(0)), TRUE(!(0)), 0);
41 if (toggle_button) gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), toggle_button, TRUE(!(0)), TRUE(!(0)), 0);
42 if (check_button) gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), check_button, TRUE(!(0)), TRUE(!(0)), 0);
43 if (plain) gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), plain, TRUE(!(0)), TRUE(!(0)), 0);
44
45 if (button) {
46 g_signal_connect (button, "enter", G_CALLBACK (button_callback), "enter")g_signal_connect_data ((button), ("enter"), (((GCallback) (button_callback
))), ("enter"), ((void*)0), (GConnectFlags) 0)
;
47 g_signal_connect (button, "leave", G_CALLBACK (button_callback), "leave")g_signal_connect_data ((button), ("leave"), (((GCallback) (button_callback
))), ("leave"), ((void*)0), (GConnectFlags) 0)
;
48 g_signal_connect (button, "pressed", G_CALLBACK (button_callback), "pressed")g_signal_connect_data ((button), ("pressed"), (((GCallback) (
button_callback))), ("pressed"), ((void*)0), (GConnectFlags) 0
)
;
49 g_signal_connect (button, "released", G_CALLBACK (button_callback), "released")g_signal_connect_data ((button), ("released"), (((GCallback) (
button_callback))), ("released"), ((void*)0), (GConnectFlags)
0)
;
50 g_signal_connect (button, "clicked", G_CALLBACK (button_callback), "clicked")g_signal_connect_data ((button), ("clicked"), (((GCallback) (
button_callback))), ("clicked"), ((void*)0), (GConnectFlags) 0
)
;
51 }
52
53 gtk_widget_show_all (vbox);
54
55 return window;
56}
57
58int
59main (int argc, char* argv[])
60{
61 GtkWidget *labeled_image_window = NULL((void*)0);
62 GtkWidget *labeled_image_button_window = NULL((void*)0);
63 GdkPixbuf *pixbuf = NULL((void*)0);
64 GtkIconTheme *icon_theme = NULL((void*)0);
65
66 test_init (&argc, &argv);
67
68 icon_theme = gtk_icon_theme_get_default ();
69
70 if (1) pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name, 32, GTK_ICON_LOOKUP_USE_BUILTIN, NULL((void*)0));
71 if (1) labeled_image_button_window = labeled_image_button_window_new ("LabeledImage in GtkButton Test", pixbuf);
72
73 eel_gdk_pixbuf_unref_if_not_null (pixbuf);
74
75 if (labeled_image_window) gtk_widget_show (labeled_image_window);
This statement is never executed
76 if (labeled_image_button_window) gtk_widget_show (labeled_image_button_window);
77
78 gtk_main ();
79
80 return test_quit (EXIT_SUCCESS0);
81}
diff --git a/2024-07-29-023715-6438-1/report-3574f0.html b/2024-07-29-023715-6438-1/report-3574f0.html new file mode 100644 index 000000000..0ce99e1e3 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-3574f0.html @@ -0,0 +1,1435 @@ + + + +eel-gdk-extensions.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-gdk-extensions.c
Warning:line 106, column 17
Access of the string literal at index 1, while it holds only a single 'char' element
+ +

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 eel-gdk-extensions.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-gdk-extensions.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* eel-gdk-extensions.c: Graphics routines to augment what's in gdk.
4
5 Copyright (C) 1999, 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Darin Adler <darin@eazel.com>,
23 Pavel Cisler <pavel@eazel.com>,
24 Ramiro Estrugo <ramiro@eazel.com>
25*/
26
27#include <config.h>
28#include "eel-gdk-extensions.h"
29
30#include "eel-glib-extensions.h"
31#include "eel-lib-self-check-functions.h"
32#include "eel-string.h"
33#include <gdk-pixbuf/gdk-pixbuf.h>
34#include <gdk/gdkprivate.h>
35#include <gdk/gdk.h>
36#include <gdk/gdkx.h>
37#include <stdlib.h>
38#include <pango/pango.h>
39
40/**
41 * eel_gradient_new
42 * @start_color: Color for the top or left.
43 * @end_color: Color for the bottom or right.
44 * @is_horizontal: Direction of the gradient.
45 *
46 * Create a string that combines the start and end colors along
47 * with the direction of the gradient in a standard format.
48 */
49char *
50eel_gradient_new (const char *start_color,
51 const char *end_color,
52 gboolean is_horizontal)
53{
54 /* Handle the special case where the start and end colors are identical.
55 Handle the special case where the end color is an empty string.
56 */
57 if (eel_strcmp(start_color, end_color) == 0 || end_color == NULL((void*)0) || end_color[0] == '\0')
58 {
59 return g_strdup (start_color)g_strdup_inline (start_color);
60 }
61
62 /* Handle the special case where the start color is an empty string. */
63 if (start_color == NULL((void*)0) || start_color[0] == '\0')
64 {
65 return g_strdup (end_color)g_strdup_inline (end_color);
66 }
67
68 /* Handle the general case. */
69 return g_strconcat (start_color, "-", end_color, is_horizontal ? ":h" : NULL((void*)0), NULL((void*)0));
70}
71
72/**
73 * eel_gradient_is_gradient
74 * @gradient_spec: A gradient spec. string.
75 *
76 * Return true if the spec. specifies a gradient instead of a solid color.
77 */
78gboolean
79eel_gradient_is_gradient (const char *gradient_spec)
80{
81 return eel_strchr (gradient_spec, '-') != NULL((void*)0);
82}
83
84/**
85 * eel_gradient_is_horizontal
86 * @gradient_spec: A gradient spec. string.
87 *
88 * Return true if the spec. specifies a horizontal gradient.
89 */
90gboolean
91eel_gradient_is_horizontal (const char *gradient_spec)
92{
93 size_t length;
94
95 length = eel_strlen (gradient_spec);
96 return length >= 2 && gradient_spec[length - 2] == ':' && gradient_spec[length - 1] == 'h';
97}
98
99static char *
100eel_gradient_strip_trailing_direction_if_any (const char *gradient_spec)
101{
102 size_t length;
103
104 length = eel_strlen (gradient_spec);
105 if (length >= 2 && gradient_spec[length - 2] == ':'
18
Assuming 'length' is >= 2
19
Assuming the condition is true
106 && (gradient_spec[length - 1] == 'v' || gradient_spec[length - 1] == 'h'))
20
Access of the string literal at index 1, while it holds only a single 'char' element
107 {
108 length -= 2;
109 }
110
111 return g_strndup (gradient_spec, length);
112}
113
114/* For parsing n-point gradients. Successive calls should pass the next_spec value
115 * set by the previous call as their first argument - to continue parsing where the
116 * previous call left off.
117 */
118char *
119eel_gradient_parse_one_color_spec (const char *spec, int *percent, const char **next_spec)
120{
121 char *result;
122 const char *rgb_end_ptr;
123 const char *percent_ptr;
124 const char *separator_ptr;
125
126 percent_ptr = eel_strchr (spec, '%');
127 separator_ptr = eel_strchr (spec, '-');
128
129 if (percent_ptr != NULL((void*)0) && (separator_ptr == NULL((void*)0) || percent_ptr < separator_ptr))
13
Assuming 'percent_ptr' is equal to NULL
130 {
131 if (percent != NULL((void*)0))
132 {
133 *percent = (int) strtol (percent_ptr + 1, NULL((void*)0), 10);
134 }
135 rgb_end_ptr = percent_ptr;
136 }
137 else
138 {
139 if (percent
13.1
'percent' is equal to NULL
!= NULL((void*)0))
14
Taking false branch
140 {
141 *percent = 100;
142 }
143 rgb_end_ptr = separator_ptr;
144 }
145
146 if (rgb_end_ptr != NULL((void*)0))
15
Assuming 'rgb_end_ptr' is equal to NULL
16
Taking false branch
147 {
148 result = g_strndup (spec, rgb_end_ptr - spec);
149 }
150 else
151 {
152 result = eel_gradient_strip_trailing_direction_if_any (spec);
17
Calling 'eel_gradient_strip_trailing_direction_if_any'
153 }
154
155 /* It's important not to use spec after setting *next_spec because it's
156 * likely that *next_spec == spec.
157 */
158 if (next_spec != NULL((void*)0))
159 {
160 *next_spec = (separator_ptr != NULL((void*)0)) ? separator_ptr + 1 : NULL((void*)0);
161 }
162
163 return result;
164}
165
166/* FIXME bugzilla.eazel.com 5076:
167 * anyone using eel_gradient_get_start_color_spec or
168 * eel_gradient_get_end_color_spec is assuming the gradient
169 * is 2 colors which is questionable.
170 *
171 * Callers should be rewritten and these fns eliminated.
172 */
173
174/**
175 * eel_gradient_get_start_color_spec
176 * @gradient_spec: A gradient spec. string.
177 *
178 * Return the start color.
179 * This may be the entire gradient_spec if it's a solid color.
180 */
181char *
182eel_gradient_get_start_color_spec (const char *gradient_spec)
183{
184 return eel_gradient_parse_one_color_spec (gradient_spec, NULL((void*)0), NULL((void*)0));
12
Calling 'eel_gradient_parse_one_color_spec'
185}
186
187/**
188 * eel_gradient_get_end_color_spec
189 * @gradient_spec: A gradient spec. string.
190 *
191 * Return the end color.
192 * This may be the entire gradient_spec if it's a solid color.
193 */
194char *
195eel_gradient_get_end_color_spec (const char *gradient_spec)
196{
197 char* color = NULL((void*)0);
198
199 do
200 {
201 g_free (color);
202 color = eel_gradient_parse_one_color_spec (gradient_spec, NULL((void*)0), &gradient_spec);
203 }
204 while (gradient_spec != NULL((void*)0));
205
206 return color;
207}
208
209/* Do the work shared by all the set_color_spec functions below. */
210static char *
211eel_gradient_set_edge_color (const char *gradient_spec,
212 const char *edge_color,
213 gboolean is_horizontal,
214 gboolean change_end)
215{
216 char *opposite_color;
217 char *result;
218
219 g_assert (edge_color != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (edge_color != ((void*)0)) _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-gdk-extensions.c", 219, ((const char*) (__func__
)), "edge_color != NULL"); } while (0)
;
220
221 /* Get the color from the existing gradient spec. for the opposite
222 edge. This will parse away all the stuff we don't want from the
223 old gradient spec.
224 */
225 opposite_color = change_end
226 ? eel_gradient_get_start_color_spec (gradient_spec)
227 : eel_gradient_get_end_color_spec (gradient_spec);
228
229 /* Create a new gradient spec. The eel_gradient_new function handles
230 some special cases, so we don't have to bother with them here.
231 */
232 result = eel_gradient_new (change_end ? opposite_color : edge_color,
233 change_end ? edge_color : opposite_color,
234 is_horizontal);
235
236 g_free (opposite_color);
237
238 return result;
239}
240
241/**
242 * eel_gradient_set_left_color_spec
243 * @gradient_spec: A gradient spec. string.
244 * @left_color: Color spec. to replace left color with.
245 *
246 * Changes the left color to what's passed in.
247 * This creates a horizontal gradient.
248 */
249char *
250eel_gradient_set_left_color_spec (const char *gradient_spec,
251 const char *left_color)
252{
253 g_return_val_if_fail (gradient_spec != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if (gradient_spec != ((void*)0)) _g_boolean_var_26 = 1; else
_g_boolean_var_26 = 0; _g_boolean_var_26; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"gradient_spec != NULL"); return (((void*)0)); } } while (0)
;
254 g_return_val_if_fail (left_color != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if (left_color != ((void*)0)) _g_boolean_var_27 = 1; else _g_boolean_var_27
= 0; _g_boolean_var_27; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "left_color != NULL"); return
(((void*)0)); } } while (0)
;
255
256 return eel_gradient_set_edge_color (gradient_spec, left_color, TRUE(!(0)), FALSE(0));
257}
258
259/**
260 * eel_gradient_set_top_color_spec
261 * @gradient_spec: A gradient spec. string.
262 * @top_color: Color spec. to replace top color with.
263 *
264 * Changes the top color to what's passed in.
265 * This creates a vertical gradient.
266 */
267char *
268eel_gradient_set_top_color_spec (const char *gradient_spec,
269 const char *top_color)
270{
271 g_return_val_if_fail (gradient_spec != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_28
; if (gradient_spec != ((void*)0)) _g_boolean_var_28 = 1; else
_g_boolean_var_28 = 0; _g_boolean_var_28; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"gradient_spec != NULL"); return (((void*)0)); } } while (0)
;
272 g_return_val_if_fail (top_color != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if (top_color != ((void*)0)) _g_boolean_var_29 = 1; else _g_boolean_var_29
= 0; _g_boolean_var_29; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "top_color != NULL"); return
(((void*)0)); } } while (0)
;
273
274 return eel_gradient_set_edge_color (gradient_spec, top_color, FALSE(0), FALSE(0));
275}
276
277/**
278 * eel_gradient_set_right_color_spec
279 * @gradient_spec: A gradient spec. string.
280 * @right_color: Color spec. to replace right color with.
281 *
282 * Changes the right color to what's passed in.
283 * This creates a horizontal gradient.
284 */
285char *
286eel_gradient_set_right_color_spec (const char *gradient_spec,
287 const char *right_color)
288{
289 g_return_val_if_fail (gradient_spec != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if (gradient_spec != ((void*)0)) _g_boolean_var_30 = 1; else
_g_boolean_var_30 = 0; _g_boolean_var_30; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"gradient_spec != NULL"); return (((void*)0)); } } while (0)
;
290 g_return_val_if_fail (right_color != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if (right_color != ((void*)0)) _g_boolean_var_31 = 1; else _g_boolean_var_31
= 0; _g_boolean_var_31; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "right_color != NULL"); return
(((void*)0)); } } while (0)
;
291
292 return eel_gradient_set_edge_color (gradient_spec, right_color, TRUE(!(0)), TRUE(!(0)));
293}
294
295/**
296 * eel_gradient_set_bottom_color_spec
297 * @gradient_spec: A gradient spec. string.
298 * @bottom_color: Color spec. to replace bottom color with.
299 *
300 * Changes the bottom color to what's passed in.
301 * This creates a vertical gradient.
302 */
303char *
304eel_gradient_set_bottom_color_spec (const char *gradient_spec,
305 const char *bottom_color)
306{
307 g_return_val_if_fail (gradient_spec != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if (gradient_spec != ((void*)0)) _g_boolean_var_32 = 1; else
_g_boolean_var_32 = 0; _g_boolean_var_32; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"gradient_spec != NULL"); return (((void*)0)); } } while (0)
;
308 g_return_val_if_fail (bottom_color != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if (bottom_color != ((void*)0)) _g_boolean_var_33 = 1; else
_g_boolean_var_33 = 0; _g_boolean_var_33; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"bottom_color != NULL"); return (((void*)0)); } } while (0)
;
309
310 return eel_gradient_set_edge_color (gradient_spec, bottom_color, FALSE(0), TRUE(!(0)));
311}
312
313/**
314 * eel_gdk_rgba_parse_with_white_default
315 * @color: Pointer to place to put resulting color.
316 * @color_spec: A color spec, or NULL.
317 *
318 * The same as gdk_rgba_parse, except sets the color to white if
319 * the spec. can't be parsed, instead of returning a boolean flag.
320 */
321void
322eel_gdk_rgba_parse_with_white_default (GdkRGBA *color,
323 const char *color_spec)
324{
325 gboolean got_color;
326
327 g_return_if_fail (color != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if (color != ((void*)0)) _g_boolean_var_34 = 1; else _g_boolean_var_34
= 0; _g_boolean_var_34; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "color != NULL"); return
; } } while (0)
;
328
329 got_color = FALSE(0);
330 if (color_spec != NULL((void*)0))
331 {
332 if (gdk_rgba_parse (color, color_spec))
333 {
334 got_color = TRUE(!(0));
335 }
336 }
337
338 if (!got_color)
339 {
340 color->red = 1.0;
341 color->green = 1.0;
342 color->blue = 1.0;
343 color->alpha = 1.0;
344 }
345}
346
347guint32
348eel_rgb16_to_rgb (gushort r, gushort g, gushort b)
349{
350 guint32 result;
351
352 result = (0xff0000 | (r & 0xff00));
353 result <<= 8;
354 result |= ((g & 0xff00) | (b >> 8));
355
356 return result;
357}
358
359/**
360 * eel_gdk_rgba_to_rgb
361 * @color: A GdkRGBA style color.
362 * Returns: An rgb value.
363 *
364 * Converts from a GdkRGBA style color to a gdk_rgb one.
365 * Alpha gets set to fully opaque
366 */
367guint32
368eel_gdk_rgba_to_rgb (const GdkRGBA *color)
369{
370 return eel_rgb16_to_rgb ((guint) (color->red * 65535),
371 (guint) (color->green * 65535),
372 (guint) (color->blue * 65535));
373}
374
375/**
376 * eel_gdk_rgb_to_rgba
377 * @color: a gdk_rgb style value.
378 *
379 * Converts from a gdk_rgb value style to a GdkRGBA one.
380 * The gdk_rgb color alpha channel is ignored.
381 *
382 * Return value: A GdkRGBA structure version of the given RGB color.
383 */
384GdkRGBA
385eel_gdk_rgb_to_rgba (guint32 color)
386{
387 GdkRGBA result;
388
389 result.red = ((gdouble) ((color >> 16) & 0xFF)) / 0xFF;
390 result.green = ((gdouble) ((color >> 8) & 0xFF)) / 0xFF;
391 result.blue = ((gdouble) (color & 0xFF)) / 0xFF;
392 result.alpha = 1.0;
393
394 return result;
395}
396
397
398/**
399 * eel_gdk_rgb_to_color_spec
400 * @color: a gdk_rgb style value.
401 *
402 * Converts from a gdk_rgb value style to a string color spec.
403 * The gdk_rgb color alpha channel is ignored.
404 *
405 * Return value: a newly allocated color spec.
406 */
407char *
408eel_gdk_rgb_to_color_spec (const guint32 color)
409{
410 return g_strdup_printf ("#%06X", (guint) (color & 0xFFFFFF));
411}
412
413
414/**
415 * eel_gdk_rgba_is_dark:
416 *
417 * Return true if the given color is `dark'
418 */
419gboolean
420eel_gdk_rgba_is_dark (const GdkRGBA *color)
421{
422 int intensity;
423
424 intensity = (((guint) (color->red * 0xff) * 77)
425 + ((guint) (color->green * 0xff) * 150)
426 + ((guint) (color->blue * 0xff) * 28)) >> 8;
427
428 return intensity < 128;
429}
430
431EelGdkGeometryFlags
432eel_gdk_parse_geometry (const char *string, int *x_return, int *y_return,
433 guint *width_return, guint *height_return)
434{
435 int x11_flags;
436 EelGdkGeometryFlags gdk_flags;
437
438 g_return_val_if_fail (string != NULL, EEL_GDK_NO_VALUE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if (string != ((void*)0)) _g_boolean_var_35 = 1; else _g_boolean_var_35
= 0; _g_boolean_var_35; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "string != NULL"); return
(EEL_GDK_NO_VALUE); } } while (0)
;
439 g_return_val_if_fail (x_return != NULL, EEL_GDK_NO_VALUE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if (x_return != ((void*)0)) _g_boolean_var_36 = 1; else _g_boolean_var_36
= 0; _g_boolean_var_36; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "x_return != NULL"); return
(EEL_GDK_NO_VALUE); } } while (0)
;
440 g_return_val_if_fail (y_return != NULL, EEL_GDK_NO_VALUE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if (y_return != ((void*)0)) _g_boolean_var_37 = 1; else _g_boolean_var_37
= 0; _g_boolean_var_37; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "y_return != NULL"); return
(EEL_GDK_NO_VALUE); } } while (0)
;
441 g_return_val_if_fail (width_return != NULL, EEL_GDK_NO_VALUE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if (width_return != ((void*)0)) _g_boolean_var_38 = 1; else
_g_boolean_var_38 = 0; _g_boolean_var_38; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"width_return != NULL"); return (EEL_GDK_NO_VALUE); } } while
(0)
;
442 g_return_val_if_fail (height_return != NULL, EEL_GDK_NO_VALUE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if (height_return != ((void*)0)) _g_boolean_var_39 = 1; else
_g_boolean_var_39 = 0; _g_boolean_var_39; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"height_return != NULL"); return (EEL_GDK_NO_VALUE); } } while
(0)
;
443
444 x11_flags = XParseGeometry (string, x_return, y_return,
445 width_return, height_return);
446
447 gdk_flags = EEL_GDK_NO_VALUE;
448 if (x11_flags & XValue0x0001)
449 {
450 gdk_flags |= EEL_GDK_X_VALUE;
451 }
452 if (x11_flags & YValue0x0002)
453 {
454 gdk_flags |= EEL_GDK_Y_VALUE;
455 }
456 if (x11_flags & WidthValue0x0004)
457 {
458 gdk_flags |= EEL_GDK_WIDTH_VALUE;
459 }
460 if (x11_flags & HeightValue0x0008)
461 {
462 gdk_flags |= EEL_GDK_HEIGHT_VALUE;
463 }
464 if (x11_flags & XNegative0x0010)
465 {
466 gdk_flags |= EEL_GDK_X_NEGATIVE;
467 }
468 if (x11_flags & YNegative0x0020)
469 {
470 gdk_flags |= EEL_GDK_Y_NEGATIVE;
471 }
472
473 return gdk_flags;
474}
475
476#if ! defined (EEL_OMIT_SELF_CHECK)
477
478static char *
479eel_gdk_rgba_as_hex_string (GdkRGBA color)
480{
481 return g_strdup_printf ("%04X%04X%04X",
482 (guint) (color.red * 65535),
483 (guint) (color.green * 65535),
484 (guint) (color.blue * 65535));
485}
486
487static char *
488eel_self_check_parse (const char *color_spec)
489{
490 GdkRGBA color;
491
492 eel_gdk_rgba_parse_with_white_default (&color, color_spec);
493 return eel_gdk_rgba_as_hex_string (color);
494}
495
496static char *
497eel_self_check_gdk_rgb_to_color (guint32 color)
498{
499 GdkRGBA result;
500
501 result = eel_gdk_rgb_to_rgba (color);
502
503 return eel_gdk_rgba_as_hex_string (result);
504}
505
506void
507eel_self_check_gdk_extensions (void)
508{
509 /* eel_gradient_new */
510 EEL_CHECK_STRING_RESULT (eel_gradient_new ("", "", FALSE), "")do { eel_before_check ("eel_gradient_new (\"\", \"\", (0))", "eel-gdk-extensions.c"
, 510); eel_check_string_result (eel_gradient_new ("", "", (0
)), ""); } while (0)
;
1
Loop condition is false. Exiting loop
511 EEL_CHECK_STRING_RESULT (eel_gradient_new ("a", "b", FALSE), "a-b")do { eel_before_check ("eel_gradient_new (\"a\", \"b\", (0))"
, "eel-gdk-extensions.c", 511); eel_check_string_result (eel_gradient_new
("a", "b", (0)), "a-b"); } while (0)
;
2
Loop condition is false. Exiting loop
512 EEL_CHECK_STRING_RESULT (eel_gradient_new ("a", "b", TRUE), "a-b:h")do { eel_before_check ("eel_gradient_new (\"a\", \"b\", (!(0)))"
, "eel-gdk-extensions.c", 512); eel_check_string_result (eel_gradient_new
("a", "b", (!(0))), "a-b:h"); } while (0)
;
3
Loop condition is false. Exiting loop
513 EEL_CHECK_STRING_RESULT (eel_gradient_new ("a", "a", FALSE), "a")do { eel_before_check ("eel_gradient_new (\"a\", \"a\", (0))"
, "eel-gdk-extensions.c", 513); eel_check_string_result (eel_gradient_new
("a", "a", (0)), "a"); } while (0)
;
4
Loop condition is false. Exiting loop
514 EEL_CHECK_STRING_RESULT (eel_gradient_new ("a", "a", TRUE), "a")do { eel_before_check ("eel_gradient_new (\"a\", \"a\", (!(0)))"
, "eel-gdk-extensions.c", 514); eel_check_string_result (eel_gradient_new
("a", "a", (!(0))), "a"); } while (0)
;
5
Loop condition is false. Exiting loop
515
516 /* eel_gradient_is_gradient */
517 EEL_CHECK_BOOLEAN_RESULT (eel_gradient_is_gradient (""), FALSE)do { eel_before_check ("eel_gradient_is_gradient (\"\")", "eel-gdk-extensions.c"
, 517); eel_check_boolean_result (eel_gradient_is_gradient (""
), (0)); } while (0)
;
6
Loop condition is false. Exiting loop
518 EEL_CHECK_BOOLEAN_RESULT (eel_gradient_is_gradient ("-"), TRUE)do { eel_before_check ("eel_gradient_is_gradient (\"-\")", "eel-gdk-extensions.c"
, 518); eel_check_boolean_result (eel_gradient_is_gradient ("-"
), (!(0))); } while (0)
;
7
Loop condition is false. Exiting loop
519 EEL_CHECK_BOOLEAN_RESULT (eel_gradient_is_gradient ("a"), FALSE)do { eel_before_check ("eel_gradient_is_gradient (\"a\")", "eel-gdk-extensions.c"
, 519); eel_check_boolean_result (eel_gradient_is_gradient ("a"
), (0)); } while (0)
;
8
Loop condition is false. Exiting loop
520 EEL_CHECK_BOOLEAN_RESULT (eel_gradient_is_gradient ("a-b"), TRUE)do { eel_before_check ("eel_gradient_is_gradient (\"a-b\")", "eel-gdk-extensions.c"
, 520); eel_check_boolean_result (eel_gradient_is_gradient ("a-b"
), (!(0))); } while (0)
;
9
Loop condition is false. Exiting loop
521 EEL_CHECK_BOOLEAN_RESULT (eel_gradient_is_gradient ("a-b:h"), TRUE)do { eel_before_check ("eel_gradient_is_gradient (\"a-b:h\")"
, "eel-gdk-extensions.c", 521); eel_check_boolean_result (eel_gradient_is_gradient
("a-b:h"), (!(0))); } while (0)
;
10
Loop condition is false. Exiting loop
522
523 /* eel_gradient_get_start_color_spec */
524 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec (""), "")do { eel_before_check ("eel_gradient_get_start_color_spec (\"\")"
, "eel-gdk-extensions.c", 524); eel_check_string_result (eel_gradient_get_start_color_spec
(""), ""); } while (0)
;
11
Calling 'eel_gradient_get_start_color_spec'
525 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("-"), "")do { eel_before_check ("eel_gradient_get_start_color_spec (\"-\")"
, "eel-gdk-extensions.c", 525); eel_check_string_result (eel_gradient_get_start_color_spec
("-"), ""); } while (0)
;
526 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a"), "a")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a\")"
, "eel-gdk-extensions.c", 526); eel_check_string_result (eel_gradient_get_start_color_spec
("a"), "a"); } while (0)
;
527 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a-b"), "a")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a-b\")"
, "eel-gdk-extensions.c", 527); eel_check_string_result (eel_gradient_get_start_color_spec
("a-b"), "a"); } while (0)
;
528 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a-"), "a")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a-\")"
, "eel-gdk-extensions.c", 528); eel_check_string_result (eel_gradient_get_start_color_spec
("a-"), "a"); } while (0)
;
529 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("-b"), "")do { eel_before_check ("eel_gradient_get_start_color_spec (\"-b\")"
, "eel-gdk-extensions.c", 529); eel_check_string_result (eel_gradient_get_start_color_spec
("-b"), ""); } while (0)
;
530 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a:h"), "a")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a:h\")"
, "eel-gdk-extensions.c", 530); eel_check_string_result (eel_gradient_get_start_color_spec
("a:h"), "a"); } while (0)
;
531 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a:v"), "a")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a:v\")"
, "eel-gdk-extensions.c", 531); eel_check_string_result (eel_gradient_get_start_color_spec
("a:v"), "a"); } while (0)
;
532 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a:c"), "a:c")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a:c\")"
, "eel-gdk-extensions.c", 532); eel_check_string_result (eel_gradient_get_start_color_spec
("a:c"), "a:c"); } while (0)
;
533 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a:-b"), "a:")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a:-b\")"
, "eel-gdk-extensions.c", 533); eel_check_string_result (eel_gradient_get_start_color_spec
("a:-b"), "a:"); } while (0)
;
534 EEL_CHECK_STRING_RESULT (eel_gradient_get_start_color_spec ("a:-b:v"), "a:")do { eel_before_check ("eel_gradient_get_start_color_spec (\"a:-b:v\")"
, "eel-gdk-extensions.c", 534); eel_check_string_result (eel_gradient_get_start_color_spec
("a:-b:v"), "a:"); } while (0)
;
535
536 /* eel_gradient_get_end_color_spec */
537 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec (""), "")do { eel_before_check ("eel_gradient_get_end_color_spec (\"\")"
, "eel-gdk-extensions.c", 537); eel_check_string_result (eel_gradient_get_end_color_spec
(""), ""); } while (0)
;
538 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("-"), "")do { eel_before_check ("eel_gradient_get_end_color_spec (\"-\")"
, "eel-gdk-extensions.c", 538); eel_check_string_result (eel_gradient_get_end_color_spec
("-"), ""); } while (0)
;
539 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a"), "a")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a\")"
, "eel-gdk-extensions.c", 539); eel_check_string_result (eel_gradient_get_end_color_spec
("a"), "a"); } while (0)
;
540 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a-b"), "b")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a-b\")"
, "eel-gdk-extensions.c", 540); eel_check_string_result (eel_gradient_get_end_color_spec
("a-b"), "b"); } while (0)
;
541 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a-"), "")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a-\")"
, "eel-gdk-extensions.c", 541); eel_check_string_result (eel_gradient_get_end_color_spec
("a-"), ""); } while (0)
;
542 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("-b"), "b")do { eel_before_check ("eel_gradient_get_end_color_spec (\"-b\")"
, "eel-gdk-extensions.c", 542); eel_check_string_result (eel_gradient_get_end_color_spec
("-b"), "b"); } while (0)
;
543 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a:h"), "a")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a:h\")"
, "eel-gdk-extensions.c", 543); eel_check_string_result (eel_gradient_get_end_color_spec
("a:h"), "a"); } while (0)
;
544 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a:v"), "a")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a:v\")"
, "eel-gdk-extensions.c", 544); eel_check_string_result (eel_gradient_get_end_color_spec
("a:v"), "a"); } while (0)
;
545 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a:c"), "a:c")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a:c\")"
, "eel-gdk-extensions.c", 545); eel_check_string_result (eel_gradient_get_end_color_spec
("a:c"), "a:c"); } while (0)
;
546 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a:-b"), "b")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a:-b\")"
, "eel-gdk-extensions.c", 546); eel_check_string_result (eel_gradient_get_end_color_spec
("a:-b"), "b"); } while (0)
;
547 EEL_CHECK_STRING_RESULT (eel_gradient_get_end_color_spec ("a:-b:v"), "b")do { eel_before_check ("eel_gradient_get_end_color_spec (\"a:-b:v\")"
, "eel-gdk-extensions.c", 547); eel_check_string_result (eel_gradient_get_end_color_spec
("a:-b:v"), "b"); } while (0)
;
548
549 /* eel_gradient_set_left_color_spec */
550 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("", ""), "")do { eel_before_check ("eel_gradient_set_left_color_spec (\"\", \"\")"
, "eel-gdk-extensions.c", 550); eel_check_string_result (eel_gradient_set_left_color_spec
("", ""), ""); } while (0)
;
551 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("", "a"), "a")do { eel_before_check ("eel_gradient_set_left_color_spec (\"\", \"a\")"
, "eel-gdk-extensions.c", 551); eel_check_string_result (eel_gradient_set_left_color_spec
("", "a"), "a"); } while (0)
;
552 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("a", ""), "a")do { eel_before_check ("eel_gradient_set_left_color_spec (\"a\", \"\")"
, "eel-gdk-extensions.c", 552); eel_check_string_result (eel_gradient_set_left_color_spec
("a", ""), "a"); } while (0)
;
553 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("a", "a"), "a")do { eel_before_check ("eel_gradient_set_left_color_spec (\"a\", \"a\")"
, "eel-gdk-extensions.c", 553); eel_check_string_result (eel_gradient_set_left_color_spec
("a", "a"), "a"); } while (0)
;
554 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("a", "b"), "b-a:h")do { eel_before_check ("eel_gradient_set_left_color_spec (\"a\", \"b\")"
, "eel-gdk-extensions.c", 554); eel_check_string_result (eel_gradient_set_left_color_spec
("a", "b"), "b-a:h"); } while (0)
;
555 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("a-c:v", "b"), "b-c:h")do { eel_before_check ("eel_gradient_set_left_color_spec (\"a-c:v\", \"b\")"
, "eel-gdk-extensions.c", 555); eel_check_string_result (eel_gradient_set_left_color_spec
("a-c:v", "b"), "b-c:h"); } while (0)
;
556 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("a-c:v", "c"), "c")do { eel_before_check ("eel_gradient_set_left_color_spec (\"a-c:v\", \"c\")"
, "eel-gdk-extensions.c", 556); eel_check_string_result (eel_gradient_set_left_color_spec
("a-c:v", "c"), "c"); } while (0)
;
557 EEL_CHECK_STRING_RESULT (eel_gradient_set_left_color_spec ("a:-b:v", "d"), "d-b:h")do { eel_before_check ("eel_gradient_set_left_color_spec (\"a:-b:v\", \"d\")"
, "eel-gdk-extensions.c", 557); eel_check_string_result (eel_gradient_set_left_color_spec
("a:-b:v", "d"), "d-b:h"); } while (0)
;
558
559 /* eel_gradient_set_top_color_spec */
560 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("", ""), "")do { eel_before_check ("eel_gradient_set_top_color_spec (\"\", \"\")"
, "eel-gdk-extensions.c", 560); eel_check_string_result (eel_gradient_set_top_color_spec
("", ""), ""); } while (0)
;
561 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("", "a"), "a")do { eel_before_check ("eel_gradient_set_top_color_spec (\"\", \"a\")"
, "eel-gdk-extensions.c", 561); eel_check_string_result (eel_gradient_set_top_color_spec
("", "a"), "a"); } while (0)
;
562 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("a", ""), "a")do { eel_before_check ("eel_gradient_set_top_color_spec (\"a\", \"\")"
, "eel-gdk-extensions.c", 562); eel_check_string_result (eel_gradient_set_top_color_spec
("a", ""), "a"); } while (0)
;
563 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("a", "a"), "a")do { eel_before_check ("eel_gradient_set_top_color_spec (\"a\", \"a\")"
, "eel-gdk-extensions.c", 563); eel_check_string_result (eel_gradient_set_top_color_spec
("a", "a"), "a"); } while (0)
;
564 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("a", "b"), "b-a")do { eel_before_check ("eel_gradient_set_top_color_spec (\"a\", \"b\")"
, "eel-gdk-extensions.c", 564); eel_check_string_result (eel_gradient_set_top_color_spec
("a", "b"), "b-a"); } while (0)
;
565 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("a-c:v", "b"), "b-c")do { eel_before_check ("eel_gradient_set_top_color_spec (\"a-c:v\", \"b\")"
, "eel-gdk-extensions.c", 565); eel_check_string_result (eel_gradient_set_top_color_spec
("a-c:v", "b"), "b-c"); } while (0)
;
566 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("a-c:v", "c"), "c")do { eel_before_check ("eel_gradient_set_top_color_spec (\"a-c:v\", \"c\")"
, "eel-gdk-extensions.c", 566); eel_check_string_result (eel_gradient_set_top_color_spec
("a-c:v", "c"), "c"); } while (0)
;
567 EEL_CHECK_STRING_RESULT (eel_gradient_set_top_color_spec ("a:-b:h", "d"), "d-b")do { eel_before_check ("eel_gradient_set_top_color_spec (\"a:-b:h\", \"d\")"
, "eel-gdk-extensions.c", 567); eel_check_string_result (eel_gradient_set_top_color_spec
("a:-b:h", "d"), "d-b"); } while (0)
;
568
569 /* eel_gradient_set_right_color_spec */
570 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("", ""), "")do { eel_before_check ("eel_gradient_set_right_color_spec (\"\", \"\")"
, "eel-gdk-extensions.c", 570); eel_check_string_result (eel_gradient_set_right_color_spec
("", ""), ""); } while (0)
;
571 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("", "a"), "a")do { eel_before_check ("eel_gradient_set_right_color_spec (\"\", \"a\")"
, "eel-gdk-extensions.c", 571); eel_check_string_result (eel_gradient_set_right_color_spec
("", "a"), "a"); } while (0)
;
572 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("a", ""), "a")do { eel_before_check ("eel_gradient_set_right_color_spec (\"a\", \"\")"
, "eel-gdk-extensions.c", 572); eel_check_string_result (eel_gradient_set_right_color_spec
("a", ""), "a"); } while (0)
;
573 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("a", "a"), "a")do { eel_before_check ("eel_gradient_set_right_color_spec (\"a\", \"a\")"
, "eel-gdk-extensions.c", 573); eel_check_string_result (eel_gradient_set_right_color_spec
("a", "a"), "a"); } while (0)
;
574 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("a", "b"), "a-b:h")do { eel_before_check ("eel_gradient_set_right_color_spec (\"a\", \"b\")"
, "eel-gdk-extensions.c", 574); eel_check_string_result (eel_gradient_set_right_color_spec
("a", "b"), "a-b:h"); } while (0)
;
575 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("a-c:v", "b"), "a-b:h")do { eel_before_check ("eel_gradient_set_right_color_spec (\"a-c:v\", \"b\")"
, "eel-gdk-extensions.c", 575); eel_check_string_result (eel_gradient_set_right_color_spec
("a-c:v", "b"), "a-b:h"); } while (0)
;
576 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("a-c:v", "c"), "a-c:h")do { eel_before_check ("eel_gradient_set_right_color_spec (\"a-c:v\", \"c\")"
, "eel-gdk-extensions.c", 576); eel_check_string_result (eel_gradient_set_right_color_spec
("a-c:v", "c"), "a-c:h"); } while (0)
;
577 EEL_CHECK_STRING_RESULT (eel_gradient_set_right_color_spec ("a:-b:v", "d"), "a:-d:h")do { eel_before_check ("eel_gradient_set_right_color_spec (\"a:-b:v\", \"d\")"
, "eel-gdk-extensions.c", 577); eel_check_string_result (eel_gradient_set_right_color_spec
("a:-b:v", "d"), "a:-d:h"); } while (0)
;
578
579 /* eel_gradient_set_bottom_color_spec */
580 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("", ""), "")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"\", \"\")"
, "eel-gdk-extensions.c", 580); eel_check_string_result (eel_gradient_set_bottom_color_spec
("", ""), ""); } while (0)
;
581 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("", "a"), "a")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"\", \"a\")"
, "eel-gdk-extensions.c", 581); eel_check_string_result (eel_gradient_set_bottom_color_spec
("", "a"), "a"); } while (0)
;
582 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("a", ""), "a")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"a\", \"\")"
, "eel-gdk-extensions.c", 582); eel_check_string_result (eel_gradient_set_bottom_color_spec
("a", ""), "a"); } while (0)
;
583 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("a", "a"), "a")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"a\", \"a\")"
, "eel-gdk-extensions.c", 583); eel_check_string_result (eel_gradient_set_bottom_color_spec
("a", "a"), "a"); } while (0)
;
584 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("a", "b"), "a-b")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"a\", \"b\")"
, "eel-gdk-extensions.c", 584); eel_check_string_result (eel_gradient_set_bottom_color_spec
("a", "b"), "a-b"); } while (0)
;
585 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("a-c:v", "b"), "a-b")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"a-c:v\", \"b\")"
, "eel-gdk-extensions.c", 585); eel_check_string_result (eel_gradient_set_bottom_color_spec
("a-c:v", "b"), "a-b"); } while (0)
;
586 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("a-c:v", "c"), "a-c")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"a-c:v\", \"c\")"
, "eel-gdk-extensions.c", 586); eel_check_string_result (eel_gradient_set_bottom_color_spec
("a-c:v", "c"), "a-c"); } while (0)
;
587 EEL_CHECK_STRING_RESULT (eel_gradient_set_bottom_color_spec ("a:-b:h", "d"), "a:-d")do { eel_before_check ("eel_gradient_set_bottom_color_spec (\"a:-b:h\", \"d\")"
, "eel-gdk-extensions.c", 587); eel_check_string_result (eel_gradient_set_bottom_color_spec
("a:-b:h", "d"), "a:-d"); } while (0)
;
588
589 /* eel_gdk_rgba_parse_with_white_default */
590 EEL_CHECK_STRING_RESULT (eel_self_check_parse (""), "FFFFFFFFFFFF")do { eel_before_check ("eel_self_check_parse (\"\")", "eel-gdk-extensions.c"
, 590); eel_check_string_result (eel_self_check_parse (""), "FFFFFFFFFFFF"
); } while (0)
;
591 EEL_CHECK_STRING_RESULT (eel_self_check_parse ("a"), "FFFFFFFFFFFF")do { eel_before_check ("eel_self_check_parse (\"a\")", "eel-gdk-extensions.c"
, 591); eel_check_string_result (eel_self_check_parse ("a"), "FFFFFFFFFFFF"
); } while (0)
;
592 EEL_CHECK_STRING_RESULT (eel_self_check_parse ("white"), "FFFFFFFFFFFF")do { eel_before_check ("eel_self_check_parse (\"white\")", "eel-gdk-extensions.c"
, 592); eel_check_string_result (eel_self_check_parse ("white"
), "FFFFFFFFFFFF"); } while (0)
;
593 EEL_CHECK_STRING_RESULT (eel_self_check_parse ("black"), "000000000000")do { eel_before_check ("eel_self_check_parse (\"black\")", "eel-gdk-extensions.c"
, 593); eel_check_string_result (eel_self_check_parse ("black"
), "000000000000"); } while (0)
;
594 EEL_CHECK_STRING_RESULT (eel_self_check_parse ("red"), "FFFF00000000")do { eel_before_check ("eel_self_check_parse (\"red\")", "eel-gdk-extensions.c"
, 594); eel_check_string_result (eel_self_check_parse ("red")
, "FFFF00000000"); } while (0)
;
595 EEL_CHECK_STRING_RESULT (eel_self_check_parse ("#012345"), "010123234545")do { eel_before_check ("eel_self_check_parse (\"#012345\")", "eel-gdk-extensions.c"
, 595); eel_check_string_result (eel_self_check_parse ("#012345"
), "010123234545"); } while (0)
;
596 /* EEL_CHECK_STRING_RESULT (eel_self_check_parse ("rgb:0123/4567/89AB"), "#014589"); */
597
598 /* eel_gdk_rgb_to_color */
599 EEL_CHECK_STRING_RESULT (eel_self_check_gdk_rgb_to_color (EEL_RGB_COLOR_RED), "FFFF00000000")do { eel_before_check ("eel_self_check_gdk_rgb_to_color (0xFF0000)"
, "eel-gdk-extensions.c", 599); eel_check_string_result (eel_self_check_gdk_rgb_to_color
(0xFF0000), "FFFF00000000"); } while (0)
;
600 EEL_CHECK_STRING_RESULT (eel_self_check_gdk_rgb_to_color (EEL_RGB_COLOR_BLACK), "000000000000")do { eel_before_check ("eel_self_check_gdk_rgb_to_color (0x000000)"
, "eel-gdk-extensions.c", 600); eel_check_string_result (eel_self_check_gdk_rgb_to_color
(0x000000), "000000000000"); } while (0)
;
601 EEL_CHECK_STRING_RESULT (eel_self_check_gdk_rgb_to_color (EEL_RGB_COLOR_WHITE), "FFFFFFFFFFFF")do { eel_before_check ("eel_self_check_gdk_rgb_to_color (0xFFFFFF)"
, "eel-gdk-extensions.c", 601); eel_check_string_result (eel_self_check_gdk_rgb_to_color
(0xFFFFFF), "FFFFFFFFFFFF"); } while (0)
;
602 EEL_CHECK_STRING_RESULT (eel_self_check_gdk_rgb_to_color (EEL_RGB_COLOR_PACK (0x01, 0x23, 0x45)), "010123234545")do { eel_before_check ("eel_self_check_gdk_rgb_to_color (( (((guint32)0xFF) << 24) | (((guint32)(0x01)) << 16) | (((guint32)(0x23)) << 8) | (((guint32)(0x45)) << 0) ))"
, "eel-gdk-extensions.c", 602); eel_check_string_result (eel_self_check_gdk_rgb_to_color
(( (((guint32)0xFF) << 24) | (((guint32)(0x01)) <<
16) | (((guint32)(0x23)) << 8) | (((guint32)(0x45)) <<
0) )), "010123234545"); } while (0)
;
603
604 /* EEL_RGBA_COLOR_PACK */
605 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0xFF, 0x00, 0x00, 00), EEL_RGB_COLOR_RED)do { eel_before_check ("( (((guint32)00) << 24) | (((guint32)0xFF) << 16) | (((guint32)0x00) << 8) | (((guint32)0x00) << 0) )"
, "eel-gdk-extensions.c", 605); eel_check_integer_result (( (
((guint32)00) << 24) | (((guint32)0xFF) << 16) | (
((guint32)0x00) << 8) | (((guint32)0x00) << 0) ),
0xFF0000); } while (0)
;
606 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0x00, 0xFF, 0x00, 00), EEL_RGB_COLOR_GREEN)do { eel_before_check ("( (((guint32)00) << 24) | (((guint32)0x00) << 16) | (((guint32)0xFF) << 8) | (((guint32)0x00) << 0) )"
, "eel-gdk-extensions.c", 606); eel_check_integer_result (( (
((guint32)00) << 24) | (((guint32)0x00) << 16) | (
((guint32)0xFF) << 8) | (((guint32)0x00) << 0) ),
0x00FF00); } while (0)
;
607 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0x00, 0x00, 0xFF, 00), EEL_RGB_COLOR_BLUE)do { eel_before_check ("( (((guint32)00) << 24) | (((guint32)0x00) << 16) | (((guint32)0x00) << 8) | (((guint32)0xFF) << 0) )"
, "eel-gdk-extensions.c", 607); eel_check_integer_result (( (
((guint32)00) << 24) | (((guint32)0x00) << 16) | (
((guint32)0x00) << 8) | (((guint32)0xFF) << 0) ),
0x0000FF); } while (0)
;
608 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0xFF, 0xFF, 0xFF, 00), EEL_RGB_COLOR_WHITE)do { eel_before_check ("( (((guint32)00) << 24) | (((guint32)0xFF) << 16) | (((guint32)0xFF) << 8) | (((guint32)0xFF) << 0) )"
, "eel-gdk-extensions.c", 608); eel_check_integer_result (( (
((guint32)00) << 24) | (((guint32)0xFF) << 16) | (
((guint32)0xFF) << 8) | (((guint32)0xFF) << 0) ),
0xFFFFFF); } while (0)
;
609 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0x00, 0x00, 0x00, 00), EEL_RGB_COLOR_BLACK)do { eel_before_check ("( (((guint32)00) << 24) | (((guint32)0x00) << 16) | (((guint32)0x00) << 8) | (((guint32)0x00) << 0) )"
, "eel-gdk-extensions.c", 609); eel_check_integer_result (( (
((guint32)00) << 24) | (((guint32)0x00) << 16) | (
((guint32)0x00) << 8) | (((guint32)0x00) << 0) ),
0x000000); } while (0)
;
610
611 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0xFF, 0x00, 0x00, 0xFF), EEL_RGBA_COLOR_OPAQUE_RED)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)0xFF) << 16) | (((guint32)0x00) << 8) | (((guint32)0x00) << 0) )"
, "eel-gdk-extensions.c", 611); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)0xFF) << 16) |
(((guint32)0x00) << 8) | (((guint32)0x00) << 0) )
, 0xFFFF0000); } while (0)
;
612 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0x00, 0xFF, 0x00, 0xFF), EEL_RGBA_COLOR_OPAQUE_GREEN)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)0x00) << 16) | (((guint32)0xFF) << 8) | (((guint32)0x00) << 0) )"
, "eel-gdk-extensions.c", 612); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)0x00) << 16) |
(((guint32)0xFF) << 8) | (((guint32)0x00) << 0) )
, 0xFF00FF00); } while (0)
;
613 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0x00, 0x00, 0xFF, 0xFF), EEL_RGBA_COLOR_OPAQUE_BLUE)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)0x00) << 16) | (((guint32)0x00) << 8) | (((guint32)0xFF) << 0) )"
, "eel-gdk-extensions.c", 613); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)0x00) << 16) |
(((guint32)0x00) << 8) | (((guint32)0xFF) << 0) )
, 0xFF0000FF); } while (0)
;
614 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0xFF, 0xFF, 0xFF, 0xFF), EEL_RGBA_COLOR_OPAQUE_WHITE)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)0xFF) << 16) | (((guint32)0xFF) << 8) | (((guint32)0xFF) << 0) )"
, "eel-gdk-extensions.c", 614); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)0xFF) << 16) |
(((guint32)0xFF) << 8) | (((guint32)0xFF) << 0) )
, 0xFFFFFFFF); } while (0)
;
615 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_PACK (0x00, 0x00, 0x00, 0xFF), EEL_RGBA_COLOR_OPAQUE_BLACK)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)0x00) << 16) | (((guint32)0x00) << 8) | (((guint32)0x00) << 0) )"
, "eel-gdk-extensions.c", 615); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)0x00) << 16) |
(((guint32)0x00) << 8) | (((guint32)0x00) << 0) )
, 0xFF000000); } while (0)
;
616
617 /* EEL_RGB_COLOR_PACK */
618 EEL_CHECK_INTEGER_RESULT (EEL_RGB_COLOR_PACK (0xFF, 0x00, 0x00), EEL_RGBA_COLOR_OPAQUE_RED)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)(0xFF)) << 16) | (((guint32)(0x00)) << 8) | (((guint32)(0x00)) << 0) )"
, "eel-gdk-extensions.c", 618); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)(0xFF)) << 16
) | (((guint32)(0x00)) << 8) | (((guint32)(0x00)) <<
0) ), 0xFFFF0000); } while (0)
;
619 EEL_CHECK_INTEGER_RESULT (EEL_RGB_COLOR_PACK (0x00, 0xFF, 0x00), EEL_RGBA_COLOR_OPAQUE_GREEN)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)(0x00)) << 16) | (((guint32)(0xFF)) << 8) | (((guint32)(0x00)) << 0) )"
, "eel-gdk-extensions.c", 619); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)(0x00)) << 16
) | (((guint32)(0xFF)) << 8) | (((guint32)(0x00)) <<
0) ), 0xFF00FF00); } while (0)
;
620 EEL_CHECK_INTEGER_RESULT (EEL_RGB_COLOR_PACK (0x00, 0x00, 0xFF), EEL_RGBA_COLOR_OPAQUE_BLUE)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)(0x00)) << 16) | (((guint32)(0x00)) << 8) | (((guint32)(0xFF)) << 0) )"
, "eel-gdk-extensions.c", 620); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)(0x00)) << 16
) | (((guint32)(0x00)) << 8) | (((guint32)(0xFF)) <<
0) ), 0xFF0000FF); } while (0)
;
621 EEL_CHECK_INTEGER_RESULT (EEL_RGB_COLOR_PACK (0xFF, 0xFF, 0xFF), EEL_RGBA_COLOR_OPAQUE_WHITE)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)(0xFF)) << 16) | (((guint32)(0xFF)) << 8) | (((guint32)(0xFF)) << 0) )"
, "eel-gdk-extensions.c", 621); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)(0xFF)) << 16
) | (((guint32)(0xFF)) << 8) | (((guint32)(0xFF)) <<
0) ), 0xFFFFFFFF); } while (0)
;
622 EEL_CHECK_INTEGER_RESULT (EEL_RGB_COLOR_PACK (0x00, 0x00, 0x00), EEL_RGBA_COLOR_OPAQUE_BLACK)do { eel_before_check ("( (((guint32)0xFF) << 24) | (((guint32)(0x00)) << 16) | (((guint32)(0x00)) << 8) | (((guint32)(0x00)) << 0) )"
, "eel-gdk-extensions.c", 622); eel_check_integer_result (( (
((guint32)0xFF) << 24) | (((guint32)(0x00)) << 16
) | (((guint32)(0x00)) << 8) | (((guint32)(0x00)) <<
0) ), 0xFF000000); } while (0)
;
623
624 /* EEL_RGBA_COLOR_GET_R */
625 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGBA_COLOR_OPAQUE_RED), 0xFF)do { eel_before_check ("(((0xFFFF0000) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 625); eel_check_integer_result ((((
0xFFFF0000) >> 16) & 0xff), 0xFF); } while (0)
;
626 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGBA_COLOR_OPAQUE_GREEN), 0x00)do { eel_before_check ("(((0xFF00FF00) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 626); eel_check_integer_result ((((
0xFF00FF00) >> 16) & 0xff), 0x00); } while (0)
;
627 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGBA_COLOR_OPAQUE_BLUE), 0x00)do { eel_before_check ("(((0xFF0000FF) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 627); eel_check_integer_result ((((
0xFF0000FF) >> 16) & 0xff), 0x00); } while (0)
;
628 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGBA_COLOR_OPAQUE_WHITE), 0xFF)do { eel_before_check ("(((0xFFFFFFFF) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 628); eel_check_integer_result ((((
0xFFFFFFFF) >> 16) & 0xff), 0xFF); } while (0)
;
629 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGBA_COLOR_OPAQUE_BLACK), 0x00)do { eel_before_check ("(((0xFF000000) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 629); eel_check_integer_result ((((
0xFF000000) >> 16) & 0xff), 0x00); } while (0)
;
630 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGB_COLOR_RED), 0xFF)do { eel_before_check ("(((0xFF0000) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 630); eel_check_integer_result ((((
0xFF0000) >> 16) & 0xff), 0xFF); } while (0)
;
631 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGB_COLOR_GREEN), 0x00)do { eel_before_check ("(((0x00FF00) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 631); eel_check_integer_result ((((
0x00FF00) >> 16) & 0xff), 0x00); } while (0)
;
632 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGB_COLOR_BLUE), 0x00)do { eel_before_check ("(((0x0000FF) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 632); eel_check_integer_result ((((
0x0000FF) >> 16) & 0xff), 0x00); } while (0)
;
633 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGB_COLOR_WHITE), 0xFF)do { eel_before_check ("(((0xFFFFFF) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 633); eel_check_integer_result ((((
0xFFFFFF) >> 16) & 0xff), 0xFF); } while (0)
;
634 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_R (EEL_RGB_COLOR_BLACK), 0x00)do { eel_before_check ("(((0x000000) >> 16) & 0xff)"
, "eel-gdk-extensions.c", 634); eel_check_integer_result ((((
0x000000) >> 16) & 0xff), 0x00); } while (0)
;
635
636 /* EEL_RGBA_COLOR_GET_G */
637 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGBA_COLOR_OPAQUE_RED), 0x00)do { eel_before_check ("(((0xFFFF0000) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 637); eel_check_integer_result ((((
0xFFFF0000) >> 8) & 0xff), 0x00); } while (0)
;
638 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGBA_COLOR_OPAQUE_GREEN), 0xFF)do { eel_before_check ("(((0xFF00FF00) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 638); eel_check_integer_result ((((
0xFF00FF00) >> 8) & 0xff), 0xFF); } while (0)
;
639 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGBA_COLOR_OPAQUE_BLUE), 0x00)do { eel_before_check ("(((0xFF0000FF) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 639); eel_check_integer_result ((((
0xFF0000FF) >> 8) & 0xff), 0x00); } while (0)
;
640 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGBA_COLOR_OPAQUE_WHITE), 0xFF)do { eel_before_check ("(((0xFFFFFFFF) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 640); eel_check_integer_result ((((
0xFFFFFFFF) >> 8) & 0xff), 0xFF); } while (0)
;
641 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGBA_COLOR_OPAQUE_BLACK), 0x00)do { eel_before_check ("(((0xFF000000) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 641); eel_check_integer_result ((((
0xFF000000) >> 8) & 0xff), 0x00); } while (0)
;
642 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGB_COLOR_RED), 0x00)do { eel_before_check ("(((0xFF0000) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 642); eel_check_integer_result ((((
0xFF0000) >> 8) & 0xff), 0x00); } while (0)
;
643 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGB_COLOR_GREEN), 0xFF)do { eel_before_check ("(((0x00FF00) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 643); eel_check_integer_result ((((
0x00FF00) >> 8) & 0xff), 0xFF); } while (0)
;
644 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGB_COLOR_BLUE), 0x00)do { eel_before_check ("(((0x0000FF) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 644); eel_check_integer_result ((((
0x0000FF) >> 8) & 0xff), 0x00); } while (0)
;
645 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGB_COLOR_WHITE), 0xFF)do { eel_before_check ("(((0xFFFFFF) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 645); eel_check_integer_result ((((
0xFFFFFF) >> 8) & 0xff), 0xFF); } while (0)
;
646 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_G (EEL_RGB_COLOR_BLACK), 0x00)do { eel_before_check ("(((0x000000) >> 8) & 0xff)"
, "eel-gdk-extensions.c", 646); eel_check_integer_result ((((
0x000000) >> 8) & 0xff), 0x00); } while (0)
;
647
648 /* EEL_RGBA_COLOR_GET_B */
649 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGBA_COLOR_OPAQUE_RED), 0x00)do { eel_before_check ("(((0xFFFF0000) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 649); eel_check_integer_result ((((
0xFFFF0000) >> 0) & 0xff), 0x00); } while (0)
;
650 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGBA_COLOR_OPAQUE_GREEN), 0x00)do { eel_before_check ("(((0xFF00FF00) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 650); eel_check_integer_result ((((
0xFF00FF00) >> 0) & 0xff), 0x00); } while (0)
;
651 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGBA_COLOR_OPAQUE_BLUE), 0xFF)do { eel_before_check ("(((0xFF0000FF) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 651); eel_check_integer_result ((((
0xFF0000FF) >> 0) & 0xff), 0xFF); } while (0)
;
652 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGBA_COLOR_OPAQUE_WHITE), 0xFF)do { eel_before_check ("(((0xFFFFFFFF) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 652); eel_check_integer_result ((((
0xFFFFFFFF) >> 0) & 0xff), 0xFF); } while (0)
;
653 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGBA_COLOR_OPAQUE_BLACK), 0x00)do { eel_before_check ("(((0xFF000000) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 653); eel_check_integer_result ((((
0xFF000000) >> 0) & 0xff), 0x00); } while (0)
;
654 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGB_COLOR_RED), 0x00)do { eel_before_check ("(((0xFF0000) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 654); eel_check_integer_result ((((
0xFF0000) >> 0) & 0xff), 0x00); } while (0)
;
655 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGB_COLOR_GREEN), 0x00)do { eel_before_check ("(((0x00FF00) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 655); eel_check_integer_result ((((
0x00FF00) >> 0) & 0xff), 0x00); } while (0)
;
656 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGB_COLOR_BLUE), 0xFF)do { eel_before_check ("(((0x0000FF) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 656); eel_check_integer_result ((((
0x0000FF) >> 0) & 0xff), 0xFF); } while (0)
;
657 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGB_COLOR_WHITE), 0xFF)do { eel_before_check ("(((0xFFFFFF) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 657); eel_check_integer_result ((((
0xFFFFFF) >> 0) & 0xff), 0xFF); } while (0)
;
658 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_B (EEL_RGB_COLOR_BLACK), 0x00)do { eel_before_check ("(((0x000000) >> 0) & 0xff)"
, "eel-gdk-extensions.c", 658); eel_check_integer_result ((((
0x000000) >> 0) & 0xff), 0x00); } while (0)
;
659
660 /* EEL_RGBA_COLOR_GET_A */
661 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGBA_COLOR_OPAQUE_RED), 0xFF)do { eel_before_check ("(((0xFFFF0000) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 661); eel_check_integer_result ((((
0xFFFF0000) >> 24) & 0xff), 0xFF); } while (0)
;
662 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGBA_COLOR_OPAQUE_GREEN), 0xFF)do { eel_before_check ("(((0xFF00FF00) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 662); eel_check_integer_result ((((
0xFF00FF00) >> 24) & 0xff), 0xFF); } while (0)
;
663 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGBA_COLOR_OPAQUE_BLUE), 0xFF)do { eel_before_check ("(((0xFF0000FF) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 663); eel_check_integer_result ((((
0xFF0000FF) >> 24) & 0xff), 0xFF); } while (0)
;
664 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGBA_COLOR_OPAQUE_WHITE), 0xFF)do { eel_before_check ("(((0xFFFFFFFF) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 664); eel_check_integer_result ((((
0xFFFFFFFF) >> 24) & 0xff), 0xFF); } while (0)
;
665 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGBA_COLOR_OPAQUE_BLACK), 0xFF)do { eel_before_check ("(((0xFF000000) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 665); eel_check_integer_result ((((
0xFF000000) >> 24) & 0xff), 0xFF); } while (0)
;
666 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGB_COLOR_RED), 0x00)do { eel_before_check ("(((0xFF0000) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 666); eel_check_integer_result ((((
0xFF0000) >> 24) & 0xff), 0x00); } while (0)
;
667 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGB_COLOR_GREEN), 0x00)do { eel_before_check ("(((0x00FF00) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 667); eel_check_integer_result ((((
0x00FF00) >> 24) & 0xff), 0x00); } while (0)
;
668 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGB_COLOR_BLUE), 0x00)do { eel_before_check ("(((0x0000FF) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 668); eel_check_integer_result ((((
0x0000FF) >> 24) & 0xff), 0x00); } while (0)
;
669 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGB_COLOR_WHITE), 0x00)do { eel_before_check ("(((0xFFFFFF) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 669); eel_check_integer_result ((((
0xFFFFFF) >> 24) & 0xff), 0x00); } while (0)
;
670 EEL_CHECK_INTEGER_RESULT (EEL_RGBA_COLOR_GET_A (EEL_RGB_COLOR_BLACK), 0x00)do { eel_before_check ("(((0x000000) >> 24) & 0xff)"
, "eel-gdk-extensions.c", 670); eel_check_integer_result ((((
0x000000) >> 24) & 0xff), 0x00); } while (0)
;
671
672}
673
674#endif /* ! EEL_OMIT_SELF_CHECK */
diff --git a/2024-07-29-023715-6438-1/report-39a95b.html b/2024-07-29-023715-6438-1/report-39a95b.html new file mode 100644 index 000000000..1969154cf --- /dev/null +++ b/2024-07-29-023715-6438-1/report-39a95b.html @@ -0,0 +1,7496 @@ + + + +caja-file-operations.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file-operations.c
Warning:line 961, column 11
Cast a region whose size is not a multiple of the destination type size
+ +

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 caja-file-operations.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file-operations.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* caja-file-operations.c - Caja file operations.
4
5 Copyright (C) 1999, 2000 Free Software Foundation
6 Copyright (C) 2000, 2001 Eazel, Inc.
7 Copyright (C) 2007 Red Hat, Inc.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (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 GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public
20 License along with this program; if not, write to the
21 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24 Authors: Alexander Larsson <alexl@redhat.com>
25 Ettore Perazzoli <ettore@gnu.org>
26 Pavel Cisler <pavel@eazel.com>
27 */
28
29#include <config.h>
30#include <string.h>
31#include <stdio.h>
32#include <stdarg.h>
33#include <locale.h>
34#include <math.h>
35#include <unistd.h>
36#include <sys/types.h>
37#include <stdlib.h>
38#include <glib/gi18n.h>
39#include <glib/gstdio.h>
40#include <gdk/gdk.h>
41#include <gdk/gdkx.h>
42#include <gtk/gtk.h>
43#include <gio/gio.h>
44#include <glib.h>
45#include <libnotify/notify.h>
46
47#include <eel/eel-glib-extensions.h>
48#include <eel/eel-gtk-extensions.h>
49#include <eel/eel-stock-dialogs.h>
50#include <eel/eel-vfs-extensions.h>
51
52#include "caja-file-operations.h"
53#include "caja-debug-log.h"
54#include "caja-file-changes-queue.h"
55#include "caja-lib-self-check-functions.h"
56#include "caja-progress-info.h"
57#include "caja-file-changes-queue.h"
58#include "caja-file-private.h"
59#include "caja-desktop-icon-file.h"
60#include "caja-desktop-link-monitor.h"
61#include "caja-global-preferences.h"
62#include "caja-link.h"
63#include "caja-autorun.h"
64#include "caja-trash-monitor.h"
65#include "caja-file-utilities.h"
66#include "caja-file-conflict-dialog.h"
67#include "caja-undostack-manager.h"
68#include "caja-metadata.h"
69
70/* TODO: TESTING!!! */
71
72typedef struct {
73 GIOSchedulerJob *io_job;
74 GTimer *time;
75 GtkWindow *parent_window;
76 int screen_num;
77 int inhibit_cookie;
78 CajaProgressInfo *progress;
79 GCancellable *cancellable;
80 GHashTable *skip_files;
81 GHashTable *skip_readdir_error;
82 gboolean skip_all_error;
83 gboolean skip_all_conflict;
84 gboolean merge_all;
85 gboolean replace_all;
86 gboolean delete_all;
87 CajaUndoStackActionData* undo_redo_data;
88} CommonJob;
89
90typedef struct {
91 CommonJob common;
92 gboolean is_move;
93 GList *files;
94 GFile *destination;
95 GFile *desktop_location;
96 GdkPoint *icon_positions;
97 int n_icon_positions;
98 GHashTable *debuting_files;
99 CajaCopyCallback done_callback;
100 gpointer done_callback_data;
101} CopyMoveJob;
102
103typedef struct {
104 CommonJob common;
105 GList *files;
106 gboolean try_trash;
107 gboolean user_cancel;
108 CajaDeleteCallback done_callback;
109 gpointer done_callback_data;
110} DeleteJob;
111
112typedef struct {
113 CommonJob common;
114 GFile *dest_dir;
115 char *filename;
116 gboolean make_dir;
117 GFile *src;
118 char *src_data;
119 int length;
120 GdkPoint position;
121 gboolean has_position;
122 GFile *created_file;
123 CajaCreateCallback done_callback;
124 gpointer done_callback_data;
125} CreateJob;
126
127
128typedef struct {
129 CommonJob common;
130 GList *trash_dirs;
131 gboolean should_confirm;
132 CajaOpCallback done_callback;
133 gpointer done_callback_data;
134} EmptyTrashJob;
135
136typedef struct {
137 CommonJob common;
138 GFile *file;
139 gboolean interactive;
140 CajaOpCallback done_callback;
141 gpointer done_callback_data;
142} MarkTrustedJob;
143
144typedef struct {
145 CommonJob common;
146 GFile *file;
147 CajaOpCallback done_callback;
148 gpointer done_callback_data;
149 guint32 file_permissions;
150 guint32 file_mask;
151 guint32 dir_permissions;
152 guint32 dir_mask;
153} SetPermissionsJob;
154
155typedef enum {
156 OP_KIND_COPY,
157 OP_KIND_MOVE,
158 OP_KIND_DELETE,
159 OP_KIND_TRASH
160} OpKind;
161
162typedef struct {
163 int num_files;
164 goffset num_bytes;
165 int num_files_since_progress;
166 OpKind op;
167} SourceInfo;
168
169typedef struct {
170 int num_files;
171 goffset num_bytes;
172 OpKind op;
173 guint64 last_report_time;
174 int last_reported_files_left;
175} TransferInfo;
176
177#define SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15 15
178#define NSEC_PER_MICROSEC1000 1000
179
180#define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50 50
181
182#define IS_IO_ERROR(__error, KIND)(((__error)->domain == g_io_error_quark() && (__error
)->code == G_IO_ERROR_KIND))
(((__error)->domain == G_IO_ERRORg_io_error_quark() && (__error)->code == G_IO_ERROR_ ## KIND))
183
184#define CANCELdcgettext (((void*)0), "_Cancel", 5) _("_Cancel")dcgettext (((void*)0), "_Cancel", 5)
185#define SKIPdcgettext (((void*)0), "_Skip", 5) _("_Skip")dcgettext (((void*)0), "_Skip", 5)
186#define SKIP_ALLdcgettext (((void*)0), "S_kip All", 5) _("S_kip All")dcgettext (((void*)0), "S_kip All", 5)
187#define RETRYdcgettext (((void*)0), "_Retry", 5) _("_Retry")dcgettext (((void*)0), "_Retry", 5)
188#define DELETEdcgettext (((void*)0), "_Delete", 5) _("_Delete")dcgettext (((void*)0), "_Delete", 5)
189#define DELETE_ALLdcgettext (((void*)0), "Delete _All", 5) _("Delete _All")dcgettext (((void*)0), "Delete _All", 5)
190#define REPLACE_ALLdcgettext (((void*)0), "Replace _All", 5) _("Replace _All")dcgettext (((void*)0), "Replace _All", 5)
191#define MERGE_ALLdcgettext (((void*)0), "Merge _All", 5) _("Merge _All")dcgettext (((void*)0), "Merge _All", 5)
192#define COPY_FORCEdcgettext (((void*)0), "Copy _Anyway", 5) _("Copy _Anyway")dcgettext (((void*)0), "Copy _Anyway", 5)
193
194NotifyNotification *unmount_notify;
195
196void
197caja_application_notify_unmount_show (const gchar *message)
198{
199 gchar **strings;
200 strings = g_strsplit (message, "\n", 0);
201
202 if (!g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_NOTIFICATIONS"show-notifications")) return;
203
204 if (unmount_notify == NULL((void*)0)) {
205 unmount_notify =
206 notify_notification_new (strings[0], strings[1],
207 "media-removable");
208
209 notify_notification_set_hint (unmount_notify,
210 "transient", g_variant_new_boolean (TRUE(!(0))));
211 notify_notification_set_urgency (unmount_notify,
212 NOTIFY_URGENCY_CRITICAL);
213 } else {
214 notify_notification_update (unmount_notify,
215 strings[0], strings[1],
216 "media-removable");
217 }
218
219 notify_notification_show (unmount_notify, NULL((void*)0));
220 g_strfreev (strings);
221}
222
223static void
224mark_desktop_file_trusted (CommonJob *common,
225 GCancellable *cancellable,
226 GFile *file,
227 gboolean interactive);
228
229static gboolean
230is_all_button_text (const char *button_text)
231{
232 g_assert (button_text != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if (button_text != ((void*)0)) _g_boolean_var_30 = 1; else _g_boolean_var_30
= 0; _g_boolean_var_30; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 232, ((const char*)
(__func__)), "button_text != NULL"); } while (0)
;
233
234 return !strcmp (button_text, SKIP_ALLdcgettext (((void*)0), "S_kip All", 5)) ||
235 !strcmp (button_text, REPLACE_ALLdcgettext (((void*)0), "Replace _All", 5)) ||
236 !strcmp (button_text, DELETE_ALLdcgettext (((void*)0), "Delete _All", 5)) ||
237 !strcmp (button_text, MERGE_ALLdcgettext (((void*)0), "Merge _All", 5));
238}
239
240static void scan_sources (GList *files,
241 SourceInfo *source_info,
242 CommonJob *job,
243 OpKind kind);
244
245
246static gboolean empty_trash_job (GIOSchedulerJob *io_job,
247 GCancellable *cancellable,
248 gpointer user_data);
249
250static char * query_fs_type (GFile *file,
251 GCancellable *cancellable);
252
253/* keep in time with format_time()
254 *
255 * This counts and outputs the number of “time units”
256 * formatted and displayed by format_time().
257 * For instance, if format_time outputs “3 hours, 4 minutes”
258 * it yields 7.
259 */
260static int
261seconds_count_format_time_units (int seconds)
262{
263 int minutes;
264 int hours;
265
266 if (seconds < 0) {
267 /* Just to make sure... */
268 seconds = 0;
269 }
270
271 if (seconds < 60) {
272 /* seconds */
273 return seconds;
274 }
275
276 if (seconds < 60*60) {
277 /* minutes */
278 minutes = seconds / 60;
279 return minutes;
280 }
281
282 hours = seconds / (60*60);
283
284 if (seconds < 60*60*4) {
285 /* minutes + hours */
286 minutes = (seconds - hours * 60 * 60) / 60;
287 return minutes + hours;
288 }
289
290 return hours;
291}
292
293static char *
294format_time (int seconds)
295{
296 int minutes;
297 int hours;
298
299 if (seconds < 0) {
300 /* Just to make sure... */
301 seconds = 0;
302 }
303
304 if (seconds < 60) {
305 return g_strdup_printf (ngettext ("%'d second","%'d seconds", (int) seconds)dcngettext (((void*)0), "%'d second", "%'d seconds", (int) seconds
, 5)
, (int) seconds);
306 }
307
308 if (seconds < 60*60) {
309 minutes = seconds / 60;
310 return g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes)dcngettext (((void*)0), "%'d minute", "%'d minutes", minutes,
5)
, minutes);
311 }
312
313 hours = seconds / (60*60);
314
315 if (seconds < 60*60*4) {
316 char *h, *m;
317 char *res;
318
319 minutes = (seconds - hours * 60 * 60) / 60;
320
321 h = g_strdup_printf (ngettext ("%'d hour", "%'d hours", hours)dcngettext (((void*)0), "%'d hour", "%'d hours", hours, 5), hours);
322 m = g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes)dcngettext (((void*)0), "%'d minute", "%'d minutes", minutes,
5)
, minutes);
323 res = g_strconcat (h, ", ", m, NULL((void*)0));
324 g_free (h);
325 g_free (m);
326 return res;
327 }
328
329 return g_strdup_printf (ngettext ("approximately %'d hour",dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
330 "approximately %'d hours",dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
331 hours)dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
, hours);
332}
333
334static char *
335shorten_utf8_string (const char *base, int reduce_by_num_bytes)
336{
337 int len;
338 char *ret;
339 const char *p;
340
341 len = strlen (base);
342 len -= reduce_by_num_bytes;
343
344 if (len <= 0) {
345 return NULL((void*)0);
346 }
347
348 ret = g_new (char, len + 1)(char *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
349
350 p = base;
351 while (len) {
352 char *next;
353 next = g_utf8_next_char (p)(char *)((p) + g_utf8_skip[*(const guchar *)(p)]);
354 if (next - p > len || *next == '\0') {
355 break;
356 }
357
358 len -= next - p;
359 p = next;
360 }
361
362 if (p - base == 0) {
363 g_free (ret);
364 return NULL((void*)0);
365 } else {
366 memcpy (ret, base, p - base);
367 ret[p - base] = '\0';
368 return ret;
369 }
370}
371
372/* Note that we have these two separate functions with separate format
373 * strings for ease of localization.
374 */
375
376static char *
377get_link_name (const char *name, int count, int max_length)
378{
379 const char *format;
380 char *result;
381 int unshortened_length;
382 gboolean use_count;
383
384 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if (name != ((void*)0)) _g_boolean_var_31 = 1; else _g_boolean_var_31
= 0; _g_boolean_var_31; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 384, ((const char*)
(__func__)), "name != NULL"); } while (0)
;
385
386 if (count < 0) {
387 g_warning ("bad count in get_link_name");
388 count = 0;
389 }
390
391 if (count <= 2) {
392 /* Handle special cases for low numbers.
393 * Perhaps for some locales we will need to add more.
394 */
395 switch (count) {
396 default:
397 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 397, ((const char*) (__func__)), ((void*)0)); } while (0)
;
398 /* fall through */
399 case 0:
400 /* duplicate original file name */
401 format = "%s";
402 break;
403 case 1:
404 /* appended to new link file */
405 format = _("Link to %s")dcgettext (((void*)0), "Link to %s", 5);
406 break;
407 case 2:
408 /* appended to new link file */
409 format = _("Another link to %s")dcgettext (((void*)0), "Another link to %s", 5);
410 break;
411 }
412
413 use_count = FALSE(0);
414 } else {
415 /* Handle special cases for the first few numbers of each ten.
416 * For locales where getting this exactly right is difficult,
417 * these can just be made all the same as the general case below.
418 */
419 switch (count % 10) {
420 case 1:
421 /* Translators: Feel free to leave out the "st" suffix
422 * if there's no way to do that nicely for a
423 * particular language.
424 */
425 format = _("%'dst link to %s")dcgettext (((void*)0), "%'dst link to %s", 5);
426 break;
427 case 2:
428 /* appended to new link file */
429 format = _("%'dnd link to %s")dcgettext (((void*)0), "%'dnd link to %s", 5);
430 break;
431 case 3:
432 /* appended to new link file */
433 format = _("%'drd link to %s")dcgettext (((void*)0), "%'drd link to %s", 5);
434 break;
435 default:
436 /* appended to new link file */
437 format = _("%'dth link to %s")dcgettext (((void*)0), "%'dth link to %s", 5);
438 break;
439 }
440
441 use_count = TRUE(!(0));
442 }
443
444 if (use_count)
445 result = g_strdup_printf (format, count, name);
446 else
447 result = g_strdup_printf (format, name);
448
449 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
450 char *new_name;
451
452 new_name = shorten_utf8_string (name, unshortened_length - max_length);
453 if (new_name) {
454 g_free (result);
455
456 if (use_count)
457 result = g_strdup_printf (format, count, new_name);
458 else
459 result = g_strdup_printf (format, new_name);
460
461 g_assert (strlen (result) <= max_length)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if (strlen (result) <= max_length) _g_boolean_var_32 = 1
; else _g_boolean_var_32 = 0; _g_boolean_var_32; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 461, ((const char*) (__func__)), "strlen (result) <= max_length"
); } while (0)
;
462 g_free (new_name);
463 }
464 }
465
466 return result;
467}
468
469
470/* Translators:
471 * Feel free to leave out the st, nd, rd and th suffix or
472 * make some or all of them match.
473 */
474
475/* Translators: tag used to detect the first copy of a file */
476static const char untranslated_copy_duplicate_tag[] = N_(" (copy)")(" (copy)");
477/* Translators: tag used to detect the second copy of a file */
478static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)")(" (another copy)");
479
480/* Translators: tag used to detect the x11th copy of a file */
481static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
482/* Translators: tag used to detect the x12th copy of a file */
483static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
484/* Translators: tag used to detect the x13th copy of a file */
485static const char untranslated_x13th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
486
487/* Translators: tag used to detect the x1st copy of a file */
488static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)")("st copy)");
489/* Translators: tag used to detect the x2nd copy of a file */
490static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)")("nd copy)");
491/* Translators: tag used to detect the x3rd copy of a file */
492static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)")("rd copy)");
493
494/* Translators: tag used to detect the xxth copy of a file */
495static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
496
497#define COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_copy_duplicate_tag, 5) _(untranslated_copy_duplicate_tag)dcgettext (((void*)0), untranslated_copy_duplicate_tag, 5)
498#define ANOTHER_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
_(untranslated_another_copy_duplicate_tag)dcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
499#define X11TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
_(untranslated_x11th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
500#define X12TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
_(untranslated_x12th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
501#define X13TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
_(untranslated_x13th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
502
503#define ST_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5) _(untranslated_st_copy_duplicate_tag)dcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5)
504#define ND_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5) _(untranslated_nd_copy_duplicate_tag)dcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5)
505#define RD_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5) _(untranslated_rd_copy_duplicate_tag)dcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5)
506#define TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5) _(untranslated_th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5)
507
508/* Translators: appended to first file copy */
509static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s")("%s (copy)%s");
510/* Translators: appended to second file copy */
511static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s")("%s (another copy)%s");
512
513/* Translators: appended to x11th file copy */
514static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
515/* Translators: appended to x12th file copy */
516static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
517/* Translators: appended to x13th file copy */
518static const char untranslated_x13th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
519
520/* Translators: if in your language there's no difference between 1st, 2nd, 3rd and nth
521 * plurals, you can leave the st, nd, rd suffixes out and just make all the translated
522 * strings look like "%s (copy %'d)%s".
523 */
524
525/* Translators: appended to x1st file copy */
526static const char untranslated_st_copy_duplicate_format[] = N_("%s (%'dst copy)%s")("%s (%'dst copy)%s");
527/* Translators: appended to x2nd file copy */
528static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%'dnd copy)%s")("%s (%'dnd copy)%s");
529/* Translators: appended to x3rd file copy */
530static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%'drd copy)%s")("%s (%'drd copy)%s");
531/* Translators: appended to xxth file copy */
532static const char untranslated_th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
533
534#define FIRST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
_(untranslated_first_copy_duplicate_format)dcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
535#define SECOND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
_(untranslated_second_copy_duplicate_format)dcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
536#define X11TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
_(untranslated_x11th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
537#define X12TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
_(untranslated_x12th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
538#define X13TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
_(untranslated_x13th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
539
540#define ST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
_(untranslated_st_copy_duplicate_format)dcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
541#define ND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
_(untranslated_nd_copy_duplicate_format)dcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
542#define RD_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
_(untranslated_rd_copy_duplicate_format)dcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
543#define TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
_(untranslated_th_copy_duplicate_format)dcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
544
545static char *
546extract_string_until (const char *original, const char *until_substring)
547{
548 char *result;
549
550 g_assert ((int) strlen (original) >= until_substring - original)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if ((int) strlen (original) >= until_substring - original
) _g_boolean_var_33 = 1; else _g_boolean_var_33 = 0; _g_boolean_var_33
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 550, ((const char*) (__func__)), "(int) strlen (original) >= until_substring - original"
); } while (0)
;
551 g_assert (until_substring - original >= 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if (until_substring - original >= 0) _g_boolean_var_34 =
1; else _g_boolean_var_34 = 0; _g_boolean_var_34; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 551, ((const char*) (__func__)), "until_substring - original >= 0"
); } while (0)
;
552
553 result = g_malloc (until_substring - original + 1);
554 strncpy (result, original, until_substring - original);
555 result[until_substring - original] = '\0';
556
557 return result;
558}
559
560/* Dismantle a file name, separating the base name, the file suffix and removing any
561 * (xxxcopy), etc. string. Figure out the count that corresponds to the given
562 * (xxxcopy) substring.
563 */
564static void
565parse_previous_duplicate_name (const char *name,
566 char **name_base,
567 const char **suffix,
568 int *count)
569{
570 const char *tag;
571
572 g_assert (name[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if (name[0] != '\0') _g_boolean_var_35 = 1; else _g_boolean_var_35
= 0; _g_boolean_var_35; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 572, ((const char*)
(__func__)), "name[0] != '\\0'"); } while (0)
;
573
574 *suffix = strchr (name + 1, '.');
575 if (*suffix == NULL((void*)0) || (*suffix)[1] == '\0') {
576 /* no suffix */
577 *suffix = "";
578 }
579
580 tag = strstr (name, COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_copy_duplicate_tag, 5));
581 if (tag != NULL((void*)0)) {
582 if (tag > *suffix) {
583 /* handle case "foo. (copy)" */
584 *suffix = "";
585 }
586 *name_base = extract_string_until (name, tag);
587 *count = 1;
588 return;
589 }
590
591
592 tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
);
593 if (tag != NULL((void*)0)) {
594 if (tag > *suffix) {
595 /* handle case "foo. (another copy)" */
596 *suffix = "";
597 }
598 *name_base = extract_string_until (name, tag);
599 *count = 2;
600 return;
601 }
602
603
604 /* Check to see if we got one of st, nd, rd, th. */
605 tag = strstr (name, X11TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
);
606
607 if (tag == NULL((void*)0)) {
608 tag = strstr (name, X12TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
);
609 }
610 if (tag == NULL((void*)0)) {
611 tag = strstr (name, X13TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
);
612 }
613
614 if (tag == NULL((void*)0)) {
615 tag = strstr (name, ST_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5));
616 }
617 if (tag == NULL((void*)0)) {
618 tag = strstr (name, ND_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5));
619 }
620 if (tag == NULL((void*)0)) {
621 tag = strstr (name, RD_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5));
622 }
623 if (tag == NULL((void*)0)) {
624 tag = strstr (name, TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5));
625 }
626
627 /* If we got one of st, nd, rd, th, fish out the duplicate number. */
628 if (tag != NULL((void*)0)) {
629 /* Translators: opening parentheses to match the "th copy)" string */
630 tag = strstr (name, _(" (")dcgettext (((void*)0), " (", 5));
631 if (tag != NULL((void*)0)) {
632 if (tag > *suffix) {
633 /* handle case "foo. (22nd copy)" */
634 *suffix = "";
635 }
636 *name_base = extract_string_until (name, tag);
637 /* Translators: opening parentheses of the "th copy)" string */
638 if (sscanf (tag, _(" (%'d")dcgettext (((void*)0), " (%'d", 5), count) == 1) {
639 if (*count < 1 || *count > 1000000) {
640 /* keep the count within a reasonable range */
641 *count = 0;
642 }
643 return;
644 }
645 *count = 0;
646 return;
647 }
648 }
649
650
651 *count = 0;
652 if (**suffix != '\0') {
653 *name_base = extract_string_until (name, *suffix);
654 } else {
655 *name_base = g_strdup (name)g_strdup_inline (name);
656 }
657}
658
659static char *
660make_next_duplicate_name (const char *base, const char *suffix, int count, int max_length)
661{
662 const char *format;
663 char *result;
664 int unshortened_length;
665 gboolean use_count;
666
667 if (count < 1) {
668 g_warning ("bad count %d in get_duplicate_name", count);
669 count = 1;
670 }
671
672 if (count <= 2) {
673
674 /* Handle special cases for low numbers.
675 * Perhaps for some locales we will need to add more.
676 */
677 switch (count) {
678 default:
679 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 679, ((const char*) (__func__)), ((void*)0)); } while (0)
;
680 /* fall through */
681 case 1:
682 format = FIRST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
;
683 break;
684 case 2:
685 format = SECOND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
;
686 break;
687
688 }
689
690 use_count = FALSE(0);
691 } else {
692
693 /* Handle special cases for the first few numbers of each ten.
694 * For locales where getting this exactly right is difficult,
695 * these can just be made all the same as the general case below.
696 */
697
698 /* Handle special cases for x11th - x20th.
699 */
700 switch (count % 100) {
701 case 11:
702 format = X11TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
;
703 break;
704 case 12:
705 format = X12TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
;
706 break;
707 case 13:
708 format = X13TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
;
709 break;
710 default:
711 format = NULL((void*)0);
712 break;
713 }
714
715 if (format == NULL((void*)0)) {
716 switch (count % 10) {
717 case 1:
718 format = ST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
;
719 break;
720 case 2:
721 format = ND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
;
722 break;
723 case 3:
724 format = RD_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
;
725 break;
726 default:
727 /* The general case. */
728 format = TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
;
729 break;
730 }
731 }
732
733 use_count = TRUE(!(0));
734
735 }
736
737 if (use_count)
738 result = g_strdup_printf (format, base, count, suffix);
739 else
740 result = g_strdup_printf (format, base, suffix);
741
742 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
743 char *new_base;
744
745 new_base = shorten_utf8_string (base, unshortened_length - max_length);
746 if (new_base) {
747 g_free (result);
748
749 if (use_count)
750 result = g_strdup_printf (format, new_base, count, suffix);
751 else
752 result = g_strdup_printf (format, new_base, suffix);
753
754 g_assert (strlen (result) <= max_length)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if (strlen (result) <= max_length) _g_boolean_var_36 = 1
; else _g_boolean_var_36 = 0; _g_boolean_var_36; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 754, ((const char*) (__func__)), "strlen (result) <= max_length"
); } while (0)
;
755 g_free (new_base);
756 }
757 }
758
759 return result;
760}
761
762static char *
763get_duplicate_name (const char *name, int count_increment, int max_length)
764{
765 char *result;
766 char *name_base;
767 const char *suffix;
768 int count;
769
770 parse_previous_duplicate_name (name, &name_base, &suffix, &count);
771 result = make_next_duplicate_name (name_base, suffix, count + count_increment, max_length);
772
773 g_free (name_base);
774
775 return result;
776}
777
778static gboolean
779has_invalid_xml_char (char *str)
780{
781 gunichar c;
782
783 while (*str != 0) {
784 c = g_utf8_get_char (str);
785 /* characters XML permits */
786 if (!(c == 0x9 ||
787 c == 0xA ||
788 c == 0xD ||
789 (c >= 0x20 && c <= 0xD7FF) ||
790 (c >= 0xE000 && c <= 0xFFFD) ||
791 (c >= 0x10000 && c <= 0x10FFFF))) {
792 return TRUE(!(0));
793 }
794 str = g_utf8_next_char (str)(char *)((str) + g_utf8_skip[*(const guchar *)(str)]);
795 }
796 return FALSE(0);
797}
798
799
800static char *
801custom_full_name_to_string (char *format, va_list va)
802{
803 GFile *file;
804
805 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
806
807 return g_file_get_parse_name (file);
808}
809
810static void
811custom_full_name_skip (va_list *va)
812{
813 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
814}
815
816static char *
817custom_basename_to_string (char *format, va_list va)
818{
819 GFile *file;
820 GFileInfo *info;
821 char *name, *basename, *tmp;
822
823 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
824
825 info = g_file_query_info (file,
826 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME"standard::display-name",
827 0,
828 g_cancellable_get_current (),
829 NULL((void*)0));
830
831 name = NULL((void*)0);
832 if (info) {
833 name = g_strdup (g_file_info_get_display_name (info))g_strdup_inline (g_file_info_get_display_name (info));
834 g_object_unref (info);
835 }
836
837 if (name == NULL((void*)0)) {
838 basename = g_file_get_basename (file);
839 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
840 name = basename;
841 } else {
842 name = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
843 g_free (basename);
844 }
845 }
846
847 /* Some chars can't be put in the markup we use for the dialogs... */
848 if (has_invalid_xml_char (name)) {
849 tmp = name;
850 name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
851 g_free (tmp);
852 }
853
854 /* Finally, if the string is too long, truncate it. */
855 if (name != NULL((void*)0)) {
856 tmp = name;
857 name = eel_str_middle_truncate (tmp, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50);
858 g_free (tmp);
859 }
860
861
862 return name;
863}
864
865static void
866custom_basename_skip (va_list *va)
867{
868 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
869}
870
871
872static char *
873custom_size_to_string (char *format, va_list va)
874{
875 goffset size;
876
877 size = va_arg (va, goffset)__builtin_va_arg(va, goffset);
878
879 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
880 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
881 else
882 return g_format_size(size);
883}
884
885static void
886custom_size_skip (va_list *va)
887{
888 (void) va_arg (*va, goffset)__builtin_va_arg(*va, goffset);
889}
890
891static char *
892custom_time_to_string (char *format, va_list va)
893{
894 int secs;
895
896 secs = va_arg (va, int)__builtin_va_arg(va, int);
897 return format_time (secs);
898}
899
900static void
901custom_time_skip (va_list *va)
902{
903 (void) va_arg (*va, int)__builtin_va_arg(*va, int);
904}
905
906static char *
907custom_mount_to_string (char *format, va_list va)
908{
909 GMount *mount;
910
911 mount = va_arg (va, GMount *)__builtin_va_arg(va, GMount *);
912 return g_mount_get_name (mount);
913}
914
915static void
916custom_mount_skip (va_list *va)
917{
918 (void) va_arg (*va, GMount *)__builtin_va_arg(*va, GMount *);
919}
920
921
922static EelPrintfHandler handlers[] = {
923 { 'F', custom_full_name_to_string, custom_full_name_skip },
924 { 'B', custom_basename_to_string, custom_basename_skip },
925 { 'S', custom_size_to_string, custom_size_skip },
926 { 'T', custom_time_to_string, custom_time_skip },
927 { 'V', custom_mount_to_string, custom_mount_skip },
928 { 0 }
929};
930
931
932static char *
933f (const char *format, ...) {
934 va_list va;
935 char *res;
936
937 va_start (va, format)__builtin_va_start(va, format);
938 res = eel_strdup_vprintf_with_custom (handlers, format, va);
939 va_end (va)__builtin_va_end(va);
940
941 return res;
942}
943
944#define op_job_new(__type, parent_window, should_start, can_pause)((__type *)(init_common (sizeof(__type), parent_window, should_start
, can_pause)))
((__type *)(init_common (sizeof(__type), parent_window, should_start, can_pause)))
945
946static gpointer
947init_common (gsize job_size,
948 GtkWindow *parent_window,
949 gboolean should_start, gboolean can_pause)
950{
951 CommonJob *common;
952
953 /* expected warning with Clang static analyzer: *
954 * "Cast a region whose size is not a multiple of the destination type size" *
955 * *
956 * It is expected for job_size to be larger than sizeof(CommonJob) no matter *
957 * what Clang analyzer reports: we're allocating the whole structure for a job *
958 * (e.g. a TrashJob), but only initializing the common part of it (CommonJob) *
959 * which is a subset of all "real" job structures, structures that all start *
960 * with a CommonJob, and that thus can be used as such. */
961 common = g_malloc0 (job_size);
2
Cast a region whose size is not a multiple of the destination type size
962
963 if (parent_window) {
964 common->parent_window = parent_window;
965 eel_add_weak_pointer (&common->parent_window);
966 }
967 common->progress = caja_progress_info_new (should_start, can_pause);
968 common->cancellable = caja_progress_info_get_cancellable (common->progress);
969 common->time = g_timer_new ();
970 common->inhibit_cookie = -1;
971 common->screen_num = 0;
972 if (parent_window) {
973 GdkScreen *screen;
974
975 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) (void *) ((parent_window))))));
976 common->screen_num = gdk_x11_screen_get_screen_number (screen);
977 }
978
979 return common;
980}
981
982static void
983finalize_common (CommonJob *common)
984{
985 caja_progress_info_finish (common->progress);
986
987 if (common->inhibit_cookie != -1) {
988 caja_uninhibit_power_manager (common->inhibit_cookie);
989 }
990
991 common->inhibit_cookie = -1;
992 g_timer_destroy (common->time);
993 eel_remove_weak_pointer (&common->parent_window);
994 if (common->skip_files) {
995 g_hash_table_destroy (common->skip_files);
996 }
997 if (common->skip_readdir_error) {
998 g_hash_table_destroy (common->skip_readdir_error);
999 }
1000 // Start UNDO-REDO
1001 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1002 common->undo_redo_data);
1003 // End UNDO-REDO
1004 g_object_unref (common->progress);
1005 g_object_unref (common->cancellable);
1006 g_free (common);
1007}
1008
1009static void
1010skip_file (CommonJob *common,
1011 GFile *file)
1012{
1013 if (common->skip_files == NULL((void*)0)) {
1014 common->skip_files =
1015 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1016 }
1017
1018 g_hash_table_insert (common->skip_files, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)), file);
1019}
1020
1021static void
1022skip_readdir_error (CommonJob *common,
1023 GFile *dir)
1024{
1025 if (common->skip_readdir_error == NULL((void*)0)) {
1026 common->skip_readdir_error =
1027 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1028 }
1029
1030 g_hash_table_insert (common->skip_readdir_error, g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir)), dir);
1031}
1032
1033static gboolean
1034should_skip_file (CommonJob *common,
1035 GFile *file)
1036{
1037 if (common->skip_files != NULL((void*)0)) {
1038 return g_hash_table_lookup (common->skip_files, file) != NULL((void*)0);
1039 }
1040
1041 return FALSE(0);
1042}
1043
1044static gboolean
1045should_skip_readdir_error (CommonJob *common,
1046 GFile *dir)
1047{
1048 if (common->skip_readdir_error != NULL((void*)0)) {
1049 return g_hash_table_lookup (common->skip_readdir_error, dir) != NULL((void*)0);
1050 }
1051 return FALSE(0);
1052}
1053
1054static gboolean
1055can_delete_without_confirm (GFile *file)
1056{
1057 if (g_file_has_uri_scheme (file, "burn") ||
1058 g_file_has_uri_scheme (file, "x-caja-desktop")) {
1059 return TRUE(!(0));
1060 }
1061
1062 return FALSE(0);
1063}
1064
1065static gboolean
1066can_delete_files_without_confirm (GList *files)
1067{
1068 g_assert (files != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if (files != ((void*)0)) _g_boolean_var_37 = 1; else _g_boolean_var_37
= 0; _g_boolean_var_37; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1068, ((const char*
) (__func__)), "files != NULL"); } while (0)
;
1069
1070 while (files != NULL((void*)0)) {
1071 if (!can_delete_without_confirm (files->data)) {
1072 return FALSE(0);
1073 }
1074
1075 files = files->next;
1076 }
1077
1078 return TRUE(!(0));
1079}
1080
1081typedef struct {
1082 GtkWindow **parent_window;
1083 gboolean ignore_close_box;
1084 GtkMessageType message_type;
1085 const char *primary_text;
1086 const char *secondary_text;
1087 const char *details_text;
1088 const char **button_titles;
1089 gboolean show_all;
1090
1091 int result;
1092} RunSimpleDialogData;
1093
1094static gboolean
1095do_run_simple_dialog (gpointer _data)
1096{
1097 RunSimpleDialogData *data = _data;
1098 GtkWidget *dialog;
1099 int result;
1100 int response_id;
1101
1102 /* Create the dialog. */
1103 dialog = gtk_message_dialog_new (*data->parent_window,
1104 0,
1105 data->message_type,
1106 GTK_BUTTONS_NONE,
1107 NULL((void*)0));
1108
1109 g_object_set (dialog,
1110 "text", data->primary_text,
1111 "secondary-text", data->secondary_text,
1112 NULL((void*)0));
1113
1114 for (response_id = 0;
1115 data->button_titles[response_id] != NULL((void*)0);
1116 response_id++) {
1117 const char *button_title;
1118
1119 button_title = data->button_titles[response_id];
1120 if (!data->show_all && is_all_button_text (button_title)) {
1121 continue;
1122 }
1123
1124 if (g_strcmp0 (button_title, CANCELdcgettext (((void*)0), "_Cancel", 5)) == 0)
1125 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, "process-stop", response_id);
1126 else if (g_strcmp0 (button_title, DELETEdcgettext (((void*)0), "_Delete", 5)) == 0)
1127 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, "edit-delete", response_id);
1128 else
1129 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, response_id);
1130
1131 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), response_id);
1132 }
1133
1134 if (data->details_text) {
1135 eel_gtk_message_dialog_set_details_label (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
1136 data->details_text);
1137 }
1138
1139 /* Run it. */
1140 gtk_widget_show (dialog);
1141 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
1142
1143 while ((result == GTK_RESPONSE_NONE || result == GTK_RESPONSE_DELETE_EVENT) && data->ignore_close_box) {
1144 gtk_widget_show (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1145 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
1146 }
1147
1148 gtk_widget_destroy (dialog);
1149
1150 data->result = result;
1151
1152 return FALSE(0);
1153}
1154
1155/* NOTE: This frees the primary / secondary strings, in order to
1156 avoid doing that everywhere. So, make sure they are strduped */
1157
1158static int
1159run_simple_dialog_va (CommonJob *job,
1160 gboolean ignore_close_box,
1161 GtkMessageType message_type,
1162 char *primary_text,
1163 char *secondary_text,
1164 const char *details_text,
1165 gboolean show_all,
1166 va_list varargs)
1167{
1168 RunSimpleDialogData *data;
1169 int res;
1170 const char *button_title;
1171 GPtrArray *ptr_array;
1172
1173 g_timer_stop (job->time);
1174
1175 data = g_new0 (RunSimpleDialogData, 1)(RunSimpleDialogData *) (__extension__ ({ gsize __n = (gsize)
(1); gsize __s = sizeof (RunSimpleDialogData); 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; }))
;
1176 data->parent_window = &job->parent_window;
1177 data->ignore_close_box = ignore_close_box;
1178 data->message_type = message_type;
1179 data->primary_text = primary_text;
1180 data->secondary_text = secondary_text;
1181 data->details_text = details_text;
1182 data->show_all = show_all;
1183
1184 ptr_array = g_ptr_array_new ();
1185 while ((button_title = va_arg (varargs, const char *)__builtin_va_arg(varargs, const char *)) != NULL((void*)0)) {
1186 g_ptr_array_add (ptr_array, (char *)button_title);
1187 }
1188 g_ptr_array_add (ptr_array, NULL((void*)0));
1189 data->button_titles = (const char **)g_ptr_array_free (ptr_array, FALSE(0));
1190
1191 caja_progress_info_pause (job->progress);
1192 g_io_scheduler_job_send_to_mainloop (job->io_job,
1193 do_run_simple_dialog,
1194 data,
1195 NULL((void*)0));
1196 caja_progress_info_resume (job->progress);
1197 res = data->result;
1198
1199 g_free (data->button_titles);
1200 g_free (data);
1201
1202 g_timer_continue (job->time);
1203
1204 g_free (primary_text);
1205 g_free (secondary_text);
1206
1207 return res;
1208}
1209
1210#if 0 /* Not used at the moment */
1211static int
1212run_simple_dialog (CommonJob *job,
1213 gboolean ignore_close_box,
1214 GtkMessageType message_type,
1215 char *primary_text,
1216 char *secondary_text,
1217 const char *details_text,
1218 ...)
1219{
1220 va_list varargs;
1221 int res;
1222
1223 va_start (varargs, details_text)__builtin_va_start(varargs, details_text);
1224 res = run_simple_dialog_va (job,
1225 ignore_close_box,
1226 message_type,
1227 primary_text,
1228 secondary_text,
1229 details_text,
1230 varargs);
1231 va_end (varargs)__builtin_va_end(varargs);
1232 return res;
1233}
1234#endif
1235
1236static int
1237run_error (CommonJob *job,
1238 char *primary_text,
1239 char *secondary_text,
1240 const char *details_text,
1241 gboolean show_all,
1242 ...)
1243{
1244 va_list varargs;
1245 int res;
1246
1247 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1248 res = run_simple_dialog_va (job,
1249 FALSE(0),
1250 GTK_MESSAGE_ERROR,
1251 primary_text,
1252 secondary_text,
1253 details_text,
1254 show_all,
1255 varargs);
1256 va_end (varargs)__builtin_va_end(varargs);
1257 return res;
1258}
1259
1260static int
1261run_warning (CommonJob *job,
1262 char *primary_text,
1263 char *secondary_text,
1264 const char *details_text,
1265 gboolean show_all,
1266 ...)
1267{
1268 va_list varargs;
1269 int res;
1270
1271 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1272 res = run_simple_dialog_va (job,
1273 FALSE(0),
1274 GTK_MESSAGE_WARNING,
1275 primary_text,
1276 secondary_text,
1277 details_text,
1278 show_all,
1279 varargs);
1280 va_end (varargs)__builtin_va_end(varargs);
1281 return res;
1282}
1283
1284static int
1285run_question (CommonJob *job,
1286 char *primary_text,
1287 char *secondary_text,
1288 const char *details_text,
1289 gboolean show_all,
1290 ...)
1291{
1292 va_list varargs;
1293 int res;
1294
1295 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1296 res = run_simple_dialog_va (job,
1297 FALSE(0),
1298 GTK_MESSAGE_QUESTION,
1299 primary_text,
1300 secondary_text,
1301 details_text,
1302 show_all,
1303 varargs);
1304 va_end (varargs)__builtin_va_end(varargs);
1305 return res;
1306}
1307
1308static void
1309inhibit_power_manager (CommonJob *job, const char *message)
1310{
1311 job->inhibit_cookie = caja_inhibit_power_manager (message);
1312}
1313
1314static void
1315abort_job (CommonJob *job)
1316{
1317 g_cancellable_cancel (job->cancellable);
1318
1319}
1320
1321/* Since this happens on a thread we can't use the global prefs object */
1322static gboolean
1323should_confirm_trash (void)
1324{
1325 GSettings *prefs;
1326 gboolean confirm_trash;
1327
1328 prefs = g_settings_new ("org.mate.caja.preferences");
1329 confirm_trash = g_settings_get_boolean (prefs, CAJA_PREFERENCES_CONFIRM_TRASH"confirm-trash");
1330 g_object_unref (prefs);
1331 return confirm_trash;
1332}
1333
1334static gboolean
1335should_confirm_move_to_trash (void)
1336{
1337 GSettings *prefs;
1338 gboolean confirm_trash;
1339
1340 prefs = g_settings_new ("org.mate.caja.preferences");
1341 confirm_trash = g_settings_get_boolean (prefs, CAJA_PREFERENCES_CONFIRM_MOVE_TO_TRASH"confirm-move-to-trash");
1342 g_object_unref (prefs);
1343 return confirm_trash;
1344}
1345
1346static gboolean
1347job_aborted (CommonJob *job)
1348{
1349 return g_cancellable_is_cancelled (job->cancellable);
1350}
1351
1352static gboolean
1353confirm_delete_from_trash (CommonJob *job,
1354 GList *files)
1355{
1356 char *prompt;
1357 int file_count;
1358 int response;
1359
1360 /* Just Say Yes if the preference says not to confirm. */
1361 if (!should_confirm_trash ()) {
1362 return TRUE(!(0));
1363 }
1364
1365 file_count = g_list_length (files);
1366 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if (file_count > 0) _g_boolean_var_38 = 1; else _g_boolean_var_38
= 0; _g_boolean_var_38; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1366, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1367
1368 if (file_count == 1) {
1369 prompt = f (_("Are you sure you want to permanently delete \"%B\" "dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\" "
"from the trash?", 5)
1370 "from the trash?")dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\" "
"from the trash?", 5)
, files->data);
1371 } else {
1372 prompt = f (ngettext("Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1373 "the %'d selected item from the trash?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1374 "Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1375 "the %'d selected items from the trash?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1376 file_count)dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
,
1377 file_count);
1378 }
1379
1380 response = run_warning (job,
1381 prompt,
1382 f (_("If you delete an item, it will be permanently lost.")dcgettext (((void*)0), "If you delete an item, it will be permanently lost."
, 5)
),
1383 NULL((void*)0),
1384 FALSE(0),
1385 CANCELdcgettext (((void*)0), "_Cancel", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1386 NULL((void*)0));
1387
1388 return (response == 1);
1389}
1390
1391static gboolean
1392confirm_empty_trash (CommonJob *job)
1393{
1394 char *prompt;
1395 int response;
1396
1397 /* Just Say Yes if the preference says not to confirm. */
1398 if (!should_confirm_trash ()) {
1399 return TRUE(!(0));
1400 }
1401
1402 prompt = f (_("Empty all items from Trash?")dcgettext (((void*)0), "Empty all items from Trash?", 5));
1403
1404 response = run_warning (job,
1405 prompt,
1406 f(_("All items in the Trash will be permanently deleted.")dcgettext (((void*)0), "All items in the Trash will be permanently deleted."
, 5)
),
1407 NULL((void*)0),
1408 FALSE(0),
1409 CANCELdcgettext (((void*)0), "_Cancel", 5), _("Empty _Trash")dcgettext (((void*)0), "Empty _Trash", 5),
1410 NULL((void*)0));
1411
1412 return (response == 1);
1413}
1414
1415static gboolean
1416confirm_delete_directly (CommonJob *job,
1417 GList *files)
1418{
1419 char *prompt;
1420 int file_count;
1421 int response;
1422
1423 /* Just Say Yes if the preference says not to confirm. */
1424 if (!should_confirm_trash ()) {
1425 return TRUE(!(0));
1426 }
1427
1428 file_count = g_list_length (files);
1429 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if (file_count > 0) _g_boolean_var_39 = 1; else _g_boolean_var_39
= 0; _g_boolean_var_39; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1429, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1430
1431 if (can_delete_files_without_confirm (files)) {
1432 return TRUE(!(0));
1433 }
1434
1435 if (file_count == 1) {
1436 prompt = f (_("Are you sure you want to permanently delete \"%B\"?")dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\"?"
, 5)
,
1437 files->data);
1438 } else {
1439 prompt = f (ngettext("Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1440 "the %'d selected item?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1441 "Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1442 "the %'d selected items?", file_count)dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
,
1443 file_count);
1444 }
1445
1446 response = run_warning (job,
1447 prompt,
1448 f (_("If you delete an item, it will be permanently lost.")dcgettext (((void*)0), "If you delete an item, it will be permanently lost."
, 5)
),
1449 NULL((void*)0),
1450 FALSE(0),
1451 CANCELdcgettext (((void*)0), "_Cancel", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1452 NULL((void*)0));
1453
1454 return response == 1;
1455}
1456
1457static gboolean
1458confirm_trash (CommonJob *job,
1459 GList *files)
1460{
1461 char *prompt;
1462 int file_count;
1463 int response;
1464
1465 /* Just Say Yes if the preference says not to confirm. */
1466 if (!should_confirm_move_to_trash ()) {
1467 return TRUE(!(0));
1468 }
1469
1470 file_count = g_list_length (files);
1471 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_40
; if (file_count > 0) _g_boolean_var_40 = 1; else _g_boolean_var_40
= 0; _g_boolean_var_40; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1471, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1472
1473 if (can_delete_files_without_confirm (files)) {
1474 return TRUE(!(0));
1475 }
1476
1477 if (file_count == 1) {
1478 prompt = f (_("Are you sure you want to trash \"%B\"?")dcgettext (((void*)0), "Are you sure you want to trash \"%B\"?"
, 5)
,
1479 files->data);
1480 } else {
1481 prompt = f (ngettext("Are you sure you want to trash "dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1482 "the %'d selected item?",dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1483 "Are you sure you want to trash "dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1484 "the %'d selected items?", file_count)dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
,
1485 file_count);
1486 }
1487
1488 response = run_warning (job,
1489 prompt,
1490 f (_("Items moved to the trash may be recovered until the trash is emptied.")dcgettext (((void*)0), "Items moved to the trash may be recovered until the trash is emptied."
, 5)
),
1491 NULL((void*)0),
1492 FALSE(0),
1493 CANCELdcgettext (((void*)0), "_Cancel", 5), _("Move to _Trash")dcgettext (((void*)0), "Move to _Trash", 5),
1494 NULL((void*)0));
1495
1496 return response == 1;
1497}
1498
1499static void
1500report_delete_progress (CommonJob *job,
1501 SourceInfo *source_info,
1502 TransferInfo *transfer_info)
1503{
1504 int files_left;
1505 double elapsed;
1506 gint64 now;
1507 char *files_left_s;
1508
1509 now = g_get_monotonic_time ();
1510 if (transfer_info->last_report_time != 0 &&
1511 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
1512 return;
1513 }
1514 transfer_info->last_report_time = now;
1515
1516 files_left = source_info->num_files - transfer_info->num_files;
1517
1518 /* Races and whatnot could cause this to be negative... */
1519 if (files_left < 0) {
1520 files_left = 1;
1521 }
1522
1523 files_left_s = f (ngettext ("%'d file left to delete",dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
1524 "%'d files left to delete",dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
1525 files_left)dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
,
1526 files_left);
1527
1528 caja_progress_info_take_status (job->progress,
1529 f (_("Deleting files")dcgettext (((void*)0), "Deleting files", 5)));
1530
1531 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
1532 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15) {
1533
1534 caja_progress_info_set_details (job->progress, files_left_s);
1535 } else {
1536 char *details, *time_left_s;
1537 int remaining_time;
1538 double transfer_rate;
1539
1540 transfer_rate = transfer_info->num_files / elapsed;
1541 remaining_time = files_left / transfer_rate;
1542
1543 /* Translators: %T will expand to a time like "2 minutes".
1544 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
1545 */
1546 time_left_s = f (ngettext ("%T left",dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
1547 "%T left",dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
1548 seconds_count_format_time_units (remaining_time))dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
,
1549 remaining_time);
1550
1551 details = g_strconcat (files_left_s, "\xE2\x80\x94", time_left_s, NULL((void*)0));
1552 caja_progress_info_take_details (job->progress, details);
1553
1554 g_free (time_left_s);
1555 }
1556
1557 g_free (files_left_s);
1558
1559 if (source_info->num_files != 0) {
1560 caja_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files);
1561 }
1562}
1563
1564static void delete_file (CommonJob *job, GFile *file,
1565 gboolean *skipped_file,
1566 SourceInfo *source_info,
1567 TransferInfo *transfer_info,
1568 gboolean toplevel);
1569
1570static void
1571delete_dir (CommonJob *job, GFile *dir,
1572 gboolean *skipped_file,
1573 SourceInfo *source_info,
1574 TransferInfo *transfer_info,
1575 gboolean toplevel)
1576{
1577 GFileInfo *info;
1578 GError *error;
1579 GFile *file;
1580 GFileEnumerator *enumerator;
1581 char *primary, *secondary, *details;
1582 int response;
1583 gboolean skip_error;
1584 gboolean local_skipped_file;
1585
1586 local_skipped_file = FALSE(0);
1587
1588 skip_error = should_skip_readdir_error (job, dir);
1589 retry:
1590 error = NULL((void*)0);
1591 enumerator = g_file_enumerate_children (dir,
1592 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
1593 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1594 job->cancellable,
1595 &error);
1596 if (enumerator) {
1597 error = NULL((void*)0);
1598
1599 while (!job_aborted (job) &&
1600 (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error)) != NULL((void*)0)) {
1601 file = g_file_get_child (dir,
1602 g_file_info_get_name (info));
1603 delete_file (job, file, &local_skipped_file, source_info, transfer_info, FALSE(0));
1604 g_object_unref (file);
1605 g_object_unref (info);
1606 }
1607 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
1608 g_object_unref (enumerator);
1609
1610 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1611 g_error_free (error);
1612 } else if (error) {
1613 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1614 details = NULL((void*)0);
1615
1616 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1617 secondary = f (_("Files in the folder \"%B\" cannot be deleted because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be deleted because you do "
"not have permissions to see them.", 5)
1618 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be deleted because you do "
"not have permissions to see them.", 5)
, dir);
1619 } else {
1620 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, dir);
1621 details = error->message;
1622 }
1623
1624 response = run_warning (job,
1625 primary,
1626 secondary,
1627 details,
1628 FALSE(0),
1629 CANCELdcgettext (((void*)0), "_Cancel", 5), _("_Skip files")dcgettext (((void*)0), "_Skip files", 5),
1630 NULL((void*)0));
1631
1632 g_error_free (error);
1633
1634 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1635 abort_job (job);
1636 } else if (response == 1) {
1637 /* Skip: Do Nothing */
1638 local_skipped_file = TRUE(!(0));
1639 } else {
1640 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1640, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1641 }
1642 }
1643
1644 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1645 g_error_free (error);
1646 } else {
1647 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1648 details = NULL((void*)0);
1649 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1650 secondary = f (_("The folder \"%B\" cannot be deleted because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be deleted because you do not have "
"permissions to read it.", 5)
1651 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be deleted because you do not have "
"permissions to read it.", 5)
, dir);
1652 } else {
1653 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, dir);
1654 details = error->message;
1655 }
1656
1657 response = run_warning (job,
1658 primary,
1659 secondary,
1660 details,
1661 FALSE(0),
1662 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
1663 NULL((void*)0));
1664
1665 g_error_free (error);
1666
1667 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1668 abort_job (job);
1669 } else if (response == 1) {
1670 /* Skip: Do Nothing */
1671 local_skipped_file = TRUE(!(0));
1672 } else if (response == 2) {
1673 goto retry;
1674 } else {
1675 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1675, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1676 }
1677 }
1678
1679 if (!job_aborted (job) &&
1680 /* Don't delete dir if there was a skipped file */
1681 !local_skipped_file) {
1682 if (!g_file_delete (dir, job->cancellable, &error)) {
1683 if (job->skip_all_error) {
1684 goto skip;
1685 }
1686 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1687 secondary = f (_("Could not remove the folder %B.")dcgettext (((void*)0), "Could not remove the folder %B.", 5), dir);
1688 details = error->message;
1689
1690 response = run_warning (job,
1691 primary,
1692 secondary,
1693 details,
1694 (source_info->num_files - transfer_info->num_files) > 1,
1695 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
1696 NULL((void*)0));
1697
1698 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1699 abort_job (job);
1700 } else if (response == 1) { /* skip all */
1701 job->skip_all_error = TRUE(!(0));
1702 local_skipped_file = TRUE(!(0));
1703 } else if (response == 2) { /* skip */
1704 local_skipped_file = TRUE(!(0));
1705 } else {
1706 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1706, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1707 }
1708
1709 skip:
1710 g_error_free (error);
1711 } else {
1712 caja_file_changes_queue_file_removed (dir);
1713 transfer_info->num_files ++;
1714 report_delete_progress (job, source_info, transfer_info);
1715 return;
1716 }
1717 }
1718
1719 if (local_skipped_file) {
1720 *skipped_file = TRUE(!(0));
1721 }
1722}
1723
1724static void
1725delete_file (CommonJob *job, GFile *file,
1726 gboolean *skipped_file,
1727 SourceInfo *source_info,
1728 TransferInfo *transfer_info,
1729 gboolean toplevel)
1730{
1731 GError *error;
1732 char *primary, *secondary, *details;
1733 int response;
1734
1735 if (should_skip_file (job, file)) {
1736 *skipped_file = TRUE(!(0));
1737 return;
1738 }
1739
1740 error = NULL((void*)0);
1741 if (g_file_delete (file, job->cancellable, &error)) {
1742 caja_file_changes_queue_file_removed (file);
1743 transfer_info->num_files ++;
1744 report_delete_progress (job, source_info, transfer_info);
1745 return;
1746 }
1747
1748 if (IS_IO_ERROR (error, NOT_EMPTY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_EMPTY))
) {
1749 g_error_free (error);
1750 delete_dir (job, file,
1751 skipped_file,
1752 source_info, transfer_info,
1753 toplevel);
1754 return;
1755
1756 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1757 g_error_free (error);
1758
1759 } else {
1760 if (job->skip_all_error) {
1761 goto skip;
1762 }
1763 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1764 secondary = f (_("There was an error deleting %B.")dcgettext (((void*)0), "There was an error deleting %B.", 5), file);
1765 details = error->message;
1766
1767 response = run_warning (job,
1768 primary,
1769 secondary,
1770 details,
1771 (source_info->num_files - transfer_info->num_files) > 1,
1772 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
1773 NULL((void*)0));
1774
1775 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1776 abort_job (job);
1777 } else if (response == 1) { /* skip all */
1778 job->skip_all_error = TRUE(!(0));
1779 } else if (response == 2) { /* skip */
1780 /* do nothing */
1781 } else {
1782 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1782, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1783 }
1784 skip:
1785 g_error_free (error);
1786 }
1787
1788 *skipped_file = TRUE(!(0));
1789}
1790
1791static void
1792delete_files (CommonJob *job, GList *files, int *files_skipped)
1793{
1794 GList *l;
1795 SourceInfo source_info;
1796 TransferInfo transfer_info;
1797 gboolean skipped_file;
1798 GFile *file = NULL((void*)0);
1799
1800 if (job_aborted (job)) {
1801 return;
1802 }
1803
1804 scan_sources (files,
1805 &source_info,
1806 job,
1807 OP_KIND_DELETE);
1808 if (job_aborted (job)) {
1809 return;
1810 }
1811
1812 g_timer_start (job->time);
1813
1814 memset (&transfer_info, 0, sizeof (transfer_info));
1815 report_delete_progress (job, &source_info, &transfer_info);
1816
1817 for (l = files;
1818 l != NULL((void*)0) && !job_aborted (job);
1819 l = l->next) {
1820 file = l->data;
1821
1822 skipped_file = FALSE(0);
1823 delete_file (job, file,
1824 &skipped_file,
1825 &source_info, &transfer_info,
1826 TRUE(!(0)));
1827 if (skipped_file) {
1828 (*files_skipped)++;
1829 }
1830 }
1831}
1832
1833static void
1834report_trash_progress (CommonJob *job,
1835 int files_trashed,
1836 int total_files)
1837{
1838 int files_left;
1839 char *s;
1840
1841 files_left = total_files - files_trashed;
1842
1843 caja_progress_info_take_status (job->progress,
1844 f (_("Moving files to trash")dcgettext (((void*)0), "Moving files to trash", 5)));
1845
1846 s = f (ngettext ("%'d file left to trash",dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
1847 "%'d files left to trash",dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
1848 files_left)dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
,
1849 files_left);
1850 caja_progress_info_take_details (job->progress, s);
1851
1852 if (total_files != 0) {
1853 caja_progress_info_set_progress (job->progress, files_trashed, total_files);
1854 }
1855}
1856
1857
1858static void
1859trash_files (CommonJob *job, GList *files, int *files_skipped)
1860{
1861 GList *l;
1862 GFile *file;
1863 GList *to_delete;
1864 GError *error;
1865 int total_files, files_trashed;
1866 char *primary, *secondary, *details;
1867 int response;
1868
1869 guint64 mtime;
1870
1871 if (job_aborted (job)) {
1872 return;
1873 }
1874
1875 total_files = g_list_length (files);
1876 files_trashed = 0;
1877
1878 report_trash_progress (job, files_trashed, total_files);
1879
1880 to_delete = NULL((void*)0);
1881 for (l = files;
1882 l != NULL((void*)0) && !job_aborted (job);
1883 l = l->next) {
1884 caja_progress_info_get_ready (job->progress);
1885
1886 file = l->data;
1887
1888 error = NULL((void*)0);
1889
1890 mtime = caja_undostack_manager_get_file_modification_time (file);
1891
1892 if (!g_file_trash (file, job->cancellable, &error)) {
1893 if (job->skip_all_error) {
1894 (*files_skipped)++;
1895 goto skip;
1896 }
1897
1898 if (job->delete_all) {
1899 to_delete = g_list_prepend (to_delete, file);
1900 goto skip;
1901 }
1902
1903 primary = f (_("Cannot move file to trash, do you want to delete immediately?")dcgettext (((void*)0), "Cannot move file to trash, do you want to delete immediately?"
, 5)
);
1904 secondary = f (_("The file \"%B\" cannot be moved to the trash.")dcgettext (((void*)0), "The file \"%B\" cannot be moved to the trash."
, 5)
, file);
1905 details = NULL((void*)0);
1906 if (!IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
1907 details = error->message;
1908 }
1909
1910 response = run_question (job,
1911 primary,
1912 secondary,
1913 details,
1914 (total_files - files_trashed) > 1,
1915 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), DELETE_ALLdcgettext (((void*)0), "Delete _All", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1916 NULL((void*)0));
1917
1918 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1919 ((DeleteJob *) job)->user_cancel = TRUE(!(0));
1920 abort_job (job);
1921 } else if (response == 1) { /* skip all */
1922 (*files_skipped)++;
1923 job->skip_all_error = TRUE(!(0));
1924 } else if (response == 2) { /* skip */
1925 (*files_skipped)++;
1926 } else if (response == 3) { /* delete all */
1927 to_delete = g_list_prepend (to_delete, file);
1928 job->delete_all = TRUE(!(0));
1929 } else if (response == 4) { /* delete */
1930 to_delete = g_list_prepend (to_delete, file);
1931 }
1932
1933 skip:
1934 g_error_free (error);
1935 total_files--;
1936 } else {
1937 caja_file_changes_queue_file_removed (file);
1938
1939 // Start UNDO-REDO
1940 caja_undostack_manager_data_add_trashed_file (job->undo_redo_data, file, mtime);
1941 // End UNDO-REDO
1942
1943 files_trashed++;
1944 report_trash_progress (job, files_trashed, total_files);
1945 }
1946 }
1947
1948 if (to_delete) {
1949 to_delete = g_list_reverse (to_delete);
1950 delete_files (job, to_delete, files_skipped);
1951 g_list_free (to_delete);
1952 }
1953}
1954
1955static gboolean
1956delete_job_done (gpointer user_data)
1957{
1958 DeleteJob *job;
1959
1960 job = user_data;
1961
1962 g_list_free_full (job->files, g_object_unref);
1963
1964 if (job->done_callback) {
1965 GHashTable *debuting_uris;
1966
1967 debuting_uris = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1968 job->done_callback (debuting_uris, job->user_cancel, job->done_callback_data);
1969 g_hash_table_unref (debuting_uris);
1970 }
1971
1972 finalize_common ((CommonJob *)job);
1973
1974 caja_file_changes_consume_changes (TRUE(!(0)));
1975
1976 return FALSE(0);
1977}
1978
1979static gboolean
1980delete_job (GIOSchedulerJob *io_job,
1981 GCancellable *cancellable,
1982 gpointer user_data)
1983{
1984 DeleteJob *job = user_data;
1985 GList *to_trash_files;
1986 GList *to_delete_files;
1987 GList *l;
1988 gboolean confirmed;
1989 CommonJob *common;
1990 gboolean must_confirm_delete_in_trash;
1991 gboolean must_confirm_delete;
1992 gboolean must_confirm_trash;
1993 int files_skipped;
1994 GFile *file = NULL((void*)0);
1995
1996 common = (CommonJob *)job;
1997 common->io_job = io_job;
1998
1999 caja_progress_info_start (job->common.progress);
2000
2001 to_trash_files = NULL((void*)0);
2002 to_delete_files = NULL((void*)0);
2003
2004 must_confirm_delete_in_trash = FALSE(0);
2005 must_confirm_delete = FALSE(0);
2006 must_confirm_trash = FALSE(0);
2007 files_skipped = 0;
2008
2009 for (l = job->files; l != NULL((void*)0); l = l->next) {
2010 file = l->data;
2011
2012 if (job->try_trash &&
2013 g_file_has_uri_scheme (file, "trash")) {
2014 must_confirm_delete_in_trash = TRUE(!(0));
2015 to_delete_files = g_list_prepend (to_delete_files, file);
2016 } else if (can_delete_without_confirm (file)) {
2017 to_delete_files = g_list_prepend (to_delete_files, file);
2018 } else {
2019 if (job->try_trash) {
2020 must_confirm_trash = TRUE(!(0));
2021 to_trash_files = g_list_prepend (to_trash_files, file);
2022 } else {
2023 must_confirm_delete = TRUE(!(0));
2024 to_delete_files = g_list_prepend (to_delete_files, file);
2025 }
2026 }
2027 }
2028
2029 if (to_delete_files != NULL((void*)0)) {
2030 to_delete_files = g_list_reverse (to_delete_files);
2031 confirmed = TRUE(!(0));
2032 if (must_confirm_delete_in_trash) {
2033 confirmed = confirm_delete_from_trash (common, to_delete_files);
2034 } else if (must_confirm_delete) {
2035 confirmed = confirm_delete_directly (common, to_delete_files);
2036 }
2037 if (confirmed) {
2038 delete_files (common, to_delete_files, &files_skipped);
2039 } else {
2040 job->user_cancel = TRUE(!(0));
2041 }
2042 }
2043
2044 if (to_trash_files != NULL((void*)0)) {
2045 to_trash_files = g_list_reverse (to_trash_files);
2046
2047 if (! must_confirm_trash || confirm_trash (common, to_trash_files)) {
2048 trash_files (common, to_trash_files, &files_skipped);
2049 } else {
2050 job->user_cancel = TRUE(!(0));
2051 }
2052 }
2053
2054 g_list_free (to_trash_files);
2055 g_list_free (to_delete_files);
2056
2057 if (files_skipped == g_list_length (job->files)) {
2058 /* User has skipped all files, report user cancel */
2059 job->user_cancel = TRUE(!(0));
2060 }
2061
2062 g_io_scheduler_job_send_to_mainloop_async (io_job,
2063 delete_job_done,
2064 job,
2065 NULL((void*)0));
2066
2067 return FALSE(0);
2068}
2069
2070static void
2071trash_or_delete_internal (GList *files,
2072 GtkWindow *parent_window,
2073 gboolean try_trash,
2074 CajaDeleteCallback done_callback,
2075 gpointer done_callback_data)
2076{
2077 DeleteJob *job;
2078
2079 /* TODO: special case desktop icon link files ... */
2080
2081 job = op_job_new (DeleteJob, parent_window, TRUE, FALSE)((DeleteJob *)(init_common (sizeof(DeleteJob), parent_window,
(!(0)), (0))))
;
2082 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
2083 job->try_trash = try_trash;
2084 job->user_cancel = FALSE(0);
2085 job->done_callback = done_callback;
2086 job->done_callback_data = done_callback_data;
2087
2088 if (try_trash) {
2089 inhibit_power_manager ((CommonJob *)job, _("Trashing Files")dcgettext (((void*)0), "Trashing Files", 5));
2090 } else {
2091 inhibit_power_manager ((CommonJob *)job, _("Deleting Files")dcgettext (((void*)0), "Deleting Files", 5));
2092 }
2093 // Start UNDO-REDO
2094 // FIXME: Disabled, because of missing mechanism to restore a file from trash in a clean way
2095 // see https://www.mail-archive.com/nautilus-list@gnome.org/msg04664.html
2096 if (try_trash && !caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
2097 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_MOVETOTRASH, g_list_length(files));
2098 GFile* src_dir = g_file_get_parent (files->data);
2099 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
2100 }
2101 // End UNDO-REDO
2102
2103 g_io_scheduler_push_job (delete_job,
2104 job,
2105 NULL((void*)0),
2106 0,
2107 NULL((void*)0));
2108}
2109
2110void
2111caja_file_operations_trash_or_delete (GList *files,
2112 GtkWindow *parent_window,
2113 CajaDeleteCallback done_callback,
2114 gpointer done_callback_data)
2115{
2116 trash_or_delete_internal (files, parent_window,
2117 TRUE(!(0)),
2118 done_callback, done_callback_data);
2119}
2120
2121void
2122caja_file_operations_delete (GList *files,
2123 GtkWindow *parent_window,
2124 CajaDeleteCallback done_callback,
2125 gpointer done_callback_data)
2126{
2127 trash_or_delete_internal (files, parent_window,
2128 FALSE(0),
2129 done_callback, done_callback_data);
2130}
2131
2132
2133
2134typedef struct {
2135 gboolean eject;
2136 GMount *mount;
2137 GtkWindow *parent_window;
2138 CajaUnmountCallback callback;
2139 gpointer callback_data;
2140} UnmountData;
2141
2142static void
2143unmount_mount_callback (GObject *source_object,
2144 GAsyncResult *res,
2145 gpointer user_data)
2146{
2147 UnmountData *data = user_data;
2148 GError *error;
2149 gboolean unmounted;
2150
2151 error = NULL((void*)0);
2152 if (data->eject) {
2153 unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object)((((GMount*) (void *) ((source_object))))),
2154 res, &error);
2155 if ((!error) || (unmounted == TRUE(!(0)))){
2156 caja_application_notify_unmount_show (_("It is now safe to remove the drive")dcgettext (((void*)0), "It is now safe to remove the drive", 5
)
);
2157 }
2158
2159 } else {
2160 unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object)((((GMount*) (void *) ((source_object))))),
2161 res, &error);
2162 }
2163
2164 if (! unmounted) {
2165 if (error && error->code != G_IO_ERROR_FAILED_HANDLED) {
2166 char *primary;
2167
2168 if (data->eject) {
2169 primary = f (_("Unable to eject %V")dcgettext (((void*)0), "Unable to eject %V", 5), source_object);
2170 } else {
2171 primary = f (_("Unable to unmount %V")dcgettext (((void*)0), "Unable to unmount %V", 5), source_object);
2172 }
2173 eel_show_error_dialog (primary,
2174 error->message,
2175 data->parent_window);
2176 g_free (primary);
2177 }
2178 }
2179
2180 if (data->callback) {
2181 data->callback (data->callback_data);
2182 }
2183
2184 if (error != NULL((void*)0)) {
2185 g_error_free (error);
2186 }
2187
2188 eel_remove_weak_pointer (&data->parent_window);
2189 g_object_unref (data->mount);
2190 g_free (data);
2191}
2192
2193static void
2194do_unmount (UnmountData *data)
2195{
2196 GMountOperation *mount_op;
2197
2198 mount_op = gtk_mount_operation_new (data->parent_window);
2199 if (data->eject) {
2200 g_mount_eject_with_operation (data->mount,
2201 0,
2202 mount_op,
2203 NULL((void*)0),
2204 unmount_mount_callback,
2205 data);
2206
2207 caja_application_notify_unmount_show (_("Writing data to the drive -- do not unplug")dcgettext (((void*)0), "Writing data to the drive -- do not unplug"
, 5)
);
2208
2209 } else {
2210 g_mount_unmount_with_operation (data->mount,
2211 0,
2212 mount_op,
2213 NULL((void*)0),
2214 unmount_mount_callback,
2215 data);
2216 }
2217 g_object_unref (mount_op);
2218}
2219
2220static gboolean
2221dir_has_files (GFile *dir)
2222{
2223 GFileEnumerator *enumerator;
2224 gboolean res;
2225
2226 res = FALSE(0);
2227
2228 enumerator = g_file_enumerate_children (dir,
2229 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
2230 0,
2231 NULL((void*)0), NULL((void*)0));
2232 if (enumerator) {
2233 GFileInfo *file_info;
2234
2235 file_info = g_file_enumerator_next_file (enumerator, NULL((void*)0), NULL((void*)0));
2236 if (file_info != NULL((void*)0)) {
2237 res = TRUE(!(0));
2238 g_object_unref (file_info);
2239 }
2240
2241 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2242 g_object_unref (enumerator);
2243 }
2244
2245
2246 return res;
2247}
2248
2249static GList *
2250get_trash_dirs_for_mount (GMount *mount)
2251{
2252 GFile *root;
2253 GList *list;
2254
2255 root = g_mount_get_root (mount);
2256 if (root == NULL((void*)0)) {
2257 return NULL((void*)0);
2258 }
2259
2260 list = NULL((void*)0);
2261
2262 if (g_file_is_native (root)) {
2263 GFile *trash;
2264 char *relpath;
2265
2266 relpath = g_strdup_printf (".Trash/%d", getuid ());
2267 trash = g_file_resolve_relative_path (root, relpath);
2268 g_free (relpath);
2269
2270 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2271 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2272
2273 g_object_unref (trash);
2274
2275 relpath = g_strdup_printf (".Trash-%d", getuid ());
2276 trash = g_file_get_child (root, relpath);
2277 g_free (relpath);
2278
2279 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2280 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2281
2282 g_object_unref (trash);
2283 }
2284
2285 g_object_unref (root);
2286
2287 return list;
2288}
2289
2290static gboolean
2291has_trash_files (GMount *mount)
2292{
2293 gboolean res;
2294 GList *dirs, *l;
2295 GFile *dir = NULL((void*)0);
2296
2297 dirs = get_trash_dirs_for_mount (mount);
2298
2299 res = FALSE(0);
2300
2301 for (l = dirs; l != NULL((void*)0); l = l->next) {
2302 dir = l->data;
2303
2304 if (dir_has_files (dir)) {
2305 res = TRUE(!(0));
2306 break;
2307 }
2308 }
2309
2310 g_list_free_full (dirs, g_object_unref);
2311
2312 return res;
2313}
2314
2315
2316static gint
2317prompt_empty_trash (GtkWindow *parent_window)
2318{
2319 gint result;
2320 GtkWidget *dialog;
2321 GdkScreen *screen;
2322
2323 screen = NULL((void*)0);
2324 if (parent_window != NULL((void*)0)) {
2325 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) (void *) ((parent_window))))));
2326 }
2327
2328 /* Do we need to be modal ? */
2329 dialog = gtk_message_dialog_new (NULL((void*)0), GTK_DIALOG_MODAL,
2330 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
2331 _("Do you want to empty the trash before you unmount?")dcgettext (((void*)0), "Do you want to empty the trash before you unmount?"
, 5)
);
2332 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
2333 _("In order to regain the "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2334 "free space on this volume "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2335 "the trash must be emptied. "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2336 "All trashed items on the volume "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2337 "will be permanently lost.")dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
);
2338
2339 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2340 _("Do _not Empty Trash")dcgettext (((void*)0), "Do _not Empty Trash", 5), GTK_RESPONSE_REJECT);
2341
2342 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2343 CANCELdcgettext (((void*)0), "_Cancel", 5), "process-stop", GTK_RESPONSE_CANCEL);
2344
2345 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2346 _("Empty _Trash")dcgettext (((void*)0), "Empty _Trash", 5), GTK_RESPONSE_ACCEPT);
2347
2348 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_ACCEPT);
2349 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), ""); /* as per HIG */
2350 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
2351 if (screen) {
2352 gtk_window_set_screen (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), screen);
2353 }
2354 atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
2355
2356 /* Make transient for the window group */
2357 gtk_widget_realize (dialog);
2358 if (screen != NULL((void*)0)) {
2359 gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog)))))),
2360 gdk_screen_get_root_window (screen));
2361 }
2362
2363 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
2364 gtk_widget_destroy (dialog);
2365 return result;
2366}
2367
2368void
2369caja_file_operations_unmount_mount_full (GtkWindow *parent_window,
2370 GMount *mount,
2371 gboolean eject,
2372 gboolean check_trash,
2373 CajaUnmountCallback callback,
2374 gpointer callback_data)
2375{
2376 UnmountData *data;
2377
2378 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
2379 data->callback = callback;
2380 data->callback_data = callback_data;
2381 if (parent_window) {
2382 data->parent_window = parent_window;
2383 eel_add_weak_pointer (&data->parent_window);
2384
2385 }
2386 data->eject = eject;
2387 data->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
2388
2389 if (check_trash && has_trash_files (mount)) {
2390 int response;
2391
2392 response = prompt_empty_trash (parent_window);
2393
2394 if (response == GTK_RESPONSE_ACCEPT) {
2395 EmptyTrashJob *job;
2396
2397 job = op_job_new (EmptyTrashJob, parent_window, TRUE, FALSE)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
, (!(0)), (0))))
;
2398 job->should_confirm = FALSE(0);
2399 job->trash_dirs = get_trash_dirs_for_mount (mount);
2400 job->done_callback = (CajaOpCallback)do_unmount;
2401 job->done_callback_data = data;
2402 g_io_scheduler_push_job (empty_trash_job,
2403 job,
2404 NULL((void*)0),
2405 0,
2406 NULL((void*)0));
2407 return;
2408 } else if (response == GTK_RESPONSE_CANCEL) {
2409 if (callback) {
2410 callback (callback_data);
2411 }
2412 eel_remove_weak_pointer (&data->parent_window);
2413 g_object_unref (data->mount);
2414 g_free (data);
2415 return;
2416 }
2417 }
2418
2419 do_unmount (data);
2420}
2421
2422void
2423caja_file_operations_unmount_mount (GtkWindow *parent_window,
2424 GMount *mount,
2425 gboolean eject,
2426 gboolean check_trash)
2427{
2428 caja_file_operations_unmount_mount_full (parent_window, mount, eject,
2429 check_trash, NULL((void*)0), NULL((void*)0));
2430}
2431
2432static void
2433mount_callback_data_notify (gpointer data,
2434 GObject *object)
2435{
2436 GMountOperation *mount_op;
2437
2438 mount_op = G_MOUNT_OPERATION (data)((((GMountOperation*) (void *) ((data)))));
2439 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback", NULL((void*)0));
2440 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback-data", NULL((void*)0));
2441}
2442
2443static void
2444volume_mount_cb (GObject *source_object,
2445 GAsyncResult *res,
2446 gpointer user_data)
2447{
2448 CajaMountCallback mount_callback;
2449 GObject *mount_callback_data_object;
2450 GMountOperation *mount_op = user_data;
2451 GError *error;
2452
2453 error = NULL((void*)0);
2454 caja_allow_autorun_for_volume_finish (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))));
2455 if (!g_volume_mount_finish (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))), res, &error)) {
2456 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2457 char *name;
2458 char *primary;
2459
2460 name = g_volume_get_name (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))));
2461 primary = g_strdup_printf (_("Unable to mount %s")dcgettext (((void*)0), "Unable to mount %s", 5), name);
2462 g_free (name);
2463 eel_show_error_dialog (primary,
2464 error->message,
2465 NULL((void*)0));
2466 g_free (primary);
2467 }
2468 g_error_free (error);
2469 }
2470
2471 mount_callback = (CajaMountCallback)
2472 g_object_get_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback");
2473 mount_callback_data_object =
2474 g_object_get_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback-data");
2475
2476 if (mount_callback != NULL((void*)0)) {
2477 (* mount_callback) (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))),
2478 mount_callback_data_object);
2479
2480 if (mount_callback_data_object != NULL((void*)0)) {
2481 g_object_weak_unref (mount_callback_data_object,
2482 mount_callback_data_notify,
2483 mount_op);
2484 }
2485 }
2486
2487 g_object_unref (mount_op);
2488}
2489
2490
2491void
2492caja_file_operations_mount_volume (GtkWindow *parent_window,
2493 GVolume *volume,
2494 gboolean allow_autorun)
2495{
2496 caja_file_operations_mount_volume_full (parent_window, volume,
2497 allow_autorun, NULL((void*)0), NULL((void*)0));
2498}
2499
2500void
2501caja_file_operations_mount_volume_full (GtkWindow *parent_window,
2502 GVolume *volume,
2503 gboolean allow_autorun,
2504 CajaMountCallback mount_callback,
2505 GObject *mount_callback_data_object)
2506{
2507 GMountOperation *mount_op;
2508
2509 mount_op = gtk_mount_operation_new (parent_window);
2510 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2511 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))),
2512 "mount-callback",
2513 mount_callback);
2514
2515 if (mount_callback != NULL((void*)0) &&
2516 mount_callback_data_object != NULL((void*)0)) {
2517 g_object_weak_ref (mount_callback_data_object,
2518 mount_callback_data_notify,
2519 mount_op);
2520 }
2521 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))),
2522 "mount-callback-data",
2523 mount_callback_data_object);
2524
2525 if (allow_autorun)
2526 caja_allow_autorun_for_volume (volume);
2527 g_volume_mount (volume, 0, mount_op, NULL((void*)0), volume_mount_cb, mount_op);
2528}
2529
2530static void
2531report_count_progress (CommonJob *job,
2532 SourceInfo *source_info)
2533{
2534 char *s;
2535
2536 switch (source_info->op) {
2537 default:
2538 case OP_KIND_COPY:
2539 s = f (ngettext("Preparing to copy %'d file (%S)",dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
2540 "Preparing to copy %'d files (%S)",dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
2541 source_info->num_files)dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
,
2542 source_info->num_files, source_info->num_bytes);
2543 break;
2544 case OP_KIND_MOVE:
2545 s = f (ngettext("Preparing to move %'d file (%S)",dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
2546 "Preparing to move %'d files (%S)",dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
2547 source_info->num_files)dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
,
2548 source_info->num_files, source_info->num_bytes);
2549 break;
2550 case OP_KIND_DELETE:
2551 s = f (ngettext("Preparing to delete %'d file (%S)",dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
2552 "Preparing to delete %'d files (%S)",dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
2553 source_info->num_files)dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
,
2554 source_info->num_files, source_info->num_bytes);
2555 break;
2556 case OP_KIND_TRASH:
2557 s = f (ngettext("Preparing to trash %'d file",dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
2558 "Preparing to trash %'d files",dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
2559 source_info->num_files)dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
,
2560 source_info->num_files);
2561 break;
2562 }
2563
2564 caja_progress_info_take_details (job->progress, s);
2565 caja_progress_info_pulse_progress (job->progress);
2566}
2567
2568static void
2569count_file (GFileInfo *info,
2570 CommonJob *job,
2571 SourceInfo *source_info)
2572{
2573 source_info->num_files += 1;
2574 source_info->num_bytes += g_file_info_get_size (info);
2575
2576 if (source_info->num_files_since_progress++ > 100) {
2577 report_count_progress (job, source_info);
2578 source_info->num_files_since_progress = 0;
2579 }
2580}
2581
2582static char *
2583get_scan_primary (OpKind kind)
2584{
2585 switch (kind) {
2586 default:
2587 case OP_KIND_COPY:
2588 return f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
2589 case OP_KIND_MOVE:
2590 return f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
2591 case OP_KIND_DELETE:
2592 return f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
2593 case OP_KIND_TRASH:
2594 return f (_("Error while moving files to trash.")dcgettext (((void*)0), "Error while moving files to trash.", 5
)
);
2595 }
2596}
2597
2598static void
2599scan_dir (GFile *dir,
2600 SourceInfo *source_info,
2601 CommonJob *job,
2602 GQueue *dirs)
2603{
2604 GFileInfo *info;
2605 GError *error;
2606 GFile *subdir;
2607 GFileEnumerator *enumerator;
2608 char *primary, *secondary, *details;
2609 int response;
2610 SourceInfo saved_info;
2611
2612 saved_info = *source_info;
2613
2614 retry:
2615 error = NULL((void*)0);
2616 enumerator = g_file_enumerate_children (dir,
2617 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
2618 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2619 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size"","
2620 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size",
2621 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2622 job->cancellable,
2623 &error);
2624 if (enumerator) {
2625 error = NULL((void*)0);
2626 while ((info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
2627 count_file (info, job, source_info);
2628
2629 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2630 subdir = g_file_get_child (dir,
2631 g_file_info_get_name (info));
2632
2633 /* Push to head, since we want depth-first */
2634 g_queue_push_head (dirs, subdir);
2635 }
2636
2637 g_object_unref (info);
2638 }
2639 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
2640 g_object_unref (enumerator);
2641
2642 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2643 g_error_free (error);
2644 } else if (error) {
2645 primary = get_scan_primary (source_info->op);
2646 details = NULL((void*)0);
2647
2648 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2649 secondary = f (_("Files in the folder \"%B\" cannot be handled because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be handled because you do "
"not have permissions to see them.", 5)
2650 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be handled because you do "
"not have permissions to see them.", 5)
, dir);
2651 } else {
2652 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, dir);
2653 details = error->message;
2654 }
2655
2656 response = run_warning (job,
2657 primary,
2658 secondary,
2659 details,
2660 FALSE(0),
2661 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
2662 NULL((void*)0));
2663
2664 g_error_free (error);
2665
2666 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2667 abort_job (job);
2668 } else if (response == 1) {
2669 *source_info = saved_info;
2670 goto retry;
2671 } else if (response == 2) {
2672 skip_readdir_error (job, dir);
2673 } else {
2674 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2674, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2675 }
2676 }
2677
2678 } else if (job->skip_all_error) {
2679 g_error_free (error);
2680 skip_file (job, dir);
2681 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2682 g_error_free (error);
2683 } else {
2684 primary = get_scan_primary (source_info->op);
2685 details = NULL((void*)0);
2686
2687 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2688 secondary = f (_("The folder \"%B\" cannot be handled because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
2689 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
, dir);
2690 } else {
2691 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, dir);
2692 details = error->message;
2693 }
2694 /* set show_all to TRUE here, as we don't know how many
2695 * files we'll end up processing yet.
2696 */
2697 response = run_warning (job,
2698 primary,
2699 secondary,
2700 details,
2701 TRUE(!(0)),
2702 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2703 NULL((void*)0));
2704
2705 g_error_free (error);
2706
2707 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2708 abort_job (job);
2709 } else if (response == 1 || response == 2) {
2710 if (response == 1) {
2711 job->skip_all_error = TRUE(!(0));
2712 }
2713 skip_file (job, dir);
2714 } else if (response == 3) {
2715 goto retry;
2716 } else {
2717 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2717, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2718 }
2719 }
2720}
2721
2722static void
2723scan_file (GFile *file,
2724 SourceInfo *source_info,
2725 CommonJob *job)
2726{
2727 GFileInfo *info;
2728 GError *error;
2729 GQueue *dirs;
2730 GFile *dir;
2731 char *primary;
2732 char *secondary;
2733 char *details;
2734 int response;
2735
2736 dirs = g_queue_new ();
2737
2738 retry:
2739 error = NULL((void*)0);
2740 info = g_file_query_info (file,
2741 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2742 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size"","
2743 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size",
2744 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2745 job->cancellable,
2746 &error);
2747
2748 if (info) {
2749 count_file (info, job, source_info);
2750
2751 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2752 g_queue_push_head (dirs, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)));
2753 }
2754
2755 g_object_unref (info);
2756 } else if (job->skip_all_error) {
2757 g_error_free (error);
2758 skip_file (job, file);
2759 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2760 g_error_free (error);
2761 } else {
2762 primary = get_scan_primary (source_info->op);
2763 details = NULL((void*)0);
2764
2765 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2766 secondary = f (_("The file \"%B\" cannot be handled because you do not have "dcgettext (((void*)0), "The file \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
2767 "permissions to read it.")dcgettext (((void*)0), "The file \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
, file);
2768 } else {
2769 secondary = f (_("There was an error getting information about \"%B\".")dcgettext (((void*)0), "There was an error getting information about \"%B\"."
, 5)
, file);
2770 details = error->message;
2771 }
2772 /* set show_all to TRUE here, as we don't know how many
2773 * files we'll end up processing yet.
2774 */
2775 response = run_warning (job,
2776 primary,
2777 secondary,
2778 details,
2779 TRUE(!(0)),
2780 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2781 NULL((void*)0));
2782
2783 g_error_free (error);
2784
2785 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2786 abort_job (job);
2787 } else if (response == 1 || response == 2) {
2788 if (response == 1) {
2789 job->skip_all_error = TRUE(!(0));
2790 }
2791 skip_file (job, file);
2792 } else if (response == 3) {
2793 goto retry;
2794 } else {
2795 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2795, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2796 }
2797 }
2798
2799 while (!job_aborted (job) &&
2800 (dir = g_queue_pop_head (dirs)) != NULL((void*)0)) {
2801 scan_dir (dir, source_info, job, dirs);
2802 g_object_unref (dir);
2803 }
2804
2805 /* Free all from queue if we exited early */
2806 g_queue_foreach (dirs, (GFunc)g_object_unref, NULL((void*)0));
2807 g_queue_free (dirs);
2808}
2809
2810static void
2811scan_sources (GList *files,
2812 SourceInfo *source_info,
2813 CommonJob *job,
2814 OpKind kind)
2815{
2816 GList *l;
2817 GFile *file = NULL((void*)0);
2818
2819 memset (source_info, 0, sizeof (SourceInfo));
2820 source_info->op = kind;
2821
2822 report_count_progress (job, source_info);
2823
2824 for (l = files; l != NULL((void*)0) && !job_aborted (job); l = l->next) {
2825 file = l->data;
2826
2827 scan_file (file,
2828 source_info,
2829 job);
2830 }
2831
2832 /* Make sure we report the final count */
2833 report_count_progress (job, source_info);
2834}
2835
2836static void
2837verify_destination (CommonJob *job,
2838 GFile *dest,
2839 char **dest_fs_id,
2840 goffset required_size)
2841{
2842 GFileInfo *info, *fsinfo;
2843 GError *error;
2844 guint64 free_size;
2845 char *primary, *secondary, *details;
2846 int response;
2847 GFileType file_type;
2848
2849 if (dest_fs_id) {
2850 *dest_fs_id = NULL((void*)0);
2851 }
2852
2853 retry:
2854
2855 error = NULL((void*)0);
2856 info = g_file_query_info (dest,
2857 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2858 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
2859 0,
2860 job->cancellable,
2861 &error);
2862
2863 if (info == NULL((void*)0)) {
2864 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2865 g_error_free (error);
2866 return;
2867 }
2868
2869 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2870 details = NULL((void*)0);
2871
2872 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2873 secondary = f (_("You do not have permissions to access the destination folder.")dcgettext (((void*)0), "You do not have permissions to access the destination folder."
, 5)
);
2874 } else {
2875 secondary = f (_("There was an error getting information about the destination.")dcgettext (((void*)0), "There was an error getting information about the destination."
, 5)
);
2876 details = error->message;
2877 }
2878
2879 response = run_error (job,
2880 primary,
2881 secondary,
2882 details,
2883 FALSE(0),
2884 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2885 NULL((void*)0));
2886
2887 g_error_free (error);
2888
2889 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2890 abort_job (job);
2891 } else if (response == 1) {
2892 goto retry;
2893 } else {
2894 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2894, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2895 }
2896
2897 return;
2898 }
2899
2900 file_type = g_file_info_get_file_type (info);
2901
2902 if (dest_fs_id) {
2903 *dest_fs_id =
2904 g_strdup (g_file_info_get_attribute_string (info,g_strdup_inline (g_file_info_get_attribute_string (info, "id::filesystem"
))
2905 G_FILE_ATTRIBUTE_ID_FILESYSTEM))g_strdup_inline (g_file_info_get_attribute_string (info, "id::filesystem"
))
;
2906 }
2907
2908 g_object_unref (info);
2909
2910 if (file_type != G_FILE_TYPE_DIRECTORY) {
2911 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2912 secondary = f (_("The destination is not a folder.")dcgettext (((void*)0), "The destination is not a folder.", 5));
2913
2914 response = run_error (job,
2915 primary,
2916 secondary,
2917 NULL((void*)0),
2918 FALSE(0),
2919 CANCELdcgettext (((void*)0), "_Cancel", 5),
2920 NULL((void*)0));
2921
2922 abort_job (job);
2923 return;
2924 }
2925
2926 fsinfo = g_file_query_filesystem_info (dest,
2927 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free"","
2928 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly",
2929 job->cancellable,
2930 NULL((void*)0));
2931 if (fsinfo == NULL((void*)0)) {
2932 /* All sorts of things can go wrong getting the fs info (like not supported)
2933 * only check these things if the fs returns them
2934 */
2935 return;
2936 }
2937
2938 if (required_size > 0 &&
2939 g_file_info_has_attribute (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
2940 free_size = g_file_info_get_attribute_uint64 (fsinfo,
2941 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
2942
2943 if (free_size < required_size) {
2944 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2945 secondary = f(_("There is not enough space on the destination. Try to remove files to make space.")dcgettext (((void*)0), "There is not enough space on the destination. Try to remove files to make space."
, 5)
);
2946
2947 details = f (_("There is %S available, but %S is required.")dcgettext (((void*)0), "There is %S available, but %S is required."
, 5)
, free_size, required_size);
2948
2949 response = run_warning (job,
2950 primary,
2951 secondary,
2952 details,
2953 FALSE(0),
2954 CANCELdcgettext (((void*)0), "_Cancel", 5),
2955 COPY_FORCEdcgettext (((void*)0), "Copy _Anyway", 5),
2956 RETRYdcgettext (((void*)0), "_Retry", 5),
2957 NULL((void*)0));
2958
2959 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2960 abort_job (job);
2961 } else if (response == 2) {
2962 goto retry;
2963 } else if (response == 1) {
2964 /* We are forced to copy - just fall through ... */
2965 } else {
2966 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2966, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2967 }
2968 }
2969 }
2970
2971 if (!job_aborted (job) &&
2972 g_file_info_get_attribute_boolean (fsinfo,
2973 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly")) {
2974 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2975 secondary = f (_("The destination is read-only.")dcgettext (((void*)0), "The destination is read-only.", 5));
2976
2977 response = run_error (job,
2978 primary,
2979 secondary,
2980 NULL((void*)0),
2981 FALSE(0),
2982 CANCELdcgettext (((void*)0), "_Cancel", 5),
2983 NULL((void*)0));
2984
2985 g_error_free (error);
2986
2987 abort_job (job);
2988 }
2989
2990 g_object_unref (fsinfo);
2991}
2992
2993static void
2994report_copy_progress (CopyMoveJob *copy_job,
2995 SourceInfo *source_info,
2996 TransferInfo *transfer_info)
2997{
2998 int files_left;
2999 goffset total_size;
3000 double elapsed, transfer_rate;
3001 guint64 now;
3002 CommonJob *job;
3003 gboolean is_move;
3004
3005 job = (CommonJob *)copy_job;
3006
3007 is_move = copy_job->is_move;
3008
3009 now = g_get_monotonic_time ();
3010
3011 if (transfer_info->last_report_time != 0 &&
3012 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
3013 return;
3014 }
3015 transfer_info->last_report_time = now;
3016
3017 files_left = source_info->num_files - transfer_info->num_files;
3018
3019 /* Races and whatnot could cause this to be negative... */
3020 if (files_left < 0) {
3021 files_left = 1;
3022 }
3023
3024 if (files_left != transfer_info->last_reported_files_left ||
3025 transfer_info->last_reported_files_left == 0) {
3026 /* Avoid changing this unless files_left changed since last time */
3027 transfer_info->last_reported_files_left = files_left;
3028
3029 if (source_info->num_files == 1) {
3030 if (copy_job->destination != NULL((void*)0)) {
3031 caja_progress_info_take_status (job->progress,
3032 f (is_move ?
3033 _("Moving \"%B\" to \"%B\"")dcgettext (((void*)0), "Moving \"%B\" to \"%B\"", 5):
3034 _("Copying \"%B\" to \"%B\"")dcgettext (((void*)0), "Copying \"%B\" to \"%B\"", 5),
3035 (GFile *)copy_job->files->data,
3036 copy_job->destination));
3037 } else {
3038 caja_progress_info_take_status (job->progress,
3039 f (_("Duplicating \"%B\"")dcgettext (((void*)0), "Duplicating \"%B\"", 5),
3040 (GFile *)copy_job->files->data));
3041 }
3042 } else if (copy_job->files != NULL((void*)0) &&
3043 copy_job->files->next == NULL((void*)0)) {
3044 if (copy_job->destination != NULL((void*)0)) {
3045 caja_progress_info_take_status (job->progress,
3046 f (is_move?
3047 ngettext ("Moving %'d file (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3048 "Moving %'d files (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3049 files_left)dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3050 :
3051 ngettext ("Copying %'d file (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
3052 "Copying %'d files (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
3053 files_left)dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
,
3054 files_left,
3055 (GFile *)copy_job->files->data,
3056 copy_job->destination));
3057 } else {
3058 caja_progress_info_take_status (job->progress,
3059 f (ngettext ("Duplicating %'d file (in \"%B\")",dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
3060 "Duplicating %'d files (in \"%B\")",dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
3061 files_left)dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
,
3062 files_left,
3063 (GFile *)copy_job->files->data));
3064 }
3065 } else {
3066 if (copy_job->destination != NULL((void*)0)) {
3067 caja_progress_info_take_status (job->progress,
3068 f (is_move?
3069 ngettext ("Moving %'d file to \"%B\"",dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3070 "Moving %'d files to \"%B\"",dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3071 files_left)dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3072 :
3073 ngettext ("Copying %'d file to \"%B\"",dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
3074 "Copying %'d files to \"%B\"",dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
3075 files_left)dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
,
3076 files_left, copy_job->destination));
3077 } else {
3078 caja_progress_info_take_status (job->progress,
3079 f (ngettext ("Duplicating %'d file",dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
3080 "Duplicating %'d files",dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
3081 files_left)dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
,
3082 files_left));
3083 }
3084 }
3085 }
3086
3087 total_size = MAX (source_info->num_bytes, transfer_info->num_bytes)(((source_info->num_bytes) > (transfer_info->num_bytes
)) ? (source_info->num_bytes) : (transfer_info->num_bytes
))
;
3088
3089 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
3090 transfer_rate = 0;
3091 if (elapsed > 0) {
3092 transfer_rate = transfer_info->num_bytes / elapsed;
3093 }
3094
3095 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15 &&
3096 transfer_rate > 0) {
3097 char *s;
3098 /* Translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */
3099 s = f (_("%S of %S")dcgettext (((void*)0), "%S of %S", 5), transfer_info->num_bytes, total_size);
3100 caja_progress_info_take_details (job->progress, s);
3101 } else {
3102 int remaining_time;
3103 char *s;
3104
3105 remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate;
3106
3107 /* Translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like
3108 * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)"
3109 *
3110 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
3111 */
3112 s = f (ngettext ("%S of %S \xE2\x80\x94 %T left (%S/sec)",dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
3113 "%S of %S \xE2\x80\x94 %T left (%S/sec)",dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
3114 seconds_count_format_time_units (remaining_time))dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
,
3115 transfer_info->num_bytes, total_size,
3116 remaining_time,
3117 (goffset)transfer_rate);
3118 caja_progress_info_take_details (job->progress, s);
3119 }
3120
3121 caja_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size);
3122}
3123
3124static int
3125get_max_name_length (GFile *file_dir)
3126{
3127 int max_length;
3128 char *dir;
3129 long max_path;
3130 long max_name;
3131
3132 max_length = -1;
3133
3134 if (!g_file_has_uri_scheme (file_dir, "file"))
3135 return max_length;
3136
3137 dir = g_file_get_path (file_dir);
3138 if (!dir)
3139 return max_length;
3140
3141 max_path = pathconf (dir, _PC_PATH_MAX_PC_PATH_MAX);
3142 max_name = pathconf (dir, _PC_NAME_MAX_PC_NAME_MAX);
3143
3144 if (max_name == -1 && max_path == -1) {
3145 max_length = -1;
3146 } else if (max_name == -1 && max_path != -1) {
3147 max_length = max_path - (strlen (dir) + 1);
3148 } else if (max_name != -1 && max_path == -1) {
3149 max_length = max_name;
3150 } else {
3151 int leftover;
3152
3153 leftover = max_path - (strlen (dir) + 1);
3154
3155 max_length = MIN (leftover, max_name)(((leftover) < (max_name)) ? (leftover) : (max_name));
3156 }
3157
3158 g_free (dir);
3159
3160 return max_length;
3161}
3162
3163#define FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>" "/:;*?\"<>"
3164
3165static gboolean
3166str_replace (char *str,
3167 const char *chars_to_replace,
3168 char replacement)
3169{
3170 gboolean success;
3171 int i;
3172
3173 success = FALSE(0);
3174 for (i = 0; str[i] != '\0'; i++) {
3175 if (strchr (chars_to_replace, str[i])) {
3176 success = TRUE(!(0));
3177 str[i] = replacement;
3178 }
3179 }
3180
3181 return success;
3182}
3183
3184static gboolean
3185make_file_name_valid_for_dest_fs (char *filename,
3186 const char *dest_fs_type)
3187{
3188 if (dest_fs_type != NULL((void*)0) && filename != NULL((void*)0)) {
3189 if (!strcmp (dest_fs_type, "fat") ||
3190 !strcmp (dest_fs_type, "vfat") ||
3191 !strcmp (dest_fs_type, "msdos") ||
3192 !strcmp (dest_fs_type, "msdosfs")) {
3193 gboolean ret;
3194 int i, old_len;
3195
3196 ret = str_replace (filename, FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>", '_');
3197
3198 old_len = strlen (filename);
3199 for (i = 0; i < old_len; i++) {
3200 if (filename[i] != ' ') {
3201 g_strchomp (filename);
3202 ret |= (old_len != strlen (filename));
3203 break;
3204 }
3205 }
3206
3207 return ret;
3208 }
3209 }
3210
3211 return FALSE(0);
3212}
3213
3214static GFile *
3215get_unique_target_file (GFile *src,
3216 GFile *dest_dir,
3217 gboolean same_fs,
3218 const char *dest_fs_type,
3219 int count)
3220{
3221 char *new_name;
3222 GFileInfo *info;
3223 GFile *dest;
3224 int max_length;
3225
3226 max_length = get_max_name_length (dest_dir);
3227
3228 dest = NULL((void*)0);
3229 info = g_file_query_info (src,
3230 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3231 0, NULL((void*)0), NULL((void*)0));
3232 if (info != NULL((void*)0)) {
3233 const char *editname;
3234
3235 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3236
3237 if (editname != NULL((void*)0)) {
3238 new_name = get_duplicate_name (editname, count, max_length);
3239 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3240 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3241 g_free (new_name);
3242 }
3243
3244 g_object_unref (info);
3245 }
3246
3247 if (dest == NULL((void*)0)) {
3248 char *basename;
3249
3250 basename = g_file_get_basename (src);
3251
3252 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3253 new_name = get_duplicate_name (basename, count, max_length);
3254 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3255 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3256 g_free (new_name);
3257 }
3258
3259 if (dest == NULL((void*)0)) {
3260 const char *end;
3261
3262 end = strrchr (basename, '.');
3263 if (end != NULL((void*)0)) {
3264 count += atoi (end + 1);
3265 }
3266 new_name = g_strdup_printf ("%s.%d", basename, count);
3267 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3268 dest = g_file_get_child (dest_dir, new_name);
3269 g_free (new_name);
3270 }
3271
3272 g_free (basename);
3273 }
3274
3275 return dest;
3276}
3277
3278static GFile *
3279get_target_file_for_link (GFile *src,
3280 GFile *dest_dir,
3281 const char *dest_fs_type,
3282 int count)
3283{
3284 char *new_name;
3285 GFileInfo *info;
3286 GFile *dest;
3287 int max_length;
3288
3289 max_length = get_max_name_length (dest_dir);
3290
3291 dest = NULL((void*)0);
3292 info = g_file_query_info (src,
3293 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3294 0, NULL((void*)0), NULL((void*)0));
3295 if (info != NULL((void*)0)) {
3296 const char *editname;
3297
3298 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3299
3300 if (editname != NULL((void*)0)) {
3301 new_name = get_link_name (editname, count, max_length);
3302 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3303 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3304 g_free (new_name);
3305 }
3306
3307 g_object_unref (info);
3308 }
3309
3310 if (dest == NULL((void*)0)) {
3311 char *basename;
3312
3313 basename = g_file_get_basename (src);
3314 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3315
3316 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3317 new_name = get_link_name (basename, count, max_length);
3318 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3319 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3320 g_free (new_name);
3321 }
3322
3323 if (dest == NULL((void*)0)) {
3324 if (count == 1) {
3325 new_name = g_strdup_printf ("%s.lnk", basename);
3326 } else {
3327 new_name = g_strdup_printf ("%s.lnk%d", basename, count);
3328 }
3329 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3330 dest = g_file_get_child (dest_dir, new_name);
3331 g_free (new_name);
3332 }
3333
3334 g_free (basename);
3335 }
3336
3337 return dest;
3338}
3339
3340static GFile *
3341get_target_file (GFile *src,
3342 GFile *dest_dir,
3343 const char *dest_fs_type,
3344 gboolean same_fs)
3345{
3346 GFile *dest;
3347
3348 dest = NULL((void*)0);
3349 if (!same_fs) {
3350 GFileInfo *info;
3351
3352 info = g_file_query_info (src,
3353 G_FILE_ATTRIBUTE_STANDARD_COPY_NAME"standard::copy-name",
3354 0, NULL((void*)0), NULL((void*)0));
3355
3356 if (info) {
3357 char *copyname;
3358
3359 copyname = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME))g_strdup_inline (g_file_info_get_attribute_string (info, "standard::copy-name"
))
;
3360
3361 if (copyname) {
3362 make_file_name_valid_for_dest_fs (copyname, dest_fs_type);
3363 dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL((void*)0));
3364 g_free (copyname);
3365 }
3366
3367 g_object_unref (info);
3368 }
3369 }
3370
3371 if (dest == NULL((void*)0)) {
3372 char *basename;
3373
3374 basename = g_file_get_basename (src);
3375 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3376 dest = g_file_get_child (dest_dir, basename);
3377 g_free (basename);
3378 }
3379
3380 return dest;
3381}
3382
3383static gboolean
3384has_fs_id (GFile *file, const char *fs_id)
3385{
3386 GFileInfo *info;
3387 gboolean res;
3388
3389 res = FALSE(0);
3390 info = g_file_query_info (file,
3391 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
3392 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3393 NULL((void*)0), NULL((void*)0));
3394
3395 if (info) {
3396 const char *id;
3397
3398 id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
3399
3400 if (id && strcmp (id, fs_id) == 0) {
3401 res = TRUE(!(0));
3402 }
3403
3404 g_object_unref (info);
3405 }
3406
3407 return res;
3408}
3409
3410static gboolean
3411is_dir (GFile *file)
3412{
3413 GFileInfo *info;
3414 gboolean res;
3415
3416 res = FALSE(0);
3417 info = g_file_query_info (file,
3418 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
3419 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3420 NULL((void*)0), NULL((void*)0));
3421 if (info) {
3422 res = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
3423 g_object_unref (info);
3424 }
3425
3426 return res;
3427}
3428
3429static void copy_move_file (CopyMoveJob *job,
3430 GFile *src,
3431 GFile *dest_dir,
3432 gboolean same_fs,
3433 gboolean unique_names,
3434 char **dest_fs_type,
3435 SourceInfo *source_info,
3436 TransferInfo *transfer_info,
3437 GHashTable *debuting_files,
3438 GdkPoint *point,
3439 gboolean overwrite,
3440 gboolean *skipped_file,
3441 gboolean readonly_source_fs,
3442 gboolean last_item);
3443
3444typedef enum {
3445 CREATE_DEST_DIR_RETRY,
3446 CREATE_DEST_DIR_FAILED,
3447 CREATE_DEST_DIR_SUCCESS
3448} CreateDestDirResult;
3449
3450static CreateDestDirResult
3451create_dest_dir (CommonJob *job,
3452 GFile *src,
3453 GFile **dest,
3454 gboolean same_fs,
3455 char **dest_fs_type)
3456{
3457 GError *error;
3458 GFile *new_dest, *dest_dir;
3459 char *primary, *secondary, *details;
3460 int response;
3461 gboolean handled_invalid_filename;
3462
3463 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
3464
3465 retry:
3466 /* First create the directory, then copy stuff to it before
3467 copying the attributes, because we need to be sure we can write to it */
3468
3469 error = NULL((void*)0);
3470 if (!g_file_make_directory (*dest, job->cancellable, &error)) {
3471 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3472 g_error_free (error);
3473 return CREATE_DEST_DIR_FAILED;
3474 } else if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
3475 !handled_invalid_filename) {
3476 handled_invalid_filename = TRUE(!(0));
3477
3478 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_41
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_41 = 1; else
_g_boolean_var_41 = 0; _g_boolean_var_41; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 3478, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
3479
3480 dest_dir = g_file_get_parent (*dest);
3481
3482 if (dest_dir != NULL((void*)0)) {
3483 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
3484
3485 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
3486 g_object_unref (dest_dir);
3487
3488 if (!g_file_equal (*dest, new_dest)) {
3489 g_object_unref (*dest);
3490 *dest = new_dest;
3491 g_error_free (error);
3492 return CREATE_DEST_DIR_RETRY;
3493 } else {
3494 g_object_unref (new_dest);
3495 }
3496 }
3497 }
3498
3499 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3500 details = NULL((void*)0);
3501
3502 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3503 secondary = f (_("The folder \"%B\" cannot be copied because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to create it in the destination.", 5)
3504 "permissions to create it in the destination.")dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to create it in the destination.", 5)
, src);
3505 } else {
3506 secondary = f (_("There was an error creating the folder \"%B\".")dcgettext (((void*)0), "There was an error creating the folder \"%B\"."
, 5)
, src);
3507 details = error->message;
3508 }
3509
3510 response = run_warning (job,
3511 primary,
3512 secondary,
3513 details,
3514 FALSE(0),
3515 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
3516 NULL((void*)0));
3517
3518 g_error_free (error);
3519
3520 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3521 abort_job (job);
3522 } else if (response == 1) {
3523 /* Skip: Do Nothing */
3524 } else if (response == 2) {
3525 goto retry;
3526 } else {
3527 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3527, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3528 }
3529 return CREATE_DEST_DIR_FAILED;
3530 }
3531 // Start UNDO-REDO
3532 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, *dest);
3533 // End UNDO-REDO
3534 caja_file_changes_queue_file_added (*dest);
3535 return CREATE_DEST_DIR_SUCCESS;
3536}
3537
3538/* a return value of FALSE means retry, i.e.
3539 * the destination has changed and the source
3540 * is expected to re-try the preceeding
3541 * g_file_move() or g_file_copy() call with
3542 * the new destination.
3543 */
3544static gboolean
3545copy_move_directory (CopyMoveJob *copy_job,
3546 GFile *src,
3547 GFile **dest,
3548 gboolean same_fs,
3549 gboolean create_dest,
3550 char **parent_dest_fs_type,
3551 SourceInfo *source_info,
3552 TransferInfo *transfer_info,
3553 GHashTable *debuting_files,
3554 gboolean *skipped_file,
3555 gboolean readonly_source_fs,
3556 gboolean last_item_above)
3557{
3558 GFileInfo *info, *nextinfo;
3559 GError *error;
3560 GFile *src_file;
3561 GFileEnumerator *enumerator;
3562 char *primary, *secondary, *details;
3563 char *dest_fs_type;
3564 int response;
3565 gboolean skip_error;
3566 gboolean local_skipped_file;
3567 CommonJob *job;
3568 GFileCopyFlags flags;
3569 gboolean last_item;
3570
3571 job = (CommonJob *)copy_job;
3572
3573 if (create_dest) {
3574 switch (create_dest_dir (job, src, dest, same_fs, parent_dest_fs_type)) {
3575 case CREATE_DEST_DIR_RETRY:
3576 /* next time copy_move_directory() is called,
3577 * create_dest will be FALSE if a directory already
3578 * exists under the new name (i.e. WOULD_RECURSE)
3579 */
3580 return FALSE(0);
3581
3582 case CREATE_DEST_DIR_FAILED:
3583 *skipped_file = TRUE(!(0));
3584 return TRUE(!(0));
3585
3586 case CREATE_DEST_DIR_SUCCESS:
3587 default:
3588 break;
3589 }
3590
3591 if (debuting_files) {
3592 g_hash_table_replace (debuting_files, g_object_ref (*dest)((__typeof__ (*dest)) (g_object_ref) (*dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
3593 }
3594
3595 }
3596
3597 local_skipped_file = FALSE(0);
3598 dest_fs_type = NULL((void*)0);
3599
3600 skip_error = should_skip_readdir_error (job, src);
3601 retry:
3602 error = NULL((void*)0);
3603 enumerator = g_file_enumerate_children (src,
3604 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3605 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3606 job->cancellable,
3607 &error);
3608 if (enumerator) {
3609 error = NULL((void*)0);
3610
3611 nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error);
3612 while (!job_aborted (job) &&
3613 (info = nextinfo) != NULL((void*)0)) {
3614 caja_progress_info_get_ready (job->progress);
3615
3616 nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error);
3617 src_file = g_file_get_child (src,
3618 g_file_info_get_name (info));
3619
3620 last_item = (last_item_above) && (!nextinfo);
3621 copy_move_file (copy_job, src_file, *dest, same_fs, FALSE(0), &dest_fs_type,
3622 source_info, transfer_info, NULL((void*)0), NULL((void*)0), FALSE(0), &local_skipped_file,
3623 readonly_source_fs, last_item);
3624 g_object_unref (src_file);
3625 g_object_unref (info);
3626 }
3627 if (nextinfo)
3628 g_object_unref (nextinfo);
3629
3630 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3631 g_object_unref (enumerator);
3632
3633 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3634 g_error_free (error);
3635 } else if (error) {
3636 if (copy_job->is_move) {
3637 primary = f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
3638 } else {
3639 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3640 }
3641 details = NULL((void*)0);
3642
3643 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3644 secondary = f (_("Files in the folder \"%B\" cannot be copied because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be copied because you do "
"not have permissions to see them.", 5)
3645 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be copied because you do "
"not have permissions to see them.", 5)
, src);
3646 } else {
3647 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, src);
3648 details = error->message;
3649 }
3650
3651 response = run_warning (job,
3652 primary,
3653 secondary,
3654 details,
3655 FALSE(0),
3656 CANCELdcgettext (((void*)0), "_Cancel", 5), _("_Skip files")dcgettext (((void*)0), "_Skip files", 5),
3657 NULL((void*)0));
3658
3659 g_error_free (error);
3660
3661 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3662 abort_job (job);
3663 } else if (response == 1) {
3664 /* Skip: Do Nothing */
3665 local_skipped_file = TRUE(!(0));
3666 } else {
3667 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3667, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3668 }
3669 }
3670
3671 /* Count the copied directory as a file */
3672 transfer_info->num_files ++;
3673 report_copy_progress (copy_job, source_info, transfer_info);
3674
3675 if (debuting_files) {
3676 g_hash_table_replace (debuting_files, g_object_ref (*dest)((__typeof__ (*dest)) (g_object_ref) (*dest)), GINT_TO_POINTER (create_dest)((gpointer) (glong) (create_dest)));
3677 }
3678 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3679 g_error_free (error);
3680 } else {
3681 if (copy_job->is_move) {
3682 primary = f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
3683 } else {
3684 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3685 }
3686 details = NULL((void*)0);
3687
3688 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3689 secondary = f (_("The folder \"%B\" cannot be copied because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to read it.", 5)
3690 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to read it.", 5)
, src);
3691 } else {
3692 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, src);
3693 details = error->message;
3694 }
3695
3696 response = run_warning (job,
3697 primary,
3698 secondary,
3699 details,
3700 FALSE(0),
3701 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
3702 NULL((void*)0));
3703
3704 g_error_free (error);
3705
3706 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3707 abort_job (job);
3708 } else if (response == 1) {
3709 /* Skip: Do Nothing */
3710 local_skipped_file = TRUE(!(0));
3711 } else if (response == 2) {
3712 goto retry;
3713 } else {
3714 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3714, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3715 }
3716 }
3717
3718 if (create_dest) {
3719 flags = (readonly_source_fs) ? G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_PERMS
3720 : G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA;
3721 /* Ignore errors here. Failure to copy metadata is not a hard error */
3722 g_file_copy_attributes (src, *dest,
3723 flags,
3724 job->cancellable, NULL((void*)0));
3725 }
3726
3727 if (!job_aborted (job) && copy_job->is_move &&
3728 /* Don't delete source if there was a skipped file */
3729 !local_skipped_file) {
3730 if (!g_file_delete (src, job->cancellable, &error)) {
3731 if (job->skip_all_error) {
3732 goto skip;
3733 }
3734 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
3735 secondary = f (_("Could not remove the source folder.")dcgettext (((void*)0), "Could not remove the source folder.",
5)
);
3736 details = error->message;
3737
3738 response = run_warning (job,
3739 primary,
3740 secondary,
3741 details,
3742 (source_info->num_files - transfer_info->num_files) > 1,
3743 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3744 NULL((void*)0));
3745
3746 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3747 abort_job (job);
3748 } else if (response == 1) { /* skip all */
3749 job->skip_all_error = TRUE(!(0));
3750 local_skipped_file = TRUE(!(0));
3751 } else if (response == 2) { /* skip */
3752 local_skipped_file = TRUE(!(0));
3753 } else {
3754 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3754, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3755 }
3756
3757 skip:
3758 g_error_free (error);
3759 }
3760 }
3761
3762 if (local_skipped_file) {
3763 *skipped_file = TRUE(!(0));
3764 }
3765
3766 g_free (dest_fs_type);
3767 return TRUE(!(0));
3768}
3769
3770static gboolean
3771remove_target_recursively (CommonJob *job,
3772 GFile *src,
3773 GFile *toplevel_dest,
3774 GFile *file)
3775{
3776 GFileEnumerator *enumerator;
3777 GError *error;
3778 GFile *child;
3779 gboolean stop;
3780 char *primary, *secondary, *details;
3781 int response;
3782 GFileInfo *info;
3783
3784 stop = FALSE(0);
3785
3786 error = NULL((void*)0);
3787 enumerator = g_file_enumerate_children (file,
3788 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3789 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3790 job->cancellable,
3791 &error);
3792 if (enumerator) {
3793 error = NULL((void*)0);
3794
3795 while (!job_aborted (job) &&
3796 (info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
3797 child = g_file_get_child (file,
3798 g_file_info_get_name (info));
3799 if (!remove_target_recursively (job, src, toplevel_dest, child)) {
3800 stop = TRUE(!(0));
3801 break;
3802 }
3803 g_object_unref (child);
3804 g_object_unref (info);
3805 }
3806 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3807 g_object_unref (enumerator);
3808
3809 } else if (IS_IO_ERROR (error, NOT_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_DIRECTORY))
) {
3810 /* Not a dir, continue */
3811 g_error_free (error);
3812
3813 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3814 g_error_free (error);
3815 } else {
3816 if (job->skip_all_error) {
3817 goto skip1;
3818 }
3819
3820 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
3821 secondary = f (_("Could not remove files from the already existing folder %F.")dcgettext (((void*)0), "Could not remove files from the already existing folder %F."
, 5)
, file);
3822 details = error->message;
3823
3824 /* set show_all to TRUE here, as we don't know how many
3825 * files we'll end up processing yet.
3826 */
3827 response = run_warning (job,
3828 primary,
3829 secondary,
3830 details,
3831 TRUE(!(0)),
3832 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3833 NULL((void*)0));
3834
3835 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3836 abort_job (job);
3837 } else if (response == 1) { /* skip all */
3838 job->skip_all_error = TRUE(!(0));
3839 } else if (response == 2) { /* skip */
3840 /* do nothing */
3841 } else {
3842 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3842, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3843 }
3844 skip1:
3845 g_error_free (error);
3846
3847 stop = TRUE(!(0));
3848 }
3849
3850 if (stop) {
3851 return FALSE(0);
3852 }
3853
3854 error = NULL((void*)0);
3855
3856 if (!g_file_delete (file, job->cancellable, &error)) {
3857 if (job->skip_all_error ||
3858 IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3859 goto skip2;
3860 }
3861 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
3862 secondary = f (_("Could not remove the already existing file %F.")dcgettext (((void*)0), "Could not remove the already existing file %F."
, 5)
, file);
3863 details = error->message;
3864
3865 /* set show_all to TRUE here, as we don't know how many
3866 * files we'll end up processing yet.
3867 */
3868 response = run_warning (job,
3869 primary,
3870 secondary,
3871 details,
3872 TRUE(!(0)),
3873 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3874 NULL((void*)0));
3875
3876 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3877 abort_job (job);
3878 } else if (response == 1) { /* skip all */
3879 job->skip_all_error = TRUE(!(0));
3880 } else if (response == 2) { /* skip */
3881 /* do nothing */
3882 } else {
3883 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3883, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3884 }
3885
3886 skip2:
3887 g_error_free (error);
3888
3889 return FALSE(0);
3890 }
3891 caja_file_changes_queue_file_removed (file);
3892
3893 return TRUE(!(0));
3894
3895}
3896
3897typedef struct {
3898 CopyMoveJob *job;
3899 goffset last_size;
3900 SourceInfo *source_info;
3901 TransferInfo *transfer_info;
3902} ProgressData;
3903
3904static void
3905copy_file_progress_callback (goffset current_num_bytes,
3906 goffset total_num_bytes,
3907 gpointer user_data)
3908{
3909 ProgressData *pdata;
3910 goffset new_size;
3911
3912 pdata = user_data;
3913
3914 new_size = current_num_bytes - pdata->last_size;
3915
3916 if (new_size > 0) {
3917 pdata->transfer_info->num_bytes += new_size;
3918 pdata->last_size = current_num_bytes;
3919 report_copy_progress (pdata->job,
3920 pdata->source_info,
3921 pdata->transfer_info);
3922 }
3923}
3924
3925static gboolean
3926test_dir_is_parent (GFile *child, GFile *root)
3927{
3928 GFile *f;
3929
3930 f = g_file_dup (child);
3931 while (f) {
3932 if (g_file_equal (f, root)) {
3933 g_object_unref (f);
3934 return TRUE(!(0));
3935 }
3936 f = g_file_get_parent (f);
3937 }
3938 if (f) {
3939 g_object_unref (f);
3940 }
3941 return FALSE(0);
3942}
3943
3944static char *
3945query_fs_type (GFile *file,
3946 GCancellable *cancellable)
3947{
3948 GFileInfo *fsinfo;
3949 char *ret;
3950
3951 ret = NULL((void*)0);
3952
3953 fsinfo = g_file_query_filesystem_info (file,
3954 G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3955 cancellable,
3956 NULL((void*)0));
3957 if (fsinfo != NULL((void*)0)) {
3958 ret = g_strdup (g_file_info_get_attribute_string (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))g_strdup_inline (g_file_info_get_attribute_string (fsinfo, "filesystem::type"
))
;
3959 g_object_unref (fsinfo);
3960 }
3961
3962 if (ret == NULL((void*)0)) {
3963 /* ensure that we don't attempt to query
3964 * the FS type for each file in a given
3965 * directory, if it can't be queried. */
3966 ret = g_strdup ("")g_strdup_inline ("");
3967 }
3968
3969 return ret;
3970}
3971
3972static gboolean
3973is_trusted_desktop_file (GFile *file,
3974 GCancellable *cancellable)
3975{
3976 char *basename;
3977 gboolean res;
3978 GFileInfo *info;
3979
3980 /* Don't trust non-local files */
3981 if (!g_file_is_native (file)) {
3982 return FALSE(0);
3983 }
3984
3985 basename = g_file_get_basename (file);
3986 if (!g_str_has_suffix (basename, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (basename); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_42; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_42 = 1; else _g_boolean_var_42
= 0; _g_boolean_var_42; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (basename, ".desktop") )
) {
3987 g_free (basename);
3988 return FALSE(0);
3989 }
3990 g_free (basename);
3991
3992 info = g_file_query_info (file,
3993 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" ","
3994 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute",
3995 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3996 cancellable,
3997 NULL((void*)0));
3998
3999 if (info == NULL((void*)0)) {
4000 return FALSE(0);
4001 }
4002
4003 res = FALSE(0);
4004
4005 /* Weird file => not trusted,
4006 Already executable => no need to mark trusted */
4007 if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR &&
4008 !g_file_info_get_attribute_boolean (info,
4009 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute") &&
4010 caja_is_in_system_dir (file)) {
4011 res = TRUE(!(0));
4012 }
4013 g_object_unref (info);
4014
4015 return res;
4016}
4017
4018typedef struct {
4019 int id;
4020 char *new_name;
4021 gboolean apply_to_all;
4022} ConflictResponseData;
4023
4024typedef struct {
4025 GFile *src;
4026 GFile *dest;
4027 GFile *dest_dir;
4028 GtkWindow *parent;
4029 ConflictResponseData *resp_data;
4030} ConflictDialogData;
4031
4032static gboolean
4033do_run_conflict_dialog (gpointer _data)
4034{
4035 ConflictDialogData *data = _data;
4036 GtkWidget *dialog;
4037 int response;
4038
4039 dialog = caja_file_conflict_dialog_new (data->parent,
4040 data->src,
4041 data->dest,
4042 data->dest_dir);
4043 response = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
4044
4045 if (response == CONFLICT_RESPONSE_RENAME) {
4046 data->resp_data->new_name =
4047 caja_file_conflict_dialog_get_new_name (CAJA_FILE_CONFLICT_DIALOG (dialog)((((CajaFileConflictDialog*) (void *) ((dialog))))));
4048 } else if (response != GTK_RESPONSE_CANCEL ||
4049 response != GTK_RESPONSE_NONE) {
4050 data->resp_data->apply_to_all =
4051 caja_file_conflict_dialog_get_apply_to_all
4052 (CAJA_FILE_CONFLICT_DIALOG (dialog)((((CajaFileConflictDialog*) (void *) ((dialog))))));
4053 }
4054
4055 data->resp_data->id = response;
4056
4057 gtk_widget_destroy (dialog);
4058
4059 return FALSE(0);
4060}
4061
4062static ConflictResponseData *
4063run_conflict_dialog (CommonJob *job,
4064 GFile *src,
4065 GFile *dest,
4066 GFile *dest_dir)
4067{
4068 ConflictDialogData *data;
4069 ConflictResponseData *resp_data;
4070
4071 g_timer_stop (job->time);
4072
4073 data = g_slice_new0 (ConflictDialogData)(ConflictDialogData *) (__extension__ ({ gsize __s = sizeof (
ConflictDialogData); gpointer __p; __p = g_slice_alloc (__s);
memset (__p, 0, __s); __p; }))
;
4074 data->parent = job->parent_window;
4075 data->src = src;
4076 data->dest = dest;
4077 data->dest_dir = dest_dir;
4078
4079 resp_data = g_slice_new0 (ConflictResponseData)(ConflictResponseData *) (__extension__ ({ gsize __s = sizeof
(ConflictResponseData); gpointer __p; __p = g_slice_alloc (__s
); memset (__p, 0, __s); __p; }))
;
4080 resp_data->new_name = NULL((void*)0);
4081 data->resp_data = resp_data;
4082
4083 caja_progress_info_pause (job->progress);
4084 g_io_scheduler_job_send_to_mainloop (job->io_job,
4085 do_run_conflict_dialog,
4086 data,
4087 NULL((void*)0));
4088 caja_progress_info_resume (job->progress);
4089
4090 g_slice_free (ConflictDialogData, data)do { if (1) g_slice_free1 (sizeof (ConflictDialogData), (data
)); else (void) ((ConflictDialogData*) 0 == (data)); } while (
0)
;
4091
4092 g_timer_continue (job->time);
4093
4094 return resp_data;
4095}
4096
4097static void
4098conflict_response_data_free (ConflictResponseData *data)
4099{
4100 g_free (data->new_name);
4101 g_slice_free (ConflictResponseData, data)do { if (1) g_slice_free1 (sizeof (ConflictResponseData), (data
)); else (void) ((ConflictResponseData*) 0 == (data)); } while
(0)
;
4102}
4103
4104static GFile *
4105get_target_file_for_display_name (GFile *dir,
4106 char *name)
4107{
4108 GFile *dest;
4109
4110 dest = NULL((void*)0);
4111 dest = g_file_get_child_for_display_name (dir, name, NULL((void*)0));
4112
4113 if (dest == NULL((void*)0)) {
4114 dest = g_file_get_child (dir, name);
4115 }
4116
4117 return dest;
4118}
4119
4120/* Debuting files is non-NULL only for toplevel items */
4121static void
4122copy_move_file (CopyMoveJob *copy_job,
4123 GFile *src,
4124 GFile *dest_dir,
4125 gboolean same_fs,
4126 gboolean unique_names,
4127 char **dest_fs_type,
4128 SourceInfo *source_info,
4129 TransferInfo *transfer_info,
4130 GHashTable *debuting_files,
4131 GdkPoint *position,
4132 gboolean overwrite,
4133 gboolean *skipped_file,
4134 gboolean readonly_source_fs,
4135 gboolean last_item)
4136{
4137 GFile *dest, *new_dest;
4138 GError *error;
4139 GFileCopyFlags flags;
4140 char *primary, *secondary, *details;
4141 int response;
4142 ProgressData pdata;
4143 gboolean would_recurse, is_merge;
4144 CommonJob *job;
4145 gboolean res;
4146 int unique_name_nr;
4147 gboolean handled_invalid_filename;
4148
4149 job = (CommonJob *)copy_job;
4150
4151 if (should_skip_file (job, src)) {
4152 *skipped_file = TRUE(!(0));
4153 return;
4154 }
4155
4156 unique_name_nr = 1;
4157
4158 // TODO: Here we should get the previous file name UNDO
4159
4160 /* another file in the same directory might have handled the invalid
4161 * filename condition for us
4162 */
4163 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4164
4165 if (unique_names) {
4166 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4167 } else {
4168 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4169 }
4170
4171
4172 /* Don't allow recursive move/copy into itself.
4173 * (We would get a file system error if we proceeded but it is nicer to
4174 * detect and report it at this level) */
4175 if (test_dir_is_parent (dest_dir, src)) {
4176 if (job->skip_all_error) {
4177 goto out;
4178 }
4179
4180 /* the run_warning() frees all strings passed in automatically */
4181 primary = copy_job->is_move ? g_strdup (_("You cannot move a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a folder into itself."
, 5))
4182 : g_strdup (_("You cannot copy a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a folder into itself."
, 5))
;
4183 secondary = g_strdup (_("The destination folder is inside the source folder."))g_strdup_inline (dcgettext (((void*)0), "The destination folder is inside the source folder."
, 5))
;
4184
4185 response = run_warning (job,
4186 primary,
4187 secondary,
4188 NULL((void*)0),
4189 (source_info->num_files - transfer_info->num_files) > 1,
4190 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4191 NULL((void*)0));
4192
4193 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4194 abort_job (job);
4195 } else if (response == 1) { /* skip all */
4196 job->skip_all_error = TRUE(!(0));
4197 } else if (response == 2) { /* skip */
4198 /* do nothing */
4199 } else {
4200 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4200, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4201 }
4202
4203 goto out;
4204 }
4205
4206 /* Don't allow copying over the source or one of the parents of the source.
4207 */
4208 if (test_dir_is_parent (src, dest)) {
4209 if (job->skip_all_error) {
4210 goto out;
4211 }
4212
4213 /* the run_warning() frees all strings passed in automatically */
4214 primary = copy_job->is_move ? g_strdup (_("You cannot move a file over itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a file over itself."
, 5))
4215 : g_strdup (_("You cannot copy a file over itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a file over itself."
, 5))
;
4216 secondary = g_strdup (_("The source file would be overwritten by the destination."))g_strdup_inline (dcgettext (((void*)0), "The source file would be overwritten by the destination."
, 5))
;
4217
4218 response = run_warning (job,
4219 primary,
4220 secondary,
4221 NULL((void*)0),
4222 (source_info->num_files - transfer_info->num_files) > 1,
4223 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4224 NULL((void*)0));
4225
4226 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4227 abort_job (job);
4228 } else if (response == 1) { /* skip all */
4229 job->skip_all_error = TRUE(!(0));
4230 } else if (response == 2) { /* skip */
4231 /* do nothing */
4232 } else {
4233 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4233, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4234 }
4235
4236 goto out;
4237 }
4238
4239
4240 retry:
4241 error = NULL((void*)0);
4242 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS;
4243 if (overwrite) {
4244 flags |= G_FILE_COPY_OVERWRITE;
4245 }
4246 if (readonly_source_fs) {
4247 flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS;
4248 }
4249
4250 pdata.job = copy_job;
4251 pdata.last_size = 0;
4252 pdata.source_info = source_info;
4253 pdata.transfer_info = transfer_info;
4254
4255 if (!is_dir(src) && last_item)
4256 /* this is the last file for this operation, cannot pause anymore */
4257 caja_progress_info_disable_pause (job->progress);
4258
4259 if (copy_job->is_move) {
4260 res = g_file_move (src, dest,
4261 flags,
4262 job->cancellable,
4263 copy_file_progress_callback,
4264 &pdata,
4265 &error);
4266 } else {
4267 res = g_file_copy (src, dest,
4268 flags,
4269 job->cancellable,
4270 copy_file_progress_callback,
4271 &pdata,
4272 &error);
4273 }
4274
4275 if (res) {
4276 if (!copy_job->is_move) {
4277 /* Ignore errors here. Failure to copy metadata is not a hard error */
4278 g_file_copy_attributes (src, dest,
4279 flags | G_FILE_COPY_ALL_METADATA,
4280 job->cancellable, NULL((void*)0));
4281 }
4282
4283 transfer_info->num_files ++;
4284 report_copy_progress (copy_job, source_info, transfer_info);
4285
4286 if (debuting_files) {
4287 if (position) {
4288 caja_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4289 } else {
4290 caja_file_changes_queue_schedule_position_remove (dest);
4291 }
4292
4293 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4294 }
4295 if (copy_job->is_move) {
4296 caja_file_changes_queue_file_moved (src, dest);
4297 } else {
4298 caja_file_changes_queue_file_added (dest);
4299 }
4300
4301 /* If copying a trusted desktop file to the desktop,
4302 mark it as trusted. */
4303 if (copy_job->desktop_location != NULL((void*)0) &&
4304 g_file_equal (copy_job->desktop_location, dest_dir) &&
4305 is_trusted_desktop_file (src, job->cancellable)) {
4306 mark_desktop_file_trusted (job,
4307 job->cancellable,
4308 dest,
4309 FALSE(0));
4310 }
4311
4312 // Start UNDO-REDO
4313 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, dest);
4314 // End UNDO-REDO
4315
4316 g_object_unref (dest);
4317 return;
4318 }
4319
4320 if (!handled_invalid_filename &&
4321 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
) {
4322 handled_invalid_filename = TRUE(!(0));
4323
4324 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_43
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_43 = 1; else
_g_boolean_var_43 = 0; _g_boolean_var_43; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4324, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4325 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4326
4327 if (unique_names) {
4328 new_dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr);
4329 } else {
4330 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4331 }
4332
4333 if (!g_file_equal (dest, new_dest)) {
4334 g_object_unref (dest);
4335 dest = new_dest;
4336
4337 g_error_free (error);
4338 goto retry;
4339 } else {
4340 g_object_unref (new_dest);
4341 }
4342 }
4343
4344 /* Conflict */
4345 if (!overwrite &&
4346 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4347 gboolean is_merge;
4348 ConflictResponseData *response;
4349
4350 g_error_free (error);
4351
4352 if (unique_names) {
4353 g_object_unref (dest);
4354 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4355 goto retry;
4356 }
4357
4358 is_merge = FALSE(0);
4359
4360 if (is_dir (dest) && is_dir (src)) {
4361 is_merge = TRUE(!(0));
4362 }
4363
4364 if ((is_merge && job->merge_all) ||
4365 (!is_merge && job->replace_all)) {
4366 overwrite = TRUE(!(0));
4367 goto retry;
4368 }
4369
4370 if (job->skip_all_conflict) {
4371 goto out;
4372 }
4373
4374 response = run_conflict_dialog (job, src, dest, dest_dir);
4375
4376 if (response->id == GTK_RESPONSE_CANCEL ||
4377 response->id == GTK_RESPONSE_DELETE_EVENT) {
4378 conflict_response_data_free (response);
4379 abort_job (job);
4380 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4381 if (response->apply_to_all) {
4382 job->skip_all_conflict = TRUE(!(0));
4383 }
4384 conflict_response_data_free (response);
4385 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4386 if (response->apply_to_all) {
4387 if (is_merge) {
4388 job->merge_all = TRUE(!(0));
4389 } else {
4390 job->replace_all = TRUE(!(0));
4391 }
4392 }
4393 overwrite = TRUE(!(0));
4394 conflict_response_data_free (response);
4395 goto retry;
4396 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4397 g_object_unref (dest);
4398 dest = get_target_file_for_display_name (dest_dir,
4399 response->new_name);
4400 conflict_response_data_free (response);
4401 goto retry;
4402 } else {
4403 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4403, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4404 }
4405 }
4406
4407 else if (overwrite &&
4408 IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
) {
4409
4410 g_error_free (error);
4411
4412 if (remove_target_recursively (job, src, dest, dest)) {
4413 goto retry;
4414 }
4415 }
4416
4417 /* Needs to recurse */
4418 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
4419 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
) {
4420 is_merge = error->code == G_IO_ERROR_WOULD_MERGE;
4421 would_recurse = error->code == G_IO_ERROR_WOULD_RECURSE;
4422 g_error_free (error);
4423
4424 if (overwrite && would_recurse) {
4425 error = NULL((void*)0);
4426
4427 /* Copying a dir onto file, first remove the file */
4428 if (!g_file_delete (dest, job->cancellable, &error) &&
4429 !IS_IO_ERROR (error, NOT_FOUND)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_FOUND))
) {
4430 if (job->skip_all_error) {
4431 g_error_free (error);
4432 goto out;
4433 }
4434 if (copy_job->is_move) {
4435 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
4436 } else {
4437 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
4438 }
4439 secondary = f (_("Could not remove the already existing file with the same name in %F.")dcgettext (((void*)0), "Could not remove the already existing file with the same name in %F."
, 5)
, dest_dir);
4440 details = error->message;
4441
4442 /* setting TRUE on show_all here, as we could have
4443 * another error on the same file later.
4444 */
4445 response = run_warning (job,
4446 primary,
4447 secondary,
4448 details,
4449 TRUE(!(0)),
4450 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4451 NULL((void*)0));
4452
4453 g_error_free (error);
4454
4455 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4456 abort_job (job);
4457 } else if (response == 1) { /* skip all */
4458 job->skip_all_error = TRUE(!(0));
4459 } else if (response == 2) { /* skip */
4460 /* do nothing */
4461 } else {
4462 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4462, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4463 }
4464 goto out;
4465
4466 }
4467 if (error) {
4468 g_error_free (error);
4469 error = NULL((void*)0);
4470 }
4471 caja_file_changes_queue_file_removed (dest);
4472 }
4473
4474 if (is_merge) {
4475 /* On merge we now write in the target directory, which may not
4476 be in the same directory as the source, even if the parent is
4477 (if the merged directory is a mountpoint). This could cause
4478 problems as we then don't transcode filenames.
4479 We just set same_fs to FALSE which is safe but a bit slower. */
4480 same_fs = FALSE(0);
4481 }
4482
4483 if (!copy_move_directory (copy_job, src, &dest, same_fs,
4484 would_recurse, dest_fs_type,
4485 source_info, transfer_info,
4486 debuting_files, skipped_file,
4487 readonly_source_fs,
4488 last_item)) {
4489 /* destination changed, since it was an invalid file name */
4490 g_assert (*dest_fs_type != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_44
; if (*dest_fs_type != ((void*)0)) _g_boolean_var_44 = 1; else
_g_boolean_var_44 = 0; _g_boolean_var_44; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4490, ((const char*
) (__func__)), "*dest_fs_type != NULL"); } while (0)
;
4491 handled_invalid_filename = TRUE(!(0));
4492 goto retry;
4493 }
4494
4495 g_object_unref (dest);
4496 return;
4497 }
4498
4499 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
4500 g_error_free (error);
4501 }
4502
4503 /* Other error */
4504 else {
4505 if (job->skip_all_error) {
4506 g_error_free (error);
4507 goto out;
4508 }
4509 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
4510 secondary = f (_("There was an error copying the file into %F.")dcgettext (((void*)0), "There was an error copying the file into %F."
, 5)
, dest_dir);
4511 details = error->message;
4512
4513 response = run_warning (job,
4514 primary,
4515 secondary,
4516 details,
4517 (source_info->num_files - transfer_info->num_files) > 1,
4518 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4519 NULL((void*)0));
4520
4521 g_error_free (error);
4522
4523 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4524 abort_job (job);
4525 } else if (response == 1) { /* skip all */
4526 job->skip_all_error = TRUE(!(0));
4527 } else if (response == 2) { /* skip */
4528 /* do nothing */
4529 } else {
4530 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4530, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4531 }
4532 }
4533 out:
4534 *skipped_file = TRUE(!(0)); /* Or aborted, but same-same */
4535 g_object_unref (dest);
4536}
4537
4538static void
4539copy_files (CopyMoveJob *job,
4540 const char *dest_fs_id,
4541 SourceInfo *source_info,
4542 TransferInfo *transfer_info)
4543{
4544 CommonJob *common;
4545 GList *l;
4546 gboolean same_fs;
4547 int i;
4548 GdkPoint *point;
4549 gboolean skipped_file;
4550 gboolean unique_names;
4551 GFile *dest;
4552 GFile *source_dir;
4553 char *dest_fs_type;
4554 gboolean readonly_source_fs;
4555 GFile *src = NULL((void*)0);
4556
4557 dest_fs_type = NULL((void*)0);
4558 readonly_source_fs = FALSE(0);
4559
4560 common = &job->common;
4561
4562 report_copy_progress (job, source_info, transfer_info);
4563
4564 /* Query the source dir, not the file because if its a symlink we'll follow it */
4565 source_dir = g_file_get_parent ((GFile *) job->files->data);
4566 if (source_dir) {
4567 GFileInfo *inf;
4568
4569 inf = g_file_query_filesystem_info (source_dir, "filesystem::readonly", NULL((void*)0), NULL((void*)0));
4570 if (inf != NULL((void*)0)) {
4571 readonly_source_fs = g_file_info_get_attribute_boolean (inf, "filesystem::readonly");
4572 g_object_unref (inf);
4573 }
4574 g_object_unref (source_dir);
4575 }
4576
4577 unique_names = (job->destination == NULL((void*)0));
4578 i = 0;
4579 for (l = job->files;
4580 l != NULL((void*)0) && !job_aborted (common);
4581 l = l->next) {
4582 caja_progress_info_get_ready (common->progress);
4583
4584 src = l->data;
4585
4586 if (i < job->n_icon_positions) {
4587 point = &job->icon_positions[i];
4588 } else {
4589 point = NULL((void*)0);
4590 }
4591
4592
4593 same_fs = FALSE(0);
4594 if (dest_fs_id) {
4595 same_fs = has_fs_id (src, dest_fs_id);
4596 }
4597
4598 if (job->destination) {
4599 dest = g_object_ref (job->destination)((__typeof__ (job->destination)) (g_object_ref) (job->destination
))
;
4600 } else {
4601 dest = g_file_get_parent (src);
4602
4603 }
4604 if (dest) {
4605 skipped_file = FALSE(0);
4606
4607 copy_move_file (job, src, dest,
4608 same_fs, unique_names,
4609 &dest_fs_type,
4610 source_info, transfer_info,
4611 job->debuting_files,
4612 point, FALSE(0), &skipped_file,
4613 readonly_source_fs,
4614 !l->next);
4615 g_object_unref (dest);
4616 }
4617 i++;
4618 }
4619
4620 g_free (dest_fs_type);
4621}
4622
4623static gboolean
4624copy_job_done (gpointer user_data)
4625{
4626 CopyMoveJob *job;
4627
4628 job = user_data;
4629 if (job->done_callback) {
4630 job->done_callback (job->debuting_files, job->done_callback_data);
4631 }
4632
4633 g_list_free_full (job->files, g_object_unref);
4634 if (job->destination) {
4635 g_object_unref (job->destination);
4636 }
4637 if (job->desktop_location) {
4638 g_object_unref (job->desktop_location);
4639 }
4640 g_hash_table_unref (job->debuting_files);
4641 g_free (job->icon_positions);
4642
4643 finalize_common ((CommonJob *)job);
4644
4645 caja_file_changes_consume_changes (TRUE(!(0)));
4646 return FALSE(0);
4647}
4648
4649static gboolean
4650copy_job (GIOSchedulerJob *io_job,
4651 GCancellable *cancellable,
4652 gpointer user_data)
4653{
4654 CopyMoveJob *job;
4655 CommonJob *common;
4656 SourceInfo source_info;
4657 TransferInfo transfer_info;
4658 char *dest_fs_id;
4659 GFile *dest;
4660
4661 job = user_data;
4662 common = &job->common;
4663 common->io_job = io_job;
4664
4665 dest_fs_id = NULL((void*)0);
4666
4667 caja_progress_info_start (job->common.progress);
4668
4669 scan_sources (job->files,
4670 &source_info,
4671 common,
4672 OP_KIND_COPY);
4673 if (job_aborted (common)) {
4674 goto aborted;
4675 }
4676
4677 if (job->destination) {
4678 dest = g_object_ref (job->destination)((__typeof__ (job->destination)) (g_object_ref) (job->destination
))
;
4679 } else {
4680 /* Duplication, no dest,
4681 * use source for free size, etc
4682 */
4683 dest = g_file_get_parent (job->files->data);
4684 }
4685
4686 verify_destination (&job->common,
4687 dest,
4688 &dest_fs_id,
4689 source_info.num_bytes);
4690 g_object_unref (dest);
4691 if (job_aborted (common)) {
4692 goto aborted;
4693 }
4694
4695 g_timer_start (job->common.time);
4696
4697 memset (&transfer_info, 0, sizeof (transfer_info));
4698 copy_files (job,
4699 dest_fs_id,
4700 &source_info, &transfer_info);
4701
4702 aborted:
4703
4704 g_free (dest_fs_id);
4705
4706 g_io_scheduler_job_send_to_mainloop_async (io_job,
4707 copy_job_done,
4708 job,
4709 NULL((void*)0));
4710
4711 return FALSE(0);
4712}
4713
4714static gboolean
4715contains_multiple_items (GList *files)
4716{
4717 GFile *first;
4718
4719 if (g_list_length (files) > 1) {
4720 return TRUE(!(0));
4721 } else {
4722 if (files) {
4723 first = files->data;
4724 if (is_dir (first))
4725 return TRUE(!(0));
4726 }
4727 }
4728
4729 return FALSE(0);
4730}
4731
4732void
4733caja_file_operations_copy (GList *files,
4734 GArray *relative_item_points,
4735 GFile *target_dir,
4736 GtkWindow *parent_window,
4737 CajaCopyCallback done_callback,
4738 gpointer done_callback_data)
4739{
4740 CopyMoveJob *job;
4741
4742 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
4743 job->desktop_location = caja_get_desktop_location ();
4744 job->done_callback = done_callback;
4745 job->done_callback_data = done_callback_data;
4746 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
4747 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
4748 if (relative_item_points != NULL((void*)0) &&
4749 relative_item_points->len > 0) {
4750 job->icon_positions =
4751 g_memdup (relative_item_points->data,
4752 sizeof (GdkPoint) * relative_item_points->len);
4753 job->n_icon_positions = relative_item_points->len;
4754 }
4755 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
4756
4757 inhibit_power_manager ((CommonJob *)job, _("Copying Files")dcgettext (((void*)0), "Copying Files", 5));
4758
4759 // Start UNDO-REDO
4760 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
4761 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_COPY, g_list_length(files));
4762 GFile* src_dir = g_file_get_parent (files->data);
4763 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
4764 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
4765 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
4766 }
4767 // End UNDO-REDO
4768
4769 g_io_scheduler_push_job (copy_job,
4770 job,
4771 NULL((void*)0), /* destroy notify */
4772 0,
4773 job->common.cancellable);
4774}
4775
4776static void
4777report_move_progress (CopyMoveJob *move_job, int total, int left)
4778{
4779 CommonJob *job;
4780
4781 job = (CommonJob *)move_job;
4782
4783 caja_progress_info_take_status (job->progress,
4784 f (_("Preparing to Move to \"%B\"")dcgettext (((void*)0), "Preparing to Move to \"%B\"", 5),
4785 move_job->destination));
4786
4787 caja_progress_info_take_details (job->progress,
4788 f (ngettext ("Preparing to move %'d file",dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
4789 "Preparing to move %'d files",dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
4790 left)dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
, left));
4791
4792 caja_progress_info_pulse_progress (job->progress);
4793}
4794
4795typedef struct {
4796 GFile *file;
4797 gboolean overwrite;
4798 gboolean has_position;
4799 GdkPoint position;
4800} MoveFileCopyFallback;
4801
4802static MoveFileCopyFallback *
4803move_copy_file_callback_new (GFile *file,
4804 gboolean overwrite,
4805 GdkPoint *position)
4806{
4807 MoveFileCopyFallback *fallback;
4808
4809 fallback = g_new (MoveFileCopyFallback, 1)(MoveFileCopyFallback *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (MoveFileCopyFallback); 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; }))
;
4810 fallback->file = file;
4811 fallback->overwrite = overwrite;
4812 if (position) {
4813 fallback->has_position = TRUE(!(0));
4814 fallback->position = *position;
4815 } else {
4816 fallback->has_position = FALSE(0);
4817 }
4818
4819 return fallback;
4820}
4821
4822static GList *
4823get_files_from_fallbacks (GList *fallbacks)
4824{
4825 GList *res, *l;
4826 MoveFileCopyFallback *fallback = NULL((void*)0);
4827
4828 res = NULL((void*)0);
4829 for (l = fallbacks; l != NULL((void*)0); l = l->next) {
4830 fallback = l->data;
4831 res = g_list_prepend (res, fallback->file);
4832 }
4833 return g_list_reverse (res);
4834}
4835
4836static void
4837move_file_prepare (CopyMoveJob *move_job,
4838 GFile *src,
4839 GFile *dest_dir,
4840 gboolean same_fs,
4841 char **dest_fs_type,
4842 GHashTable *debuting_files,
4843 GdkPoint *position,
4844 GList **fallback_files,
4845 int files_left)
4846{
4847 GFile *dest, *new_dest;
4848 GError *error;
4849 CommonJob *job;
4850 gboolean overwrite;
4851 char *primary, *secondary, *details;
4852 int response;
4853 GFileCopyFlags flags;
4854 MoveFileCopyFallback *fallback;
4855 gboolean handled_invalid_filename;
4856
4857 overwrite = FALSE(0);
4858 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4859
4860 job = (CommonJob *)move_job;
4861
4862 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4863
4864
4865 /* Don't allow recursive move/copy into itself.
4866 * (We would get a file system error if we proceeded but it is nicer to
4867 * detect and report it at this level) */
4868 if (test_dir_is_parent (dest_dir, src)) {
4869 if (job->skip_all_error) {
4870 goto out;
4871 }
4872
4873 /* the run_warning() frees all strings passed in automatically */
4874 primary = move_job->is_move ? g_strdup (_("You cannot move a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a folder into itself."
, 5))
4875 : g_strdup (_("You cannot copy a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a folder into itself."
, 5))
;
4876 secondary = g_strdup (_("The destination folder is inside the source folder."))g_strdup_inline (dcgettext (((void*)0), "The destination folder is inside the source folder."
, 5))
;
4877
4878 response = run_warning (job,
4879 primary,
4880 secondary,
4881 NULL((void*)0),
4882 files_left > 1,
4883 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4884 NULL((void*)0));
4885
4886 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4887 abort_job (job);
4888 } else if (response == 1) { /* skip all */
4889 job->skip_all_error = TRUE(!(0));
4890 } else if (response == 2) { /* skip */
4891 /* do nothing */
4892 } else {
4893 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4893, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4894 }
4895
4896 goto out;
4897 }
4898
4899 retry:
4900 caja_progress_info_get_ready (job->progress);
4901
4902 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_NO_FALLBACK_FOR_MOVE;
4903 if (overwrite) {
4904 flags |= G_FILE_COPY_OVERWRITE;
4905 }
4906
4907 error = NULL((void*)0);
4908 if (g_file_move (src, dest,
4909 flags,
4910 job->cancellable,
4911 NULL((void*)0),
4912 NULL((void*)0),
4913 &error)) {
4914
4915 if (debuting_files) {
4916 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4917 }
4918
4919 caja_file_changes_queue_file_moved (src, dest);
4920
4921 if (position) {
4922 caja_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4923 } else {
4924 caja_file_changes_queue_schedule_position_remove (dest);
4925 }
4926
4927 // Start UNDO-REDO
4928 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, dest);
4929 // End UNDO-REDO
4930
4931 return;
4932 }
4933
4934 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
4935 !handled_invalid_filename) {
4936 handled_invalid_filename = TRUE(!(0));
4937
4938 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_45
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_45 = 1; else
_g_boolean_var_45 = 0; _g_boolean_var_45; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4938, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4939 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4940
4941 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4942 if (!g_file_equal (dest, new_dest)) {
4943 g_object_unref (dest);
4944 dest = new_dest;
4945 goto retry;
4946 } else {
4947 g_object_unref (new_dest);
4948 }
4949 }
4950
4951 /* Conflict */
4952 else if (!overwrite &&
4953 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4954 gboolean is_merge;
4955 ConflictResponseData *response;
4956
4957 g_error_free (error);
4958
4959 is_merge = FALSE(0);
4960 if (is_dir (dest) && is_dir (src)) {
4961 is_merge = TRUE(!(0));
4962 }
4963
4964 if ((is_merge && job->merge_all) ||
4965 (!is_merge && job->replace_all)) {
4966 overwrite = TRUE(!(0));
4967 goto retry;
4968 }
4969
4970 if (job->skip_all_conflict) {
4971 goto out;
4972 }
4973
4974 response = run_conflict_dialog (job, src, dest, dest_dir);
4975
4976 if (response->id == GTK_RESPONSE_CANCEL ||
4977 response->id == GTK_RESPONSE_DELETE_EVENT) {
4978 conflict_response_data_free (response);
4979 abort_job (job);
4980 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4981 if (response->apply_to_all) {
4982 job->skip_all_conflict = TRUE(!(0));
4983 }
4984 conflict_response_data_free (response);
4985 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4986 if (response->apply_to_all) {
4987 if (is_merge) {
4988 job->merge_all = TRUE(!(0));
4989 } else {
4990 job->replace_all = TRUE(!(0));
4991 }
4992 }
4993 overwrite = TRUE(!(0));
4994 conflict_response_data_free (response);
4995 goto retry;
4996 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4997 g_object_unref (dest);
4998 dest = get_target_file_for_display_name (dest_dir,
4999 response->new_name);
5000 conflict_response_data_free (response);
5001 goto retry;
5002 } else {
5003 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5003, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5004 }
5005 }
5006
5007 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
5008 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
||
5009 IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
||
5010 (overwrite && IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
)) {
5011 g_error_free (error);
5012
5013 fallback = move_copy_file_callback_new (src,
5014 overwrite,
5015 position);
5016 *fallback_files = g_list_prepend (*fallback_files, fallback);
5017 }
5018
5019 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
5020 g_error_free (error);
5021 }
5022
5023 /* Other error */
5024 else {
5025 if (job->skip_all_error) {
5026 goto out;
5027 }
5028 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
5029 secondary = f (_("There was an error moving the file into %F.")dcgettext (((void*)0), "There was an error moving the file into %F."
, 5)
, dest_dir);
5030 details = error->message;
5031
5032 response = run_warning (job,
5033 primary,
5034 secondary,
5035 details,
5036 files_left > 1,
5037 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
5038 NULL((void*)0));
5039
5040 g_error_free (error);
5041
5042 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5043 abort_job (job);
5044 } else if (response == 1) { /* skip all */
5045 job->skip_all_error = TRUE(!(0));
5046 } else if (response == 2) { /* skip */
5047 /* do nothing */
5048 } else {
5049 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5049, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5050 }
5051 }
5052
5053 out:
5054 g_object_unref (dest);
5055}
5056
5057static void
5058move_files_prepare (CopyMoveJob *job,
5059 const char *dest_fs_id,
5060 char **dest_fs_type,
5061 GList **fallbacks)
5062{
5063 CommonJob *common;
5064 GList *l;
5065 gboolean same_fs;
5066 gboolean last_item;
5067 int i;
5068 GdkPoint *point;
5069 int total, left;
5070 GFile *src = NULL((void*)0);
5071
5072 common = &job->common;
5073
5074 total = left = g_list_length (job->files);
5075
5076 caja_progress_info_get_ready (common->progress);
5077 report_move_progress (job, total, left);
5078
5079 i = 0;
5080 for (l = job->files;
5081 l != NULL((void*)0) && !job_aborted (common);
5082 l = l->next) {
5083 src = l->data;
5084
5085 last_item = (!l->next) && (!is_dir(src)) && (!(*fallbacks));
5086 if (last_item)
5087 /* this is the last file and there are no fallbacks to process, cannot pause anymore */
5088 caja_progress_info_disable_pause (common->progress);
5089
5090 if (i < job->n_icon_positions) {
5091 point = &job->icon_positions[i];
5092 } else {
5093 point = NULL((void*)0);
5094 }
5095
5096
5097 same_fs = FALSE(0);
5098 if (dest_fs_id) {
5099 same_fs = has_fs_id (src, dest_fs_id);
5100 }
5101
5102 move_file_prepare (job, src, job->destination,
5103 same_fs, dest_fs_type,
5104 job->debuting_files,
5105 point,
5106 fallbacks,
5107 left);
5108 report_move_progress (job, total, --left);
5109 i++;
5110 }
5111
5112 *fallbacks = g_list_reverse (*fallbacks);
5113
5114
5115}
5116
5117static void
5118move_files (CopyMoveJob *job,
5119 GList *fallbacks,
5120 const char *dest_fs_id,
5121 char **dest_fs_type,
5122 SourceInfo *source_info,
5123 TransferInfo *transfer_info)
5124{
5125 CommonJob *common;
5126 GList *l;
5127 gboolean same_fs;
5128 int i;
5129 GdkPoint *point;
5130 gboolean skipped_file;
5131 MoveFileCopyFallback *fallback;
5132 GFile *src = NULL((void*)0);
5133
5134 common = &job->common;
5135
5136 report_copy_progress (job, source_info, transfer_info);
5137
5138 i = 0;
5139 for (l = fallbacks;
5140 l != NULL((void*)0) && !job_aborted (common);
5141 l = l->next) {
5142 caja_progress_info_get_ready (common->progress);
5143
5144 fallback = l->data;
5145 src = fallback->file;
5146
5147 if (fallback->has_position) {
5148 point = &fallback->position;
5149 } else {
5150 point = NULL((void*)0);
5151 }
5152
5153 same_fs = FALSE(0);
5154 if (dest_fs_id) {
5155 same_fs = has_fs_id (src, dest_fs_id);
5156 }
5157
5158 /* Set overwrite to true, as the user has
5159 selected overwrite on all toplevel items */
5160 skipped_file = FALSE(0);
5161 copy_move_file (job, src, job->destination,
5162 same_fs, FALSE(0), dest_fs_type,
5163 source_info, transfer_info,
5164 job->debuting_files,
5165 point, fallback->overwrite, &skipped_file, FALSE(0),
5166 !l->next);
5167 i++;
5168 }
5169}
5170
5171
5172static gboolean
5173move_job_done (gpointer user_data)
5174{
5175 CopyMoveJob *job;
5176
5177 job = user_data;
5178 if (job->done_callback) {
5179 job->done_callback (job->debuting_files, job->done_callback_data);
5180 }
5181
5182 g_list_free_full (job->files, g_object_unref);
5183 g_object_unref (job->destination);
5184 g_hash_table_unref (job->debuting_files);
5185 g_free (job->icon_positions);
5186
5187 finalize_common ((CommonJob *)job);
5188
5189 caja_file_changes_consume_changes (TRUE(!(0)));
5190 return FALSE(0);
5191}
5192
5193static gboolean
5194move_job (GIOSchedulerJob *io_job,
5195 GCancellable *cancellable,
5196 gpointer user_data)
5197{
5198 CopyMoveJob *job;
5199 CommonJob *common;
5200 GList *fallbacks;
5201 SourceInfo source_info;
5202 TransferInfo transfer_info;
5203 char *dest_fs_id;
5204 char *dest_fs_type;
5205 GList *fallback_files;
5206
5207 job = user_data;
5208 common = &job->common;
5209 common->io_job = io_job;
5210
5211 dest_fs_id = NULL((void*)0);
5212 dest_fs_type = NULL((void*)0);
5213
5214 fallbacks = NULL((void*)0);
5215
5216 caja_progress_info_start (job->common.progress);
5217
5218 verify_destination (&job->common,
5219 job->destination,
5220 &dest_fs_id,
5221 -1);
5222 if (job_aborted (common)) {
5223 goto aborted;
5224 }
5225
5226 /* This moves all files that we can do without copy + delete */
5227 move_files_prepare (job, dest_fs_id, &dest_fs_type, &fallbacks);
5228 if (job_aborted (common)) {
5229 goto aborted;
5230 }
5231
5232 /* The rest we need to do deep copy + delete behind on,
5233 so scan for size */
5234
5235 fallback_files = get_files_from_fallbacks (fallbacks);
5236 scan_sources (fallback_files,
5237 &source_info,
5238 common,
5239 OP_KIND_MOVE);
5240
5241 g_list_free (fallback_files);
5242
5243 if (job_aborted (common)) {
5244 goto aborted;
5245 }
5246
5247 verify_destination (&job->common,
5248 job->destination,
5249 NULL((void*)0),
5250 source_info.num_bytes);
5251 if (job_aborted (common)) {
5252 goto aborted;
5253 }
5254
5255 memset (&transfer_info, 0, sizeof (transfer_info));
5256 move_files (job,
5257 fallbacks,
5258 dest_fs_id, &dest_fs_type,
5259 &source_info, &transfer_info);
5260
5261 aborted:
5262 g_list_free_full (fallbacks, g_free);
5263
5264 g_free (dest_fs_id);
5265 g_free (dest_fs_type);
5266
5267 g_io_scheduler_job_send_to_mainloop (io_job,
5268 move_job_done,
5269 job,
5270 NULL((void*)0));
5271
5272 return FALSE(0);
5273}
5274
5275void
5276caja_file_operations_move (GList *files,
5277 GArray *relative_item_points,
5278 GFile *target_dir,
5279 GtkWindow *parent_window,
5280 CajaCopyCallback done_callback,
5281 gpointer done_callback_data)
5282{
5283 CopyMoveJob *job;
5284
5285 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
5286 job->is_move = TRUE(!(0));
5287 job->done_callback = done_callback;
5288 job->done_callback_data = done_callback_data;
5289 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5290 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5291 if (relative_item_points != NULL((void*)0) &&
5292 relative_item_points->len > 0) {
5293 job->icon_positions =
5294 g_memdup (relative_item_points->data,
5295 sizeof (GdkPoint) * relative_item_points->len);
5296 job->n_icon_positions = relative_item_points->len;
5297 }
5298 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5299
5300 inhibit_power_manager ((CommonJob *)job, _("Moving Files")dcgettext (((void*)0), "Moving Files", 5));
5301
5302 // Start UNDO-REDO
5303 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5304 if (g_file_has_uri_scheme (g_list_first(files)->data, "trash")) {
5305 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RESTOREFROMTRASH, g_list_length(files));
5306 } else {
5307 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_MOVE, g_list_length(files));
5308 }
5309 GFile* src_dir = g_file_get_parent (files->data);
5310 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5311 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5312 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
5313 }
5314 // End UNDO-REDO
5315
5316 g_io_scheduler_push_job (move_job,
5317 job,
5318 NULL((void*)0), /* destroy notify */
5319 0,
5320 job->common.cancellable);
5321}
5322
5323static void
5324report_link_progress (CopyMoveJob *link_job, int total, int left)
5325{
5326 CommonJob *job;
5327
5328 job = (CommonJob *)link_job;
5329
5330 caja_progress_info_take_status (job->progress,
5331 f (_("Creating links in \"%B\"")dcgettext (((void*)0), "Creating links in \"%B\"", 5),
5332 link_job->destination));
5333
5334 caja_progress_info_take_details (job->progress,
5335 f (ngettext ("Making link to %'d file",dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
5336 "Making links to %'d files",dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
5337 left)dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
, left));
5338
5339 caja_progress_info_set_progress (job->progress, left, total);
5340}
5341
5342static char *
5343get_abs_path_for_symlink (GFile *file)
5344{
5345 GFile *root, *parent;
5346 char *relative, *abs;
5347
5348 if (g_file_is_native (file)) {
5349 return g_file_get_path (file);
5350 }
5351
5352 root = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
5353 while ((parent = g_file_get_parent (root)) != NULL((void*)0)) {
5354 g_object_unref (root);
5355 root = parent;
5356 }
5357
5358 relative = g_file_get_relative_path (root, file);
5359 g_object_unref (root);
5360 abs = g_strconcat ("/", relative, NULL((void*)0));
5361 g_free (relative);
5362 return abs;
5363}
5364
5365
5366static void
5367link_file (CopyMoveJob *job,
5368 GFile *src, GFile *dest_dir,
5369 char **dest_fs_type,
5370 GHashTable *debuting_files,
5371 GdkPoint *position,
5372 int files_left)
5373{
5374 GFile *src_dir, *dest, *new_dest;
5375 int count;
5376 char *path;
5377 gboolean not_local;
5378 GError *error;
5379 CommonJob *common;
5380 char *primary, *secondary, *details;
5381 int response;
5382 gboolean handled_invalid_filename;
5383
5384 common = (CommonJob *)job;
5385
5386 count = 0;
5387
5388 src_dir = g_file_get_parent (src);
5389 if (g_file_equal (src_dir, dest_dir)) {
5390 count = 1;
5391 }
5392 g_object_unref (src_dir);
5393
5394 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
5395
5396 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5397
5398 retry:
5399 error = NULL((void*)0);
5400 not_local = FALSE(0);
5401
5402 path = get_abs_path_for_symlink (src);
5403 if (path == NULL((void*)0)) {
5404 not_local = TRUE(!(0));
5405 } else if (g_file_make_symbolic_link (dest,
5406 path,
5407 common->cancellable,
5408 &error)) {
5409 // Start UNDO-REDO
5410 caja_undostack_manager_data_add_origin_target_pair (common->undo_redo_data, src, dest);
5411 // End UNDO-REDO
5412 g_free (path);
5413 if (debuting_files) {
5414 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
5415 }
5416
5417 caja_file_changes_queue_file_added (dest);
5418 if (position) {
5419 caja_file_changes_queue_schedule_position_set (dest, *position, common->screen_num);
5420 } else {
5421 caja_file_changes_queue_schedule_position_remove (dest);
5422 }
5423
5424 g_object_unref (dest);
5425
5426 return;
5427 }
5428 g_free (path);
5429
5430 if (error != NULL((void*)0) &&
5431 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
5432 !handled_invalid_filename) {
5433 handled_invalid_filename = TRUE(!(0));
5434
5435 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_46
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_46 = 1; else
_g_boolean_var_46 = 0; _g_boolean_var_46; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 5435, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
5436 *dest_fs_type = query_fs_type (dest_dir, common->cancellable);
5437
5438 new_dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5439
5440 if (!g_file_equal (dest, new_dest)) {
5441 g_object_unref (dest);
5442 dest = new_dest;
5443 g_error_free (error);
5444
5445 goto retry;
5446 } else {
5447 g_object_unref (new_dest);
5448 }
5449 }
5450 /* Conflict */
5451 if (error != NULL((void*)0) && IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
5452 g_object_unref (dest);
5453 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count++);
5454 g_error_free (error);
5455 goto retry;
5456 }
5457
5458 else if (error != NULL((void*)0) && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
5459 g_error_free (error);
5460 }
5461
5462 /* Other error */
5463 else {
5464 if (common->skip_all_error) {
5465 goto out;
5466 }
5467 primary = f (_("Error while creating link to %B.")dcgettext (((void*)0), "Error while creating link to %B.", 5), src);
5468 if (not_local) {
5469 secondary = f (_("Symbolic links only supported for local files")dcgettext (((void*)0), "Symbolic links only supported for local files"
, 5)
);
5470 details = NULL((void*)0);
5471 } else if (error != NULL((void*)0) && IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
5472 secondary = f (_("The target doesn't support symbolic links.")dcgettext (((void*)0), "The target doesn't support symbolic links."
, 5)
);
5473 details = NULL((void*)0);
5474 } else {
5475 secondary = f (_("There was an error creating the symlink in %F.")dcgettext (((void*)0), "There was an error creating the symlink in %F."
, 5)
, dest_dir);
5476 details = error ? error->message : NULL((void*)0);
5477 }
5478
5479 response = run_warning (common,
5480 primary,
5481 secondary,
5482 details,
5483 files_left > 1,
5484 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
5485 NULL((void*)0));
5486
5487 if (error) {
5488 g_error_free (error);
5489 }
5490
5491 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5492 abort_job (common);
5493 } else if (response == 1) { /* skip all */
5494 common->skip_all_error = TRUE(!(0));
5495 } else if (response == 2) { /* skip */
5496 /* do nothing */
5497 } else {
5498 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5498, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5499 }
5500 }
5501
5502 out:
5503 g_object_unref (dest);
5504}
5505
5506static gboolean
5507link_job_done (gpointer user_data)
5508{
5509 CopyMoveJob *job;
5510
5511 job = user_data;
5512 if (job->done_callback) {
5513 job->done_callback (job->debuting_files, job->done_callback_data);
5514 }
5515
5516 g_list_free_full (job->files, g_object_unref);
5517 g_object_unref (job->destination);
5518 g_hash_table_unref (job->debuting_files);
5519 g_free (job->icon_positions);
5520
5521 finalize_common ((CommonJob *)job);
5522
5523 caja_file_changes_consume_changes (TRUE(!(0)));
5524 return FALSE(0);
5525}
5526
5527static gboolean
5528link_job (GIOSchedulerJob *io_job,
5529 GCancellable *cancellable,
5530 gpointer user_data)
5531{
5532 CopyMoveJob *job;
5533 CommonJob *common;
5534 GFile *src;
5535 GdkPoint *point;
5536 char *dest_fs_type;
5537 int total, left;
5538 int i;
5539 GList *l;
5540
5541 job = user_data;
5542 common = &job->common;
5543 common->io_job = io_job;
5544
5545 dest_fs_type = NULL((void*)0);
5546
5547 caja_progress_info_start (job->common.progress);
5548
5549 verify_destination (&job->common,
5550 job->destination,
5551 NULL((void*)0),
5552 -1);
5553 if (job_aborted (common)) {
5554 goto aborted;
5555 }
5556
5557 total = left = g_list_length (job->files);
5558
5559 report_link_progress (job, total, left);
5560
5561 i = 0;
5562 for (l = job->files;
5563 l != NULL((void*)0) && !job_aborted (common);
5564 l = l->next) {
5565 caja_progress_info_get_ready (common->progress);
5566
5567 src = l->data;
5568
5569 if (i < job->n_icon_positions) {
5570 point = &job->icon_positions[i];
5571 } else {
5572 point = NULL((void*)0);
5573 }
5574
5575
5576 link_file (job, src, job->destination,
5577 &dest_fs_type, job->debuting_files,
5578 point, left);
5579 report_link_progress (job, total, --left);
5580 i++;
5581
5582 }
5583
5584 aborted:
5585 g_free (dest_fs_type);
5586
5587 g_io_scheduler_job_send_to_mainloop (io_job,
5588 link_job_done,
5589 job,
5590 NULL((void*)0));
5591
5592 return FALSE(0);
5593}
5594
5595void
5596caja_file_operations_link (GList *files,
5597 GArray *relative_item_points,
5598 GFile *target_dir,
5599 GtkWindow *parent_window,
5600 CajaCopyCallback done_callback,
5601 gpointer done_callback_data)
5602{
5603 CopyMoveJob *job;
5604
5605 job = op_job_new (CopyMoveJob, parent_window, TRUE, FALSE)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (!(0)), (0))))
;
5606 job->done_callback = done_callback;
5607 job->done_callback_data = done_callback_data;
5608 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5609 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5610 if (relative_item_points != NULL((void*)0) &&
5611 relative_item_points->len > 0) {
5612 job->icon_positions =
5613 g_memdup (relative_item_points->data,
5614 sizeof (GdkPoint) * relative_item_points->len);
5615 job->n_icon_positions = relative_item_points->len;
5616 }
5617 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5618
5619 // Start UNDO-REDO
5620 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5621 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATELINK, g_list_length(files));
5622 GFile* src_dir = g_file_get_parent (files->data);
5623 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5624 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5625 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
5626 }
5627 // End UNDO-REDO
5628
5629 g_io_scheduler_push_job (link_job,
5630 job,
5631 NULL((void*)0), /* destroy notify */
5632 0,
5633 job->common.cancellable);
5634}
5635
5636
5637void
5638caja_file_operations_duplicate (GList *files,
5639 GArray *relative_item_points,
5640 GtkWindow *parent_window,
5641 CajaCopyCallback done_callback,
5642 gpointer done_callback_data)
5643{
5644 CopyMoveJob *job;
5645
5646 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
5647 job->done_callback = done_callback;
5648 job->done_callback_data = done_callback_data;
5649 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5650 job->destination = NULL((void*)0);
5651 if (relative_item_points != NULL((void*)0) &&
5652 relative_item_points->len > 0) {
5653 job->icon_positions =
5654 g_memdup (relative_item_points->data,
5655 sizeof (GdkPoint) * relative_item_points->len);
5656 job->n_icon_positions = relative_item_points->len;
5657 }
5658 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5659
5660 // Start UNDO-REDO
5661 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5662 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_DUPLICATE, g_list_length(files));
5663 GFile* src_dir = g_file_get_parent (files->data);
5664 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5665 g_object_ref (src_dir)((__typeof__ (src_dir)) (g_object_ref) (src_dir));
5666 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, src_dir);
5667 }
5668 // End UNDO-REDO
5669
5670 g_io_scheduler_push_job (copy_job,
5671 job,
5672 NULL((void*)0), /* destroy notify */
5673 0,
5674 job->common.cancellable);
5675}
5676
5677static gboolean
5678set_permissions_job_done (gpointer user_data)
5679{
5680 SetPermissionsJob *job;
5681
5682 job = user_data;
5683
5684 g_object_unref (job->file);
5685
5686 if (job->done_callback) {
5687 job->done_callback (job->done_callback_data);
5688 }
5689
5690 finalize_common ((CommonJob *)job);
5691 return FALSE(0);
5692}
5693
5694static void
5695set_permissions_file (SetPermissionsJob *job,
5696 GFile *file,
5697 GFileInfo *info)
5698{
5699 CommonJob *common;
5700 gboolean free_info;
5701 guint32 current;
5702 guint32 value;
5703 guint32 mask;
5704
5705 common = (CommonJob *)job;
5706
5707 caja_progress_info_pulse_progress (common->progress);
5708
5709 caja_progress_info_get_ready (common->progress);
5710
5711 free_info = FALSE(0);
5712 if (info == NULL((void*)0)) {
5713 free_info = TRUE(!(0));
5714 info = g_file_query_info (file,
5715 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5716 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5717 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5718 common->cancellable,
5719 NULL((void*)0));
5720 /* Ignore errors */
5721 if (info == NULL((void*)0)) {
5722 return;
5723 }
5724 }
5725
5726 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5727 value = job->dir_permissions;
5728 mask = job->dir_mask;
5729 } else {
5730 value = job->file_permissions;
5731 mask = job->file_mask;
5732 }
5733
5734
5735 if (!job_aborted (common) &&
5736 g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
5737 current = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
5738 // Start UNDO-REDO
5739 caja_undostack_manager_data_add_file_permissions(common->undo_redo_data, file, current);
5740 // End UNDO-REDO
5741 current = (current & ~mask) | value;
5742
5743 g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5744 current, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5745 common->cancellable, NULL((void*)0));
5746 }
5747
5748 if (!job_aborted (common) && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5749 GFileEnumerator *enumerator;
5750
5751 enumerator = g_file_enumerate_children (file,
5752 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
5753 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5754 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5755 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5756 common->cancellable,
5757 NULL((void*)0));
5758 if (enumerator) {
5759 GFile *child = NULL((void*)0);
5760 GFileInfo *child_info = NULL((void*)0);
5761
5762 while (!job_aborted (common) &&
5763 (child_info = g_file_enumerator_next_file (enumerator, common->cancellable, NULL((void*)0))) != NULL((void*)0)) {
5764 child = g_file_get_child (file,
5765 g_file_info_get_name (child_info));
5766 set_permissions_file (job, child, child_info);
5767 g_object_unref (child);
5768 g_object_unref (child_info);
5769 }
5770 g_file_enumerator_close (enumerator, common->cancellable, NULL((void*)0));
5771 g_object_unref (enumerator);
5772 }
5773 }
5774 if (free_info) {
5775 g_object_unref (info);
5776 }
5777}
5778
5779
5780static gboolean
5781set_permissions_job (GIOSchedulerJob *io_job,
5782 GCancellable *cancellable,
5783 gpointer user_data)
5784{
5785 SetPermissionsJob *job = user_data;
5786 CommonJob *common;
5787
5788 common = (CommonJob *)job;
5789 common->io_job = io_job;
5790
5791 caja_progress_info_set_status (common->progress,
5792 _("Setting permissions")dcgettext (((void*)0), "Setting permissions", 5));
5793
5794 caja_progress_info_start (job->common.progress);
5795
5796 set_permissions_file (job, job->file, NULL((void*)0));
5797
5798 g_io_scheduler_job_send_to_mainloop_async (io_job,
5799 set_permissions_job_done,
5800 job,
5801 NULL((void*)0));
5802
5803 return FALSE(0);
5804}
5805
5806
5807
5808void
5809caja_file_set_permissions_recursive (const char *directory,
5810 guint32 file_permissions,
5811 guint32 file_mask,
5812 guint32 dir_permissions,
5813 guint32 dir_mask,
5814 CajaOpCallback callback,
5815 gpointer callback_data)
5816{
5817 SetPermissionsJob *job;
5818
5819 job = op_job_new (SetPermissionsJob, NULL, TRUE, FALSE)((SetPermissionsJob *)(init_common (sizeof(SetPermissionsJob)
, ((void*)0), (!(0)), (0))))
;
5820 job->file = g_file_new_for_uri (directory);
5821 job->file_permissions = file_permissions;
5822 job->file_mask = file_mask;
5823 job->dir_permissions = dir_permissions;
5824 job->dir_mask = dir_mask;
5825 job->done_callback = callback;
5826 job->done_callback_data = callback_data;
5827
5828 // Start UNDO-REDO
5829 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5830 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RECURSIVESETPERMISSIONS, 1);
5831 g_object_ref (job->file)((__typeof__ (job->file)) (g_object_ref) (job->file));
5832 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, job->file);
5833 caja_undostack_manager_data_set_recursive_permissions(job->common.undo_redo_data, file_permissions, file_mask, dir_permissions, dir_mask);
5834 }
5835 // End UNDO-REDO
5836
5837 g_io_scheduler_push_job (set_permissions_job,
5838 job,
5839 NULL((void*)0),
5840 0,
5841 NULL((void*)0));
5842}
5843
5844static GList *
5845location_list_from_uri_list (const GList *uris)
5846{
5847 const GList *l;
5848 GList *files;
5849 GFile *f = NULL((void*)0);
5850
5851 files = NULL((void*)0);
5852 for (l = uris; l != NULL((void*)0); l = l->next) {
5853 f = g_file_new_for_uri (l->data);
5854 files = g_list_prepend (files, f);
5855 }
5856
5857 return g_list_reverse (files);
5858}
5859
5860typedef struct {
5861 CajaCopyCallback real_callback;
5862 gpointer real_data;
5863} MoveTrashCBData;
5864
5865static void
5866callback_for_move_to_trash (GHashTable *debuting_uris,
5867 gboolean user_cancelled,
5868 MoveTrashCBData *data)
5869{
5870 if (data->real_callback)
5871 data->real_callback (debuting_uris, data->real_data);
5872 g_slice_free (MoveTrashCBData, data)do { if (1) g_slice_free1 (sizeof (MoveTrashCBData), (data));
else (void) ((MoveTrashCBData*) 0 == (data)); } while (0)
;
5873}
5874
5875void
5876caja_file_operations_copy_move (const GList *item_uris,
5877 GArray *relative_item_points,
5878 const char *target_dir,
5879 GdkDragAction copy_action,
5880 GtkWidget *parent_view,
5881 CajaCopyCallback done_callback,
5882 gpointer done_callback_data)
5883{
5884 GList *locations;
5885 GList *p;
5886 GFile *src_dir;
5887 GFile *dest;
5888 GtkWindow *parent_window;
5889 gboolean target_is_mapping;
5890 gboolean have_nonmapping_source;
5891
5892 dest = NULL((void*)0);
5893 target_is_mapping = FALSE(0);
5894 have_nonmapping_source = FALSE(0);
5895
5896 if (target_dir) {
5897 dest = g_file_new_for_uri (target_dir);
5898 if (g_file_has_uri_scheme (dest, "burn")) {
5899 target_is_mapping = TRUE(!(0));
5900 }
5901 }
5902
5903 locations = location_list_from_uri_list (item_uris);
5904
5905 for (p = location_list_from_uri_list (item_uris); p != NULL((void*)0); p = p->next) {
5906 if (!g_file_has_uri_scheme ((GFile* )p->data, "burn")) {
5907 have_nonmapping_source = TRUE(!(0));
5908 }
5909 }
5910
5911 if (target_is_mapping && have_nonmapping_source && copy_action == GDK_ACTION_MOVE) {
5912 /* never move to "burn:///", but fall back to copy.
5913 * This is a workaround, because otherwise the source files would be removed.
5914 */
5915 copy_action = GDK_ACTION_COPY;
5916 }
5917
5918 parent_window = NULL((void*)0);
5919 if (parent_view) {
5920 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
5921 }
5922
5923 src_dir = g_file_get_parent (locations->data);
5924
5925 if (copy_action == GDK_ACTION_COPY) {
5926 if (target_dir == NULL((void*)0) ||
5927 (src_dir != NULL((void*)0) &&
5928 g_file_equal (src_dir, dest))) {
5929 caja_file_operations_duplicate (locations,
5930 relative_item_points,
5931 parent_window,
5932 done_callback, done_callback_data);
5933 } else {
5934 caja_file_operations_copy (locations,
5935 relative_item_points,
5936 dest,
5937 parent_window,
5938 done_callback, done_callback_data);
5939 }
5940 } else if (copy_action == GDK_ACTION_MOVE) {
5941 if (g_file_has_uri_scheme (dest, "trash")) {
5942 MoveTrashCBData *cb_data;
5943
5944 cb_data = g_slice_new0 (MoveTrashCBData)(MoveTrashCBData *) (__extension__ ({ gsize __s = sizeof (MoveTrashCBData
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
5945 cb_data->real_callback = done_callback;
5946 cb_data->real_data = done_callback_data;
5947 caja_file_operations_trash_or_delete (locations,
5948 parent_window,
5949 (CajaDeleteCallback) callback_for_move_to_trash,
5950 cb_data);
5951 } else if (src_dir == NULL((void*)0) || !g_file_equal (src_dir, dest)) {
5952 caja_file_operations_move (locations,
5953 relative_item_points,
5954 dest,
5955 parent_window,
5956 done_callback, done_callback_data);
5957 }
5958 } else {
5959 caja_file_operations_link (locations,
5960 relative_item_points,
5961 dest,
5962 parent_window,
5963 done_callback, done_callback_data);
5964 }
5965
5966 g_list_free_full (locations, g_object_unref);
5967 if (dest) {
5968 g_object_unref (dest);
5969 }
5970
5971 if (src_dir) {
5972 g_object_unref (src_dir);
5973 }
5974}
5975
5976static gboolean
5977create_job_done (gpointer user_data)
5978{
5979 CreateJob *job;
5980
5981 job = user_data;
5982 if (job->done_callback) {
5983 job->done_callback (job->created_file, job->done_callback_data);
5984 }
5985
5986 g_object_unref (job->dest_dir);
5987 if (job->src) {
5988 g_object_unref (job->src);
5989 }
5990 g_free (job->src_data);
5991 g_free (job->filename);
5992 if (job->created_file) {
5993 g_object_unref (job->created_file);
5994 }
5995
5996 finalize_common ((CommonJob *)job);
5997
5998 caja_file_changes_consume_changes (TRUE(!(0)));
5999 return FALSE(0);
6000}
6001
6002static gboolean
6003create_job (GIOSchedulerJob *io_job,
6004 GCancellable *cancellable,
6005 gpointer user_data)
6006{
6007 CreateJob *job;
6008 CommonJob *common;
6009 int count;
6010 GFile *dest;
6011 char *filename, *filename2, *new_filename;
6012 char *dest_fs_type;
6013 GError *error;
6014 gboolean res;
6015 gboolean filename_is_utf8;
6016 char *primary, *secondary, *details;
6017 int response;
6018 char *data;
6019 int length;
6020 GFileOutputStream *out;
6021 gboolean handled_invalid_filename;
6022 int max_length;
6023
6024 job = user_data;
6025 common = &job->common;
6026 common->io_job = io_job;
6027
6028 caja_progress_info_start (job->common.progress);
6029
6030 handled_invalid_filename = FALSE(0);
6031
6032 dest_fs_type = NULL((void*)0);
6033 filename = NULL((void*)0);
6034 dest = NULL((void*)0);
6035
6036 max_length = get_max_name_length (job->dest_dir);
6037
6038 verify_destination (common,
6039 job->dest_dir,
6040 NULL((void*)0), -1);
6041 if (job_aborted (common)) {
6042 goto aborted;
6043 }
6044
6045 filename = g_strdup (job->filename)g_strdup_inline (job->filename);
6046 filename_is_utf8 = FALSE(0);
6047 if (filename) {
6048 filename_is_utf8 = g_utf8_validate (filename, -1, NULL((void*)0));
6049 }
6050 if (filename == NULL((void*)0)) {
6051 if (job->make_dir) {
6052 /* Translators: the initial name of a new folder */
6053 filename = g_strdup (_("untitled folder"))g_strdup_inline (dcgettext (((void*)0), "untitled folder", 5)
)
;
6054 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6055 } else {
6056 if (job->src != NULL((void*)0)) {
6057 filename = g_file_get_basename (job->src);
6058 }
6059 if (filename == NULL((void*)0)) {
6060 /* Translators: the initial name of a new empty file */
6061 filename = g_strdup (_("new file"))g_strdup_inline (dcgettext (((void*)0), "new file", 5));
6062 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6063 }
6064 }
6065 }
6066
6067 make_file_name_valid_for_dest_fs (filename, dest_fs_type);
6068 if (filename_is_utf8) {
6069 dest = g_file_get_child_for_display_name (job->dest_dir, filename, NULL((void*)0));
6070 }
6071 if (dest == NULL((void*)0)) {
6072 dest = g_file_get_child (job->dest_dir, filename);
6073 }
6074 count = 1;
6075
6076 retry:
6077 caja_progress_info_get_ready (common->progress);
6078
6079 error = NULL((void*)0);
6080 if (job->make_dir) {
6081 res = g_file_make_directory (dest,
6082 common->cancellable,
6083 &error);
6084 // Start UNDO-REDO
6085 if (res) {
6086 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6087 g_file_get_uri(dest),
6088 NULL((void*)0));
6089 }
6090 // End UNDO-REDO
6091 } else {
6092 if (job->src) {
6093 res = g_file_copy (job->src,
6094 dest,
6095 G_FILE_COPY_NONE,
6096 common->cancellable,
6097 NULL((void*)0), NULL((void*)0),
6098 &error);
6099 // Start UNDO-REDO
6100 if (res) {
6101 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6102 g_file_get_uri(dest),
6103 g_file_get_uri(job->src));
6104 }
6105 // End UNDO-REDO
6106 } else {
6107 data = "";
6108 length = 0;
6109 if (job->src_data) {
6110 data = job->src_data;
6111 length = job->length;
6112 }
6113
6114 out = g_file_create (dest,
6115 G_FILE_CREATE_NONE,
6116 common->cancellable,
6117 &error);
6118 if (out) {
6119 res = g_output_stream_write_all (G_OUTPUT_STREAM (out)((((GOutputStream*) (void *) ((out))))),
6120 data, length,
6121 NULL((void*)0),
6122 common->cancellable,
6123 &error);
6124 if (res) {
6125 res = g_output_stream_close (G_OUTPUT_STREAM (out)((((GOutputStream*) (void *) ((out))))),
6126 common->cancellable,
6127 &error);
6128 // Start UNDO-REDO
6129 if (res) {
6130 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6131 g_file_get_uri(dest),
6132 g_strdup(data)g_strdup_inline (data));
6133 }
6134 // End UNDO-REDO
6135 }
6136
6137 /* This will close if the write failed and we didn't close */
6138 g_object_unref (out);
6139 } else {
6140 res = FALSE(0);
6141 }
6142 }
6143 }
6144
6145 if (res) {
6146 job->created_file = g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest));
6147 caja_file_changes_queue_file_added (dest);
6148 if (job->has_position) {
6149 caja_file_changes_queue_schedule_position_set (dest, job->position, common->screen_num);
6150 } else {
6151 caja_file_changes_queue_schedule_position_remove (dest);
6152 }
6153 } else {
6154 g_assert (error != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_47
; if (error != ((void*)0)) _g_boolean_var_47 = 1; else _g_boolean_var_47
= 0; _g_boolean_var_47; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 6154, ((const char*
) (__func__)), "error != NULL"); } while (0)
;
6155
6156 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
6157 !handled_invalid_filename) {
6158 handled_invalid_filename = TRUE(!(0));
6159
6160 g_assert (dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_48
; if (dest_fs_type == ((void*)0)) _g_boolean_var_48 = 1; else
_g_boolean_var_48 = 0; _g_boolean_var_48; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 6160, ((const char*
) (__func__)), "dest_fs_type == NULL"); } while (0)
;
6161 dest_fs_type = query_fs_type (job->dest_dir, common->cancellable);
6162
6163 g_object_unref (dest);
6164
6165 if (count == 1) {
6166 new_filename = g_strdup (filename)g_strdup_inline (filename);
6167 } else if (job->make_dir) {
6168 filename2 = g_strdup_printf ("%s %d", filename, count);
6169
6170 new_filename = NULL((void*)0);
6171 if (max_length > 0 && strlen (filename2) > max_length) {
6172 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6173 }
6174
6175 if (new_filename == NULL((void*)0)) {
6176 new_filename = g_strdup (filename2)g_strdup_inline (filename2);
6177 }
6178
6179 g_free (filename2);
6180 } else {
6181 new_filename = get_duplicate_name (filename, count, max_length);
6182 }
6183
6184 if (make_file_name_valid_for_dest_fs (new_filename, dest_fs_type)) {
6185 g_object_unref (dest);
6186
6187 if (filename_is_utf8) {
6188 dest = g_file_get_child_for_display_name (job->dest_dir, new_filename, NULL((void*)0));
6189 }
6190 if (dest == NULL((void*)0)) {
6191 dest = g_file_get_child (job->dest_dir, new_filename);
6192 }
6193
6194 g_free (new_filename);
6195 g_error_free (error);
6196 goto retry;
6197 }
6198 g_free (new_filename);
6199 } else if (IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
6200 g_object_unref (dest);
6201 dest = NULL((void*)0);
6202 if (job->make_dir) {
6203 filename2 = g_strdup_printf ("%s %d", filename, ++count);
6204 if (max_length > 0 && strlen (filename2) > max_length) {
6205 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6206 if (new_filename != NULL((void*)0)) {
6207 g_free (filename2);
6208 filename2 = new_filename;
6209 }
6210 }
6211 } else {
6212 filename2 = get_duplicate_name (filename, count++, max_length);
6213 }
6214 make_file_name_valid_for_dest_fs (filename2, dest_fs_type);
6215 if (filename_is_utf8) {
6216 dest = g_file_get_child_for_display_name (job->dest_dir, filename2, NULL((void*)0));
6217 }
6218 if (dest == NULL((void*)0)) {
6219 dest = g_file_get_child (job->dest_dir, filename2);
6220 }
6221 g_free (filename2);
6222 g_error_free (error);
6223 goto retry;
6224 }
6225
6226 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
6227 g_error_free (error);
6228 }
6229
6230 /* Other error */
6231 else {
6232 if (job->make_dir) {
6233 primary = f (_("Error while creating directory %B.")dcgettext (((void*)0), "Error while creating directory %B.", 5
)
, dest);
6234 } else {
6235 primary = f (_("Error while creating file %B.")dcgettext (((void*)0), "Error while creating file %B.", 5), dest);
6236 }
6237 secondary = f (_("There was an error creating the directory in %F.")dcgettext (((void*)0), "There was an error creating the directory in %F."
, 5)
, job->dest_dir);
6238 details = error->message;
6239
6240 response = run_warning (common,
6241 primary,
6242 secondary,
6243 details,
6244 FALSE(0),
6245 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
6246 NULL((void*)0));
6247
6248 g_error_free (error);
6249
6250 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6251 abort_job (common);
6252 } else if (response == 1) { /* skip */
6253 /* do nothing */
6254 } else {
6255 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6255, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6256 }
6257 }
6258 }
6259
6260 aborted:
6261 if (dest) {
6262 g_object_unref (dest);
6263 }
6264 g_free (filename);
6265 g_free (dest_fs_type);
6266 g_io_scheduler_job_send_to_mainloop_async (io_job,
6267 create_job_done,
6268 job,
6269 NULL((void*)0));
6270
6271 return FALSE(0);
6272}
6273
6274void
6275caja_file_operations_new_folder (GtkWidget *parent_view,
6276 GdkPoint *target_point,
6277 const char *parent_dir,
6278 CajaCreateCallback done_callback,
6279 gpointer done_callback_data)
6280{
6281 CreateJob *job;
6282 GtkWindow *parent_window;
6283
6284 parent_window = NULL((void*)0);
6285 if (parent_view) {
6286 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6287 }
6288
6289 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6290 job->done_callback = done_callback;
6291 job->done_callback_data = done_callback_data;
6292 job->dest_dir = g_file_new_for_uri (parent_dir);
6293 job->make_dir = TRUE(!(0));
6294 if (target_point != NULL((void*)0)) {
6295 job->position = *target_point;
6296 job->has_position = TRUE(!(0));
6297 }
6298
6299 // Start UNDO-REDO
6300 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6301 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEFOLDER, 1);
6302 }
6303 // End UNDO-REDO
6304
6305 g_io_scheduler_push_job (create_job,
6306 job,
6307 NULL((void*)0), /* destroy notify */
6308 0,
6309 job->common.cancellable);
6310}
6311
6312void
6313caja_file_operations_new_file_from_template (GtkWidget *parent_view,
6314 GdkPoint *target_point,
6315 const char *parent_dir,
6316 const char *target_filename,
6317 const char *template_uri,
6318 CajaCreateCallback done_callback,
6319 gpointer done_callback_data)
6320{
6321 CreateJob *job;
6322 GtkWindow *parent_window;
6323
6324 parent_window = NULL((void*)0);
6325 if (parent_view) {
6326 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6327 }
6328
6329 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6330 job->done_callback = done_callback;
6331 job->done_callback_data = done_callback_data;
6332 job->dest_dir = g_file_new_for_uri (parent_dir);
6333 if (target_point != NULL((void*)0)) {
6334 job->position = *target_point;
6335 job->has_position = TRUE(!(0));
6336 }
6337 job->filename = g_strdup (target_filename)g_strdup_inline (target_filename);
6338
6339 if (template_uri) {
6340 job->src = g_file_new_for_uri (template_uri);
6341 }
6342
6343 // Start UNDO-REDO
6344 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6345 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEFILEFROMTEMPLATE, 1);
6346 }
6347 // End UNDO-REDO
6348
6349 g_io_scheduler_push_job (create_job,
6350 job,
6351 NULL((void*)0), /* destroy notify */
6352 0,
6353 job->common.cancellable);
6354}
6355
6356void
6357caja_file_operations_new_file (GtkWidget *parent_view,
6358 GdkPoint *target_point,
6359 const char *parent_dir,
6360 const char *target_filename,
6361 const char *initial_contents,
6362 int length,
6363 CajaCreateCallback done_callback,
6364 gpointer done_callback_data)
6365{
6366 CreateJob *job;
6367 GtkWindow *parent_window;
6368
6369 parent_window = NULL((void*)0);
6370 if (parent_view) {
6371 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6372 }
6373
6374 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6375 job->done_callback = done_callback;
6376 job->done_callback_data = done_callback_data;
6377 job->dest_dir = g_file_new_for_uri (parent_dir);
6378 if (target_point != NULL((void*)0)) {
6379 job->position = *target_point;
6380 job->has_position = TRUE(!(0));
6381 }
6382 job->src_data = g_memdup (initial_contents, length);
6383 job->length = length;
6384 job->filename = g_strdup (target_filename)g_strdup_inline (target_filename);
6385
6386 // Start UNDO-REDO
6387 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6388 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEEMPTYFILE, 1);
6389 }
6390 // End UNDO-REDO
6391
6392 g_io_scheduler_push_job (create_job,
6393 job,
6394 NULL((void*)0), /* destroy notify */
6395 0,
6396 job->common.cancellable);
6397}
6398
6399
6400
6401static void
6402delete_trash_file (CommonJob *job,
6403 GFile *file,
6404 gboolean del_file,
6405 gboolean del_children)
6406{
6407 caja_progress_info_get_ready (job->progress);
6408
6409 if (job_aborted (job)) {
6410 return;
6411 }
6412
6413 if (del_children) {
6414 GFileEnumerator *enumerator;
6415
6416 enumerator = g_file_enumerate_children (file,
6417 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" ","
6418 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
6419 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6420 job->cancellable,
6421 NULL((void*)0));
6422 if (enumerator) {
6423 GFileInfo *info = NULL((void*)0);
6424 GFile *child = NULL((void*)0);
6425
6426 while (!job_aborted (job) &&
6427 (info = g_file_enumerator_next_file (enumerator, job->cancellable, NULL((void*)0))) != NULL((void*)0)) {
6428 child = g_file_get_child (file,
6429 g_file_info_get_name (info));
6430 delete_trash_file (job, child, TRUE(!(0)),
6431 g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY);
6432 g_object_unref (child);
6433 g_object_unref (info);
6434 }
6435 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
6436 g_object_unref (enumerator);
6437 }
6438 }
6439
6440 if (!job_aborted (job) && del_file) {
6441 g_file_delete (file, job->cancellable, NULL((void*)0));
6442 }
6443}
6444
6445static gboolean
6446empty_trash_job_done (gpointer user_data)
6447{
6448 EmptyTrashJob *job;
6449
6450 job = user_data;
6451
6452 g_list_free_full (job->trash_dirs, g_object_unref);
6453
6454 if (job->done_callback) {
6455 job->done_callback (job->done_callback_data);
6456 }
6457
6458 caja_undostack_manager_trash_has_emptied(caja_undostack_manager_instance());
6459
6460 finalize_common ((CommonJob *)job);
6461 return FALSE(0);
6462}
6463
6464static gboolean
6465empty_trash_job (GIOSchedulerJob *io_job,
6466 GCancellable *cancellable,
6467 gpointer user_data)
6468{
6469 EmptyTrashJob *job = user_data;
6470 CommonJob *common;
6471 GList *l;
6472 gboolean confirmed;
6473
6474 common = (CommonJob *)job;
6475 common->io_job = io_job;
6476
6477 caja_progress_info_start (job->common.progress);
6478
6479 if (job->should_confirm) {
6480 confirmed = confirm_empty_trash (common);
6481 } else {
6482 confirmed = TRUE(!(0));
6483 }
6484 if (confirmed) {
6485 for (l = job->trash_dirs;
6486 l != NULL((void*)0) && !job_aborted (common);
6487 l = l->next) {
6488 delete_trash_file (common, l->data, FALSE(0), TRUE(!(0)));
6489 }
6490 }
6491
6492 g_io_scheduler_job_send_to_mainloop_async (io_job,
6493 empty_trash_job_done,
6494 job,
6495 NULL((void*)0));
6496
6497 return FALSE(0);
6498}
6499
6500void
6501caja_file_operations_empty_trash (GtkWidget *parent_view)
6502{
6503 EmptyTrashJob *job;
6504 GtkWindow *parent_window;
6505
6506 parent_window = NULL((void*)0);
6507 if (parent_view) {
6508 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6509 }
6510
6511 job = op_job_new (EmptyTrashJob, parent_window, TRUE, FALSE)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
, (!(0)), (0))))
;
6512 job->trash_dirs = g_list_prepend (job->trash_dirs,
6513 g_file_new_for_uri ("trash:"));
6514 job->should_confirm = TRUE(!(0));
6515
6516 inhibit_power_manager ((CommonJob *)job, _("Emptying Trash")dcgettext (((void*)0), "Emptying Trash", 5));
6517
6518 g_io_scheduler_push_job (empty_trash_job,
6519 job,
6520 NULL((void*)0),
6521 0,
6522 NULL((void*)0));
6523}
6524
6525static gboolean
6526mark_trusted_job_done (gpointer user_data)
6527{
6528 MarkTrustedJob *job = user_data;
6529
6530 g_object_unref (job->file);
6531
6532 if (job->done_callback) {
6533 job->done_callback (job->done_callback_data);
6534 }
6535
6536 finalize_common ((CommonJob *)job);
6537 return FALSE(0);
6538}
6539
6540#define TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
6541
6542static void
6543mark_desktop_file_trusted (CommonJob *common,
6544 GCancellable *cancellable,
6545 GFile *file,
6546 gboolean interactive)
6547{
6548 char *contents, *new_contents;
6549 gsize length, new_length;
6550 GError *error;
6551 guint32 current_perms, new_perms;
6552 int response;
6553 GFileInfo *info;
6554
6555 retry:
6556 caja_progress_info_get_ready (common->progress);
6557
6558 error = NULL((void*)0);
6559 if (!g_file_load_contents (file,
6560 cancellable,
6561 &contents, &length,
6562 NULL((void*)0), &error)) {
6563 if (interactive) {
6564 response = run_error (common,
6565 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6566 error->message,
6567 NULL((void*)0),
6568 FALSE(0),
6569 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6570 NULL((void*)0));
6571 } else {
6572 response = 0;
6573 }
6574
6575
6576 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6577 abort_job (common);
6578 } else if (response == 1) {
6579 goto retry;
6580 } else {
6581 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6581, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6582 }
6583
6584 goto out;
6585 }
6586
6587 if (!g_str_has_prefix (contents, "#!")(__builtin_constant_p ("#!")? __extension__ ({ const char * const
__str = (contents); const char * const __prefix = ("#!"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_49
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_49
= 1; else _g_boolean_var_49 = 0; _g_boolean_var_49; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
contents, "#!") )
) {
6588 new_length = length + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n") + 1;
6589 new_contents = g_malloc0 (new_length);
6590
6591 g_strlcpy (new_contents, TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n", new_length);
6592 memcpy (new_contents + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n"),
6593 contents, length);
6594
6595 if (!g_file_replace_contents (file,
6596 new_contents,
6597 new_length,
6598 NULL((void*)0),
6599 FALSE(0), 0,
6600 NULL((void*)0), cancellable, &error)) {
6601 g_free (contents);
6602 g_free (new_contents);
6603
6604 if (interactive) {
6605 response = run_error (common,
6606 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6607 error->message,
6608 NULL((void*)0),
6609 FALSE(0),
6610 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6611 NULL((void*)0));
6612 } else {
6613 response = 0;
6614 }
6615
6616 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6617 abort_job (common);
6618 } else if (response == 1) {
6619 goto retry;
6620 } else {
6621 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6621, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6622 }
6623
6624 goto out;
6625 }
6626 g_free (new_contents);
6627
6628 }
6629 g_free (contents);
6630
6631 info = g_file_query_info (file,
6632 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
6633 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6634 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6635 common->cancellable,
6636 &error);
6637
6638 if (info == NULL((void*)0)) {
6639 if (interactive) {
6640 response = run_error (common,
6641 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6642 error->message,
6643 NULL((void*)0),
6644 FALSE(0),
6645 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6646 NULL((void*)0));
6647 } else {
6648 response = 0;
6649 }
6650
6651 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6652 abort_job (common);
6653 } else if (response == 1) {
6654 goto retry;
6655 } else {
6656 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6656, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6657 }
6658
6659 goto out;
6660 }
6661
6662
6663 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
6664 current_perms = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
6665 new_perms = current_perms | S_IXGRP(0100 >> 3) | S_IXUSR0100 | S_IXOTH((0100 >> 3) >> 3);
6666
6667 if ((current_perms != new_perms) &&
6668 !g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6669 new_perms, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6670 common->cancellable, &error))
6671 {
6672 g_object_unref (info);
6673
6674 if (interactive) {
6675 response = run_error (common,
6676 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6677 error->message,
6678 NULL((void*)0),
6679 FALSE(0),
6680 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6681 NULL((void*)0));
6682 } else {
6683 response = 0;
6684 }
6685
6686 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6687 abort_job (common);
6688 } else if (response == 1) {
6689 goto retry;
6690 } else {
6691 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6691, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6692 }
6693
6694 goto out;
6695 }
6696 }
6697 g_object_unref (info);
6698
6699 g_file_set_attribute_string (file,
6700 "metadata::" CAJA_METADATA_KEY_TRUSTED_LAUNCHER"caja-trusted-launcher", "true",
6701 G_FILE_QUERY_INFO_NONE,
6702 cancellable,
6703 NULL((void*)0));
6704 out:
6705 ;
6706}
6707
6708static gboolean
6709mark_trusted_job (GIOSchedulerJob *io_job,
6710 GCancellable *cancellable,
6711 gpointer user_data)
6712{
6713 MarkTrustedJob *job = user_data;
6714 CommonJob *common;
6715
6716 common = (CommonJob *)job;
6717 common->io_job = io_job;
6718
6719 caja_progress_info_start (job->common.progress);
6720
6721 mark_desktop_file_trusted (common,
6722 cancellable,
6723 job->file,
6724 job->interactive);
6725
6726 g_io_scheduler_job_send_to_mainloop_async (io_job,
6727 mark_trusted_job_done,
6728 job,
6729 NULL((void*)0));
6730
6731 return FALSE(0);
6732}
6733
6734void
6735caja_file_mark_desktop_file_trusted (GFile *file,
6736 GtkWindow *parent_window,
6737 gboolean interactive,
6738 CajaOpCallback done_callback,
6739 gpointer done_callback_data)
6740{
6741 MarkTrustedJob *job;
6742
6743 job = op_job_new (MarkTrustedJob, parent_window, TRUE, FALSE)((MarkTrustedJob *)(init_common (sizeof(MarkTrustedJob), parent_window
, (!(0)), (0))))
;
1
Calling 'init_common'
6744 job->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
6745 job->interactive = interactive;
6746 job->done_callback = done_callback;
6747 job->done_callback_data = done_callback_data;
6748
6749 g_io_scheduler_push_job (mark_trusted_job,
6750 job,
6751 NULL((void*)0),
6752 0,
6753 NULL((void*)0));
6754}
6755
6756#if !defined (CAJA_OMIT_SELF_CHECK)
6757
6758void
6759caja_self_check_file_operations (void)
6760{
6761 setlocale (LC_MESSAGES5, "C");
6762
6763
6764 /* test the next duplicate name generator */
6765 EEL_CHECK_STRING_RESULT (get_duplicate_name (" (copy)", 1, -1), " (another copy)")do { eel_before_check ("get_duplicate_name (\" (copy)\", 1, -1)"
, "caja-file-operations.c", 6765); eel_check_string_result (get_duplicate_name
(" (copy)", 1, -1), " (another copy)"); } while (0)
;
6766 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo", 1, -1), "foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo\", 1, -1)",
"caja-file-operations.c", 6766); eel_check_string_result (get_duplicate_name
("foo", 1, -1), "foo (copy)"); } while (0)
;
6767 EEL_CHECK_STRING_RESULT (get_duplicate_name (".bashrc", 1, -1), ".bashrc (copy)")do { eel_before_check ("get_duplicate_name (\".bashrc\", 1, -1)"
, "caja-file-operations.c", 6767); eel_check_string_result (get_duplicate_name
(".bashrc", 1, -1), ".bashrc (copy)"); } while (0)
;
6768 EEL_CHECK_STRING_RESULT (get_duplicate_name (".foo.txt", 1, -1), ".foo (copy).txt")do { eel_before_check ("get_duplicate_name (\".foo.txt\", 1, -1)"
, "caja-file-operations.c", 6768); eel_check_string_result (get_duplicate_name
(".foo.txt", 1, -1), ".foo (copy).txt"); } while (0)
;
6769 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo", 1, -1), "foo foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo foo\", 1, -1)"
, "caja-file-operations.c", 6769); eel_check_string_result (get_duplicate_name
("foo foo", 1, -1), "foo foo (copy)"); } while (0)
;
6770 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo.txt", 1, -1), "foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo.txt\", 1, -1)"
, "caja-file-operations.c", 6770); eel_check_string_result (get_duplicate_name
("foo.txt", 1, -1), "foo (copy).txt"); } while (0)
;
6771 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt\", 1, -1)"
, "caja-file-operations.c", 6771); eel_check_string_result (get_duplicate_name
("foo foo.txt", 1, -1), "foo foo (copy).txt"); } while (0)
;
6772 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt txt\", 1, -1)"
, "caja-file-operations.c", 6772); eel_check_string_result (get_duplicate_name
("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt"); } while
(0)
;
6773 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...txt", 1, -1), "foo (copy)...txt")do { eel_before_check ("get_duplicate_name (\"foo...txt\", 1, -1)"
, "caja-file-operations.c", 6773); eel_check_string_result (get_duplicate_name
("foo...txt", 1, -1), "foo (copy)...txt"); } while (0)
;
6774 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...", 1, -1), "foo (copy)...")do { eel_before_check ("get_duplicate_name (\"foo...\", 1, -1)"
, "caja-file-operations.c", 6774); eel_check_string_result (get_duplicate_name
("foo...", 1, -1), "foo (copy)..."); } while (0)
;
6775 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo. (copy)", 1, -1), "foo. (another copy)")do { eel_before_check ("get_duplicate_name (\"foo. (copy)\", 1, -1)"
, "caja-file-operations.c", 6775); eel_check_string_result (get_duplicate_name
("foo. (copy)", 1, -1), "foo. (another copy)"); } while (0)
;
6776 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy)", 1, -1), "foo (another copy)")do { eel_before_check ("get_duplicate_name (\"foo (copy)\", 1, -1)"
, "caja-file-operations.c", 6776); eel_check_string_result (get_duplicate_name
("foo (copy)", 1, -1), "foo (another copy)"); } while (0)
;
6777 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy).txt", 1, -1), "foo (another copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (copy).txt\", 1, -1)"
, "caja-file-operations.c", 6777); eel_check_string_result (get_duplicate_name
("foo (copy).txt", 1, -1), "foo (another copy).txt"); } while
(0)
;
6778 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy)", 1, -1), "foo (3rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (another copy)\", 1, -1)"
, "caja-file-operations.c", 6778); eel_check_string_result (get_duplicate_name
("foo (another copy)", 1, -1), "foo (3rd copy)"); } while (0
)
;
6779 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy).txt", 1, -1), "foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (another copy).txt\", 1, -1)"
, "caja-file-operations.c", 6779); eel_check_string_result (get_duplicate_name
("foo (another copy).txt", 1, -1), "foo (3rd copy).txt"); } while
(0)
;
6780 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (another copy).txt\", 1, -1)"
, "caja-file-operations.c", 6780); eel_check_string_result (get_duplicate_name
("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt"
); } while (0)
;
6781 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy)", 1, -1), "foo (14th copy)")do { eel_before_check ("get_duplicate_name (\"foo (13th copy)\", 1, -1)"
, "caja-file-operations.c", 6781); eel_check_string_result (get_duplicate_name
("foo (13th copy)", 1, -1), "foo (14th copy)"); } while (0)
;
6782 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy).txt", 1, -1), "foo (14th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (13th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6782); eel_check_string_result (get_duplicate_name
("foo (13th copy).txt", 1, -1), "foo (14th copy).txt"); } while
(0)
;
6783 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy)", 1, -1), "foo (22nd copy)")do { eel_before_check ("get_duplicate_name (\"foo (21st copy)\", 1, -1)"
, "caja-file-operations.c", 6783); eel_check_string_result (get_duplicate_name
("foo (21st copy)", 1, -1), "foo (22nd copy)"); } while (0)
;
6784 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (21st copy).txt\", 1, -1)"
, "caja-file-operations.c", 6784); eel_check_string_result (get_duplicate_name
("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt"); } while
(0)
;
6785 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy)", 1, -1), "foo (23rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy)\", 1, -1)"
, "caja-file-operations.c", 6785); eel_check_string_result (get_duplicate_name
("foo (22nd copy)", 1, -1), "foo (23rd copy)"); } while (0)
;
6786 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6786); eel_check_string_result (get_duplicate_name
("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt"); } while
(0)
;
6787 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy)", 1, -1), "foo (24th copy)")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy)\", 1, -1)"
, "caja-file-operations.c", 6787); eel_check_string_result (get_duplicate_name
("foo (23rd copy)", 1, -1), "foo (24th copy)"); } while (0)
;
6788 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6788); eel_check_string_result (get_duplicate_name
("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt"); } while
(0)
;
6789 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy)", 1, -1), "foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo (24th copy)\", 1, -1)"
, "caja-file-operations.c", 6789); eel_check_string_result (get_duplicate_name
("foo (24th copy)", 1, -1), "foo (25th copy)"); } while (0)
;
6790 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy).txt", 1, -1), "foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (24th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6790); eel_check_string_result (get_duplicate_name
("foo (24th copy).txt", 1, -1), "foo (25th copy).txt"); } while
(0)
;
6791 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy)", 1, -1), "foo foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy)\", 1, -1)"
, "caja-file-operations.c", 6791); eel_check_string_result (get_duplicate_name
("foo foo (24th copy)", 1, -1), "foo foo (25th copy)"); } while
(0)
;
6792 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6792); eel_check_string_result (get_duplicate_name
("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt"
); } while (0)
;
6793 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (100000000000000th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6793); eel_check_string_result (get_duplicate_name
("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt"
); } while (0)
;
6794 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy)", 1, -1), "foo (11th copy)")do { eel_before_check ("get_duplicate_name (\"foo (10th copy)\", 1, -1)"
, "caja-file-operations.c", 6794); eel_check_string_result (get_duplicate_name
("foo (10th copy)", 1, -1), "foo (11th copy)"); } while (0)
;
6795 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy).txt", 1, -1), "foo (11th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (10th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6795); eel_check_string_result (get_duplicate_name
("foo (10th copy).txt", 1, -1), "foo (11th copy).txt"); } while
(0)
;
6796 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy)", 1, -1), "foo (12th copy)")do { eel_before_check ("get_duplicate_name (\"foo (11th copy)\", 1, -1)"
, "caja-file-operations.c", 6796); eel_check_string_result (get_duplicate_name
("foo (11th copy)", 1, -1), "foo (12th copy)"); } while (0)
;
6797 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy).txt", 1, -1), "foo (12th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (11th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6797); eel_check_string_result (get_duplicate_name
("foo (11th copy).txt", 1, -1), "foo (12th copy).txt"); } while
(0)
;
6798 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy)", 1, -1), "foo (13th copy)")do { eel_before_check ("get_duplicate_name (\"foo (12th copy)\", 1, -1)"
, "caja-file-operations.c", 6798); eel_check_string_result (get_duplicate_name
("foo (12th copy)", 1, -1), "foo (13th copy)"); } while (0)
;
6799 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy).txt", 1, -1), "foo (13th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (12th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6799); eel_check_string_result (get_duplicate_name
("foo (12th copy).txt", 1, -1), "foo (13th copy).txt"); } while
(0)
;
6800 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy)", 1, -1), "foo (111th copy)")do { eel_before_check ("get_duplicate_name (\"foo (110th copy)\", 1, -1)"
, "caja-file-operations.c", 6800); eel_check_string_result (get_duplicate_name
("foo (110th copy)", 1, -1), "foo (111th copy)"); } while (0
)
;
6801 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy).txt", 1, -1), "foo (111th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (110th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6801); eel_check_string_result (get_duplicate_name
("foo (110th copy).txt", 1, -1), "foo (111th copy).txt"); } while
(0)
;
6802 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy)", 1, -1), "foo (123rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy)\", 1, -1)"
, "caja-file-operations.c", 6802); eel_check_string_result (get_duplicate_name
("foo (122nd copy)", 1, -1), "foo (123rd copy)"); } while (0
)
;
6803 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6803); eel_check_string_result (get_duplicate_name
("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt"); } while
(0)
;
6804 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy)", 1, -1), "foo (124th copy)")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy)\", 1, -1)"
, "caja-file-operations.c", 6804); eel_check_string_result (get_duplicate_name
("foo (123rd copy)", 1, -1), "foo (124th copy)"); } while (0
)
;
6805 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6805); eel_check_string_result (get_duplicate_name
("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt"); } while
(0)
;
6806
6807 setlocale (LC_MESSAGES5, "");
6808}
6809
6810#endif
diff --git a/2024-07-29-023715-6438-1/report-4215de.html b/2024-07-29-023715-6438-1/report-4215de.html new file mode 100644 index 000000000..bd0d3eabe --- /dev/null +++ b/2024-07-29-023715-6438-1/report-4215de.html @@ -0,0 +1,2583 @@ + + + +caja-query-editor.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-query-editor.c
Warning:line 1047, column 9
Value stored to 'model' 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 caja-query-editor.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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-query-editor.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/*
3 * Copyright (C) 2005 Red Hat, Inc.
4 *
5 * Caja is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * Caja 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 GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; see the file COPYING. If not,
17 * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 * Author: Alexander Larsson <alexl@redhat.com>
21 *
22 */
23
24#include <config.h>
25#include <string.h>
26
27#include <glib/gi18n.h>
28#include <gio/gio.h>
29#include <gdk/gdkkeysyms.h>
30#include <gtk/gtk.h>
31
32#include <eel/eel-gtk-macros.h>
33#include <eel/eel-glib-extensions.h>
34#include <eel/eel-stock-dialogs.h>
35
36#include <libcaja-private/caja-global-preferences.h>
37
38#include "caja-query-editor.h"
39#include "caja-src-marshal.h"
40#include "caja-window-slot.h"
41
42enum
43{
44 DURATION_INVALID,
45 DURATION_ONE_HOUR,
46 DURATION_ONE_DAY,
47 DURATION_ONE_WEEK,
48 DURATION_ONE_MONTH,
49 DURATION_SIX_MONTHS,
50 DURATION_ONE_YEAR,
51};
52
53typedef enum
54{
55 CAJA_QUERY_EDITOR_ROW_LOCATION,
56 CAJA_QUERY_EDITOR_ROW_TYPE,
57 CAJA_QUERY_EDITOR_ROW_TAGS,
58 CAJA_QUERY_EDITOR_ROW_TIME_MODIFIED,
59 CAJA_QUERY_EDITOR_ROW_SIZE,
60 CAJA_QUERY_EDITOR_ROW_CONTAINED_TEXT,
61
62 CAJA_QUERY_EDITOR_ROW_LAST
63} CajaQueryEditorRowType;
64
65typedef struct
66{
67 CajaQueryEditorRowType type;
68 CajaQueryEditor *editor;
69 GtkWidget *hbox;
70 GtkWidget *combo;
71
72 GtkWidget *type_widget;
73
74 void *data;
75} CajaQueryEditorRow;
76
77
78typedef struct
79{
80 const char *name;
81 GtkWidget * (*create_widgets) (CajaQueryEditorRow *row);
82 void (*add_to_query) (CajaQueryEditorRow *row,
83 CajaQuery *query);
84 void (*free_data) (CajaQueryEditorRow *row);
85 void (*add_rows_from_query) (CajaQueryEditor *editor,
86 CajaQuery *query);
87} CajaQueryEditorRowOps;
88
89struct CajaQueryEditorDetails
90{
91 gboolean is_indexed;
92 GtkWidget *entry;
93 gboolean change_frozen;
94 guint typing_timeout_id;
95 gboolean is_visible;
96 GtkWidget *invisible_vbox;
97 GtkWidget *visible_vbox;
98
99 GList *rows;
100 char *last_set_query_text;
101
102 CajaSearchBar *bar;
103 CajaWindowSlot *slot;
104};
105
106enum
107{
108 CHANGED,
109 CANCEL,
110 LAST_SIGNAL
111};
112
113static guint signals[LAST_SIGNAL] = { 0 };
114
115static void caja_query_editor_class_init (CajaQueryEditorClass *class);
116static void caja_query_editor_init (CajaQueryEditor *editor);
117
118static void go_search_cb (GtkButton *clicked_button, CajaQueryEditor *editor);
119
120static void entry_activate_cb (GtkWidget *entry, CajaQueryEditor *editor);
121static void entry_changed_cb (GtkWidget *entry, CajaQueryEditor *editor);
122static void caja_query_editor_changed_force (CajaQueryEditor *editor,
123 gboolean force);
124static void caja_query_editor_changed (CajaQueryEditor *editor);
125static CajaQueryEditorRow * caja_query_editor_add_row (CajaQueryEditor *editor,
126 CajaQueryEditorRowType type);
127
128static GtkWidget *location_row_create_widgets (CajaQueryEditorRow *row);
129static void location_row_add_to_query (CajaQueryEditorRow *row,
130 CajaQuery *query);
131static void location_row_free_data (CajaQueryEditorRow *row);
132static void location_add_rows_from_query (CajaQueryEditor *editor,
133 CajaQuery *query);
134
135static GtkWidget *tags_row_create_widgets (CajaQueryEditorRow *row);
136static void tags_row_add_to_query (CajaQueryEditorRow *row,
137 CajaQuery *query);
138static void tags_row_free_data (CajaQueryEditorRow *row);
139static void tags_add_rows_from_query (CajaQueryEditor *editor,
140 CajaQuery *query);
141
142static GtkWidget *type_row_create_widgets (CajaQueryEditorRow *row);
143static void type_row_add_to_query (CajaQueryEditorRow *row,
144 CajaQuery *query);
145static void type_row_free_data (CajaQueryEditorRow *row);
146static void type_add_rows_from_query (CajaQueryEditor *editor,
147 CajaQuery *query);
148static GtkWidget *modtime_row_create_widgets(CajaQueryEditorRow *row);
149static void modtime_row_add_to_query(CajaQueryEditorRow *row,
150 CajaQuery *query);
151static void modtime_row_free_data(CajaQueryEditorRow *row);
152static void modtime_add_rows_from_query(CajaQueryEditor *editor,
153 CajaQuery *query);
154static GtkWidget *size_row_create_widgets(CajaQueryEditorRow *row);
155static void size_row_add_to_query(CajaQueryEditorRow *row,
156 CajaQuery *query);
157static void size_row_free_data(CajaQueryEditorRow *row);
158static void size_add_rows_from_query(CajaQueryEditor *editor,
159 CajaQuery *query);
160
161static GtkWidget *contained_text_row_create_widgets(CajaQueryEditorRow *row);
162static void contained_text_row_add_to_query(CajaQueryEditorRow *row,
163 CajaQuery *query);
164static void contained_text_row_free_data(CajaQueryEditorRow *row);
165static void contained_text_add_rows_from_query(CajaQueryEditor *editor,
166 CajaQuery *query);
167
168static CajaQueryEditorRowOps row_type[] =
169{
170 {
171 N_("Location")("Location"),
172 location_row_create_widgets,
173 location_row_add_to_query,
174 location_row_free_data,
175 location_add_rows_from_query
176 },
177 {
178 N_("File Type")("File Type"),
179 type_row_create_widgets,
180 type_row_add_to_query,
181 type_row_free_data,
182 type_add_rows_from_query
183 },
184 {
185 N_("Tags")("Tags"),
186 tags_row_create_widgets,
187 tags_row_add_to_query,
188 tags_row_free_data,
189 tags_add_rows_from_query
190 },
191 {
192 N_("Modification Time")("Modification Time"),
193 modtime_row_create_widgets,
194 modtime_row_add_to_query,
195 modtime_row_free_data,
196 modtime_add_rows_from_query
197 },
198 {
199 N_("Size")("Size"),
200 size_row_create_widgets,
201 size_row_add_to_query,
202 size_row_free_data,
203 size_add_rows_from_query
204 },
205 {
206 N_("Contained text")("Contained text"),
207 contained_text_row_create_widgets,
208 contained_text_row_add_to_query,
209 contained_text_row_free_data,
210 contained_text_add_rows_from_query
211 }
212};
213
214EEL_CLASS_BOILERPLATE (CajaQueryEditor,static gpointer parent_class; GType caja_query_editor_get_type
(void) { GType parent_type; static GType type; if (type == 0
) { static GTypeInfo info = { sizeof (CajaQueryEditorClass), (
(void*)0), ((void*)0), (GClassInitFunc) caja_query_editor_class_init
, ((void*)0), ((void*)0), sizeof (CajaQueryEditor), 0, (GInstanceInitFunc
) caja_query_editor_init, ((void*)0) }; parent_type = ((gtk_box_get_type
())); type = g_type_register_static (parent_type, "CajaQueryEditor"
, &info, 0); parent_class = g_type_class_ref (parent_type
); } return type; }
215 caja_query_editor,static gpointer parent_class; GType caja_query_editor_get_type
(void) { GType parent_type; static GType type; if (type == 0
) { static GTypeInfo info = { sizeof (CajaQueryEditorClass), (
(void*)0), ((void*)0), (GClassInitFunc) caja_query_editor_class_init
, ((void*)0), ((void*)0), sizeof (CajaQueryEditor), 0, (GInstanceInitFunc
) caja_query_editor_init, ((void*)0) }; parent_type = ((gtk_box_get_type
())); type = g_type_register_static (parent_type, "CajaQueryEditor"
, &info, 0); parent_class = g_type_class_ref (parent_type
); } return type; }
216 GTK_TYPE_BOX)static gpointer parent_class; GType caja_query_editor_get_type
(void) { GType parent_type; static GType type; if (type == 0
) { static GTypeInfo info = { sizeof (CajaQueryEditorClass), (
(void*)0), ((void*)0), (GClassInitFunc) caja_query_editor_class_init
, ((void*)0), ((void*)0), sizeof (CajaQueryEditor), 0, (GInstanceInitFunc
) caja_query_editor_init, ((void*)0) }; parent_type = ((gtk_box_get_type
())); type = g_type_register_static (parent_type, "CajaQueryEditor"
, &info, 0); parent_class = g_type_class_ref (parent_type
); } return type; }
217
218static void
219caja_query_editor_finalize (GObject *object)
220{
221 CajaQueryEditor *editor;
222
223 editor = CAJA_QUERY_EDITOR (object)((((CajaQueryEditor*) (void *) ((object)))));
224
225 g_free (editor->details);
226
227 EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object))do { if (((((GObjectClass*) (void *) ((parent_class)))))->
finalize != ((void*)0)) { (* ((((GObjectClass*) (void *) ((parent_class
)))))->finalize) (object); } } while (0)
;
228}
229
230static void
231caja_query_editor_dispose (GObject *object)
232{
233 CajaQueryEditor *editor;
234
235 editor = CAJA_QUERY_EDITOR (object)((((CajaQueryEditor*) (void *) ((object)))));
236
237 if (editor->details->typing_timeout_id)
238 {
239 g_source_remove (editor->details->typing_timeout_id);
240 editor->details->typing_timeout_id = 0;
241 }
242
243 if (editor->details->bar != NULL((void*)0))
244 {
245 g_signal_handlers_disconnect_by_func (editor->details->entry,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
246 entry_activate_cb,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
247 editor)g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
;
248 g_signal_handlers_disconnect_by_func (editor->details->entry,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
249 entry_changed_cb,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
250 editor)g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
;
251
252 caja_search_bar_return_entry (editor->details->bar);
253 eel_remove_weak_pointer (&editor->details->bar);
254 }
255
256 EEL_CALL_PARENT (G_OBJECT_CLASS, dispose, (object))do { if (((((GObjectClass*) (void *) ((parent_class)))))->
dispose != ((void*)0)) { (* ((((GObjectClass*) (void *) ((parent_class
)))))->dispose) (object); } } while (0)
;
257}
258
259static void
260caja_query_editor_class_init (CajaQueryEditorClass *class)
261{
262 GObjectClass *gobject_class;
263 GtkBindingSet *binding_set;
264
265 gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))));
266 gobject_class->finalize = caja_query_editor_finalize;
267 gobject_class->dispose = caja_query_editor_dispose;
268
269 signals[CHANGED] =
270 g_signal_new ("changed",
271 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
272 G_SIGNAL_RUN_LAST,
273 G_STRUCT_OFFSET (CajaQueryEditorClass, changed)((glong) __builtin_offsetof(CajaQueryEditorClass, changed)),
274 NULL((void*)0), NULL((void*)0),
275 caja_src_marshal_VOID__OBJECT_BOOLEAN,
276 G_TYPE_NONE((GType) ((1) << (2))), 2, CAJA_TYPE_QUERY(caja_query_get_type ()), G_TYPE_BOOLEAN((GType) ((5) << (2))));
277
278 signals[CANCEL] =
279 g_signal_new ("cancel",
280 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
281 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
282 G_STRUCT_OFFSET (CajaQueryEditorClass, cancel)((glong) __builtin_offsetof(CajaQueryEditorClass, cancel)),
283 NULL((void*)0), NULL((void*)0),
284 g_cclosure_marshal_VOID__VOID,
285 G_TYPE_NONE((GType) ((1) << (2))), 0);
286
287 binding_set = gtk_binding_set_by_class (class);
288 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape0xff1b, 0, "cancel", 0);
289}
290
291static void
292entry_activate_cb (GtkWidget *entry, CajaQueryEditor *editor)
293{
294 if (editor->details->typing_timeout_id)
295 {
296 g_source_remove (editor->details->typing_timeout_id);
297 editor->details->typing_timeout_id = 0;
298 }
299
300 caja_query_editor_changed_force (editor, TRUE(!(0)));
301}
302
303static gboolean
304typing_timeout_cb (gpointer user_data)
305{
306 CajaQueryEditor *editor;
307
308 editor = CAJA_QUERY_EDITOR (user_data)((((CajaQueryEditor*) (void *) ((user_data)))));
309
310 caja_query_editor_changed (editor);
311
312 editor->details->typing_timeout_id = 0;
313
314 return FALSE(0);
315}
316
317#define TYPING_TIMEOUT750 750
318
319static void
320entry_changed_cb (GtkWidget *entry, CajaQueryEditor *editor)
321{
322 if (editor->details->change_frozen)
323 {
324 return;
325 }
326
327 if (editor->details->typing_timeout_id)
328 {
329 g_source_remove (editor->details->typing_timeout_id);
330 }
331
332 editor->details->typing_timeout_id =
333 g_timeout_add (TYPING_TIMEOUT750,
334 typing_timeout_cb,
335 editor);
336}
337
338static void
339edit_clicked (GtkButton *button, CajaQueryEditor *editor)
340{
341 caja_query_editor_set_visible (editor, TRUE(!(0)));
342 caja_query_editor_grab_focus (editor);
343}
344
345/* Location */
346
347static GtkWidget *
348location_row_create_widgets (CajaQueryEditorRow *row)
349{
350 GtkWidget *chooser;
351
352 chooser = gtk_file_chooser_button_new (_("Select folder to search in")dcgettext (((void*)0), "Select folder to search in", 5),
353 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
354 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser)((((GtkFileChooser*) (void *) ((chooser))))), TRUE(!(0)));
355 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser)((((GtkFileChooser*) (void *) ((chooser))))),
356 g_get_home_dir ());
357 gtk_widget_show (chooser);
358
359 g_signal_connect_swapped (chooser, "current-folder-changed",g_signal_connect_data ((chooser), ("current-folder-changed"),
(((GCallback) (caja_query_editor_changed))), (row->editor
), ((void*)0), G_CONNECT_SWAPPED)
360 G_CALLBACK (caja_query_editor_changed),g_signal_connect_data ((chooser), ("current-folder-changed"),
(((GCallback) (caja_query_editor_changed))), (row->editor
), ((void*)0), G_CONNECT_SWAPPED)
361 row->editor)g_signal_connect_data ((chooser), ("current-folder-changed"),
(((GCallback) (caja_query_editor_changed))), (row->editor
), ((void*)0), G_CONNECT_SWAPPED)
;
362
363 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), chooser, FALSE(0), FALSE(0), 0);
364
365 return chooser;
366}
367
368static void
369location_row_add_to_query (CajaQueryEditorRow *row,
370 CajaQuery *query)
371{
372 char *folder, *uri;
373
374 folder = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (row->type_widget)((((GtkFileChooser*) (void *) ((row->type_widget))))));
375 if (folder == NULL((void*)0))
376 {
377 /* I don't know why, but i got NULL here on initial search in browser mode
378 even with the location set to the homedir in create_widgets... */
379 folder = g_strdup (g_get_home_dir ())g_strdup_inline (g_get_home_dir ());
380 }
381
382 uri = g_filename_to_uri (folder, NULL((void*)0), NULL((void*)0));
383 g_free (folder);
384
385 caja_query_set_location (query, uri);
386 g_free (uri);
387}
388
389static void
390location_row_free_data (CajaQueryEditorRow *row)
391{
392}
393
394static void
395location_add_rows_from_query (CajaQueryEditor *editor,
396 CajaQuery *query)
397{
398 CajaQueryEditorRow *row;
399 char *uri, *folder;
400
401 uri = caja_query_get_location (query);
402
403 if (uri == NULL((void*)0))
404 {
405 return;
406 }
407 folder = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
408 g_free (uri);
409 if (folder == NULL((void*)0))
410 {
411 return;
412 }
413
414 row = caja_query_editor_add_row (editor,
415 CAJA_QUERY_EDITOR_ROW_LOCATION);
416 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (row->type_widget)((((GtkFileChooser*) (void *) ((row->type_widget))))),
417 folder);
418
419 g_free (folder);
420}
421
422/* Tags */
423static void
424tags_entry_changed_cb (GtkWidget *entry, gpointer *data)
425{
426 /* remove commas from string */
427 const gchar *text = gtk_entry_get_text ( GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))));
428 if (g_strrstr (text, ",") == NULL((void*)0)) {
429 return;
430 }
431
432 gchar **words = g_strsplit (text, ",", -1);
433 gchar *sanitized = g_strjoinv ("", words);
434 g_strfreev (words);
435
436 gtk_entry_set_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))), sanitized);
437 g_free(sanitized);
438}
439
440#define MAX_TAGS_ENTRY_LEN4096 4096 // arbitrary value.
441
442static GtkWidget *
443tags_row_create_widgets (CajaQueryEditorRow *row)
444{
445 GtkWidget *entry = gtk_entry_new();
446 gtk_entry_set_max_length (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))), MAX_TAGS_ENTRY_LEN4096);
447 gtk_widget_set_tooltip_text (entry,
448 _("Tags separated by spaces. "dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
449 "Matches files that contains ALL specified tags.")dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
);
450
451 gtk_entry_set_placeholder_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))),
452 _("Tags separated by spaces. "dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
453 "Matches files that contains ALL specified tags.")dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
);
454
455 gtk_widget_show (entry);
456 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), entry, TRUE(!(0)), TRUE(!(0)), 0);
457 g_signal_connect (entry, "changed", G_CALLBACK (tags_entry_changed_cb), entry)g_signal_connect_data ((entry), ("changed"), (((GCallback) (tags_entry_changed_cb
))), (entry), ((void*)0), (GConnectFlags) 0)
;
458 g_signal_connect (entry, "activate", G_CALLBACK (go_search_cb), row->editor)g_signal_connect_data ((entry), ("activate"), (((GCallback) (
go_search_cb))), (row->editor), ((void*)0), (GConnectFlags
) 0)
;
459
460 return entry;
461}
462
463static void
464tags_row_add_to_query (CajaQueryEditorRow *row,
465 CajaQuery *query)
466{
467 GtkEntry *entry = GTK_ENTRY (row->type_widget)((((GtkEntry*) (void *) ((row->type_widget)))));
468 const gchar *tags = gtk_entry_get_text (entry);
469
470 char **strv = g_strsplit (tags, " ", -1);
471 guint len = g_strv_length (strv);
472 int i;
473
474 for (i = 0; i < len; ++i) {
475 strv[i] = g_strstrip (strv[i])g_strchomp (g_strchug (strv[i]));
476 if (strlen (strv[i]) > 0) {
477 caja_query_add_tag (query, strv[i]);
478 }
479 }
480 g_strfreev (strv);
481}
482
483static void
484tags_row_free_data (CajaQueryEditorRow *row)
485{
486}
487
488static gchar *
489xattr_tags_list_to_str (const GList *tags)
490{
491 gchar *result = NULL((void*)0);
492
493 const GList *tags_iter = NULL((void*)0);
494 for (tags_iter = tags; tags_iter; tags_iter = tags_iter->next) {
495 gchar *tmp;
496
497 if (result != NULL((void*)0)) {
498 tmp = g_strconcat (result, ",", tags_iter->data, NULL((void*)0));
499 g_free (result);
500 } else {
501 tmp = g_strdup (tags_iter->data)g_strdup_inline (tags_iter->data);
502 }
503
504 result = tmp;
505 }
506
507 return result;
508}
509
510static void
511tags_add_rows_from_query (CajaQueryEditor *editor,
512 CajaQuery *query)
513{
514 GList *tags = caja_query_get_tags (query);
515 if (tags == NULL((void*)0)) {
516 return;
517 }
518
519 CajaQueryEditorRow *row;
520 row = caja_query_editor_add_row (editor, CAJA_QUERY_EDITOR_ROW_TAGS);
521
522 gchar *tags_str = xattr_tags_list_to_str (tags);
523 g_list_free_full (tags, g_free);
524
525 gtk_entry_set_text (GTK_ENTRY (row->type_widget)((((GtkEntry*) (void *) ((row->type_widget))))), tags_str);
526 g_free (tags_str);
527}
528
529
530/* Type */
531
532static gboolean
533type_separator_func (GtkTreeModel *model,
534 GtkTreeIter *iter,
535 gpointer data)
536{
537 char *text;
538 gboolean res;
539
540 gtk_tree_model_get (model, iter, 0, &text, -1);
541
542 res = text != NULL((void*)0) && strcmp (text, "---") == 0;
543
544 g_free (text);
545 return res;
546}
547
548struct
549{
550 char *name;
551 char *mimetypes[20];
552} mime_type_groups[] =
553{
554 {
555 N_("Documents")("Documents"),
556 {
557 "application/rtf",
558 "application/msword",
559 "application/vnd.sun.xml.writer",
560 "application/vnd.sun.xml.writer.global",
561 "application/vnd.sun.xml.writer.template",
562 "application/vnd.oasis.opendocument.text",
563 "application/vnd.oasis.opendocument.text-template",
564 "application/x-abiword",
565 "application/x-applix-word",
566 "application/x-mswrite",
567 "application/docbook+xml",
568 "application/x-kword",
569 "application/x-kword-crypt",
570 "application/x-lyx",
571 NULL((void*)0)
572 }
573 },
574 {
575 N_("Music")("Music"),
576 {
577 "application/ogg",
578 "audio/ac3",
579 "audio/basic",
580 "audio/midi",
581 "audio/x-flac",
582 "audio/mp4",
583 "audio/mpeg",
584 "audio/x-mpeg",
585 "audio/x-ms-asx",
586 "audio/x-pn-realaudio",
587 NULL((void*)0)
588 }
589 },
590 {
591 N_("Video")("Video"),
592 {
593 "video/mp4",
594 "video/3gpp",
595 "video/mpeg",
596 "video/quicktime",
597 "video/vivo",
598 "video/x-avi",
599 "video/x-mng",
600 "video/x-ms-asf",
601 "video/x-ms-wmv",
602 "video/x-msvideo",
603 "video/x-nsv",
604 "video/x-real-video",
605 NULL((void*)0)
606 }
607 },
608 {
609 N_("Picture")("Picture"),
610 {
611 "application/vnd.oasis.opendocument.image",
612 "application/x-krita",
613 "image/bmp",
614 "image/cgm",
615 "image/gif",
616 "image/jpeg",
617 "image/jpeg2000",
618 "image/png",
619 "image/svg+xml",
620 "image/tiff",
621 "image/x-compressed-xcf",
622 "image/x-pcx",
623 "image/x-photo-cd",
624 "image/x-psd",
625 "image/x-tga",
626 "image/x-xcf",
627 NULL((void*)0)
628 }
629 },
630 {
631 N_("Illustration")("Illustration"),
632 {
633 "application/illustrator",
634 "application/vnd.corel-draw",
635 "application/vnd.stardivision.draw",
636 "application/vnd.oasis.opendocument.graphics",
637 "application/x-dia-diagram",
638 "application/x-karbon",
639 "application/x-killustrator",
640 "application/x-kivio",
641 "application/x-kontour",
642 "application/x-wpg",
643 NULL((void*)0)
644 }
645 },
646 {
647 N_("Spreadsheet")("Spreadsheet"),
648 {
649 "application/vnd.lotus-1-2-3",
650 "application/vnd.ms-excel",
651 "application/vnd.stardivision.calc",
652 "application/vnd.sun.xml.calc",
653 "application/vnd.oasis.opendocument.spreadsheet",
654 "application/x-applix-spreadsheet",
655 "application/x-gnumeric",
656 "application/x-kspread",
657 "application/x-kspread-crypt",
658 "application/x-quattropro",
659 "application/x-sc",
660 "application/x-siag",
661 NULL((void*)0)
662 }
663 },
664 {
665 N_("Presentation")("Presentation"),
666 {
667 "application/vnd.ms-powerpoint",
668 "application/vnd.sun.xml.impress",
669 "application/vnd.oasis.opendocument.presentation",
670 "application/x-magicpoint",
671 "application/x-kpresenter",
672 NULL((void*)0)
673 }
674 },
675 {
676 N_("Pdf / Postscript")("Pdf / Postscript"),
677 {
678 "application/pdf",
679 "application/postscript",
680 "application/x-dvi",
681 "image/x-eps",
682 NULL((void*)0)
683 }
684 },
685 {
686 N_("Text File")("Text File"),
687 {
688 "text/plain",
689 NULL((void*)0)
690 }
691 }
692};
693
694static void
695type_add_custom_type (CajaQueryEditorRow *row,
696 const char *mime_type,
697 const char *description,
698 GtkTreeIter *iter)
699{
700 GtkTreeModel *model;
701 GtkListStore *store;
702
703 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
704 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
705
706 gtk_list_store_append (store, iter);
707 gtk_list_store_set (store, iter,
708 0, description,
709 2, mime_type,
710 -1);
711}
712
713
714static void
715type_combo_changed (GtkComboBox *combo_box, CajaQueryEditorRow *row)
716{
717 GtkTreeIter iter;
718 gboolean other;
719 GtkTreeModel *model;
720
721 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
722 &iter))
723 {
724 return;
725 }
726
727 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
728 gtk_tree_model_get (model, &iter, 3, &other, -1);
729
730 if (other)
731 {
732 GList *mime_infos, *l;
733 GtkWidget *dialog;
734 GtkWidget *scrolled, *treeview;
735 GtkListStore *store;
736 GtkTreeViewColumn *column;
737 GtkCellRenderer *renderer;
738 GtkWidget *toplevel;
739 GtkTreeSelection *selection;
740
741 mime_infos = g_content_types_get_registered ();
742
743 store = gtk_list_store_new (2, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
744 for (l = mime_infos; l != NULL((void*)0); l = l->next)
745 {
746 GtkTreeIter iter;
747 char *mime_type = l->data;
748 char *description;
749
750 description = g_content_type_get_description (mime_type);
751 if (description == NULL((void*)0))
752 {
753 description = g_strdup (mime_type)g_strdup_inline (mime_type);
754 }
755
756 gtk_list_store_append (store, &iter);
757 gtk_list_store_set (store, &iter,
758 0, description,
759 1, mime_type,
760 -1);
761
762 g_free (mime_type);
763 g_free (description);
764 }
765 g_list_free (mime_infos);
766
767
768
769 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (combo_box)((((GtkWidget*) (void *) ((combo_box))))));
770
771 dialog = gtk_dialog_new ();
772 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), _("Select type")dcgettext (((void*)0), "Select type", 5));
773 gtk_window_set_transient_for (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), GTK_WINDOW (toplevel)((((GtkWindow*) (void *) ((toplevel))))));
774
775 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
776 _("_OK")dcgettext (((void*)0), "_OK", 5),
777 "gtk-ok",
778 GTK_RESPONSE_OK);
779
780 gtk_window_set_default_size (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), 400, 600);
781
782 scrolled = gtk_scrolled_window_new (NULL((void*)0), NULL((void*)0));
783 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
784 GTK_POLICY_AUTOMATIC,
785 GTK_POLICY_AUTOMATIC);
786 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
787 GTK_SHADOW_IN);
788 gtk_scrolled_window_set_overlay_scrolling (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
789 FALSE(0));
790
791 gtk_widget_show (scrolled);
792 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dialog)))))))))))
, scrolled, TRUE(!(0)), TRUE(!(0)), 6);
793
794 treeview = gtk_tree_view_new ();
795 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))),
796 GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))));
797 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store)((((GtkTreeSortable*) (void *) ((store))))), 0,
798 GTK_SORT_ASCENDING);
799
800 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))));
801 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
802
803
804 renderer = gtk_cell_renderer_text_new ();
805 column = gtk_tree_view_column_new_with_attributes ("Name",
806 renderer,
807 "text",
808 0,
809 NULL((void*)0));
810 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))), column);
811 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))), FALSE(0));
812
813 gtk_widget_show (treeview);
814 gtk_container_add (GTK_CONTAINER (scrolled)((((GtkContainer*) (void *) ((scrolled))))), treeview);
815
816 if (gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog)))))) == GTK_RESPONSE_OK)
817 {
818 char *mimetype, *description;
819
820 gtk_tree_selection_get_selected (selection, NULL((void*)0), &iter);
821 gtk_tree_model_get (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))), &iter,
822 0, &description,
823 1, &mimetype,
824 -1);
825
826 type_add_custom_type (row, mimetype, description, &iter);
827 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
828 &iter);
829 }
830 else
831 {
832 gtk_combo_box_set_active (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))), 0);
833 }
834
835 gtk_widget_destroy (dialog);
836 }
837
838 caja_query_editor_changed (row->editor);
839}
840
841static GtkWidget *
842type_row_create_widgets (CajaQueryEditorRow *row)
843{
844 GtkWidget *combo;
845 GtkCellRenderer *cell;
846 GtkListStore *store;
847 GtkTreeIter iter;
848 int i;
849
850 store = gtk_list_store_new (4, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_POINTER((GType) ((17) << (2))), G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_BOOLEAN((GType) ((5) << (2))));
851 combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))));
852 g_object_unref (store);
853
854 cell = gtk_cell_renderer_text_new ();
855 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
856 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell,
857 "text", 0,
858 NULL((void*)0));
859 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))),
860 type_separator_func,
861 NULL((void*)0), NULL((void*)0));
862
863 gtk_list_store_append (store, &iter);
864 gtk_list_store_set (store, &iter, 0, _("Any")dcgettext (((void*)0), "Any", 5), -1);
865 gtk_list_store_append (store, &iter);
866 gtk_list_store_set (store, &iter, 0, "---", -1);
867
868 for (i = 0; i < G_N_ELEMENTS (mime_type_groups)(sizeof (mime_type_groups) / sizeof ((mime_type_groups)[0])); i++)
869 {
870 gtk_list_store_append (store, &iter);
871 gtk_list_store_set (store, &iter,
872 0, gettext (mime_type_groups[i].name)dcgettext (((void*)0), mime_type_groups[i].name, 5),
873 1, mime_type_groups[i].mimetypes,
874 -1);
875 }
876
877 gtk_list_store_append (store, &iter);
878 gtk_list_store_set (store, &iter, 0, "---", -1);
879 gtk_list_store_append (store, &iter);
880 gtk_list_store_set (store, &iter, 0, _("Other Type...")dcgettext (((void*)0), "Other Type...", 5), 3, TRUE(!(0)), -1);
881
882 gtk_combo_box_set_active (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), 0);
883
884 g_signal_connect (combo, "changed",g_signal_connect_data ((combo), ("changed"), (((GCallback) (type_combo_changed
))), (row), ((void*)0), (GConnectFlags) 0)
885 G_CALLBACK (type_combo_changed),g_signal_connect_data ((combo), ("changed"), (((GCallback) (type_combo_changed
))), (row), ((void*)0), (GConnectFlags) 0)
886 row)g_signal_connect_data ((combo), ("changed"), (((GCallback) (type_combo_changed
))), (row), ((void*)0), (GConnectFlags) 0)
;
887
888 gtk_widget_show (combo);
889
890 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), combo, FALSE(0), FALSE(0), 0);
891
892 return combo;
893}
894
895static void
896type_row_add_to_query (CajaQueryEditorRow *row,
897 CajaQuery *query)
898{
899 GtkTreeIter iter;
900 char **mimetypes;
901 char *mimetype;
902 GtkTreeModel *model;
903
904 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
905 &iter))
906 {
907 return;
908 }
909
910 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
911 gtk_tree_model_get (model, &iter, 1, &mimetypes, 2, &mimetype, -1);
912
913 if (mimetypes != NULL((void*)0))
914 {
915 while (*mimetypes != NULL((void*)0))
916 {
917 caja_query_add_mime_type (query, *mimetypes);
918 mimetypes++;
919 }
920 }
921 if (mimetype)
922 {
923 caja_query_add_mime_type (query, mimetype);
924 g_free (mimetype);
925 }
926}
927
928static void
929type_row_free_data (CajaQueryEditorRow *row)
930{
931}
932
933static gboolean
934all_group_types_in_list (char **group_types, GList *mime_types)
935{
936 GList *l;
937 char **group_type;
938 char *mime_type;
939 gboolean found;
940
941 group_type = group_types;
942 while (*group_type != NULL((void*)0))
943 {
944 found = FALSE(0);
945
946 for (l = mime_types; l != NULL((void*)0); l = l->next)
947 {
948 mime_type = l->data;
949
950 if (strcmp (mime_type, *group_type) == 0)
951 {
952 found = TRUE(!(0));
953 break;
954 }
955 }
956
957 if (!found)
958 {
959 return FALSE(0);
960 }
961 group_type++;
962 }
963 return TRUE(!(0));
964}
965
966static GList *
967remove_group_types_from_list (char **group_types, GList *mime_types)
968{
969 GList *l, *next;
970 char **group_type;
971 char *mime_type;
972
973 group_type = group_types;
974 while (*group_type != NULL((void*)0))
975 {
976 for (l = mime_types; l != NULL((void*)0); l = next)
977 {
978 mime_type = l->data;
979 next = l->next;
980
981 if (strcmp (mime_type, *group_type) == 0)
982 {
983 mime_types = g_list_remove_link (mime_types, l);
984 g_free (mime_type);
985 break;
986 }
987 }
988
989 group_type++;
990 }
991 return mime_types;
992}
993
994
995static void
996type_add_rows_from_query (CajaQueryEditor *editor,
997 CajaQuery *query)
998{
999 GList *mime_types;
1000 char *mime_type;
1001 CajaQueryEditorRow *row;
1002 GtkTreeIter iter;
1003 int i;
1004 GtkTreeModel *model;
1005 GList *l;
1006
1007 mime_types = caja_query_get_mime_types (query);
1008
1009 if (mime_types == NULL((void*)0))
1010 {
1011 return;
1012 }
1013
1014 for (i = 0; i < G_N_ELEMENTS (mime_type_groups)(sizeof (mime_type_groups) / sizeof ((mime_type_groups)[0])); i++)
1015 {
1016 if (all_group_types_in_list (mime_type_groups[i].mimetypes,
1017 mime_types))
1018 {
1019 mime_types = remove_group_types_from_list (mime_type_groups[i].mimetypes,
1020 mime_types);
1021
1022 row = caja_query_editor_add_row (editor,
1023 CAJA_QUERY_EDITOR_ROW_TYPE);
1024
1025 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
1026
1027 gtk_tree_model_iter_nth_child (model, &iter, NULL((void*)0), i + 2);
1028 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
1029 &iter);
1030 }
1031 }
1032
1033 for (l = mime_types; l != NULL((void*)0); l = l->next)
1034 {
1035 const char *desc;
1036
1037 mime_type = l->data;
1038
1039 desc = g_content_type_get_description (mime_type);
1040 if (desc == NULL((void*)0))
1041 {
1042 desc = mime_type;
1043 }
1044
1045 row = caja_query_editor_add_row (editor,
1046 CAJA_QUERY_EDITOR_ROW_TYPE);
1047 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
Value stored to 'model' is never read
1048
1049 type_add_custom_type (row, mime_type, desc, &iter);
1050 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
1051 &iter);
1052 }
1053
1054 g_list_free_full (mime_types, g_free);
1055}
1056
1057/* End of row types */
1058
1059
1060static GtkWidget *modtime_row_create_widgets(CajaQueryEditorRow *row)
1061{
1062 GtkWidget *hbox = NULL((void*)0);
1063 GtkWidget *combo = NULL((void*)0);
1064 GtkWidget *duration_combo = NULL((void*)0);
1065 GtkCellRenderer *cell = NULL((void*)0);
1066 GtkListStore *store = NULL((void*)0);
1067 GtkListStore *duration_store = NULL((void*)0);
1068 GtkTreeIter iter;
1069
1070 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7);
1071
1072 store = gtk_list_store_new(2, G_TYPE_BOOLEAN((GType) ((5) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1073 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)((((GtkTreeModel*) (void *) ((store))))));
1074 g_object_unref(store);
1075
1076 cell = gtk_cell_renderer_text_new();
1077 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
1078 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, "text", 1,
1079 NULL((void*)0));
1080
1081 gtk_list_store_append(store, &iter);
1082 gtk_list_store_set(store, &iter, 0, FALSE(0), 1, _("Less than or equal to")dcgettext (((void*)0), "Less than or equal to", 5), -1);
1083 gtk_list_store_append(store, &iter);
1084 gtk_list_store_set(store, &iter, 0, TRUE(!(0)), 1, _("Greater than or equal to")dcgettext (((void*)0), "Greater than or equal to", 5), -1);
1085
1086 gtk_combo_box_set_active(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), 0);
1087
1088 duration_store = gtk_list_store_new(2, G_TYPE_INT((GType) ((6) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1089 duration_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(duration_store)((((GtkTreeModel*) (void *) ((duration_store))))));
1090 g_object_unref(duration_store);
1091
1092 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(duration_combo)((((GtkCellLayout*) (void *) ((duration_combo))))), cell, TRUE(!(0)));
1093 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(duration_combo)((((GtkCellLayout*) (void *) ((duration_combo))))), cell,
1094 "text", 1, NULL((void*)0));
1095
1096 gtk_list_store_append(duration_store, &iter);
1097 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_HOUR, 1, _("1 Hour")dcgettext (((void*)0), "1 Hour", 5), -1);
1098 gtk_list_store_append(duration_store, &iter);
1099 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_DAY, 1, _("1 Day")dcgettext (((void*)0), "1 Day", 5), -1);
1100 gtk_list_store_append(duration_store, &iter);
1101 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_WEEK, 1, _("1 Week")dcgettext (((void*)0), "1 Week", 5), -1);
1102 gtk_list_store_append(duration_store, &iter);
1103 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_MONTH, 1, _("1 Month")dcgettext (((void*)0), "1 Month", 5), -1);
1104 gtk_list_store_append(duration_store, &iter);
1105 gtk_list_store_set(duration_store, &iter, 0, DURATION_SIX_MONTHS, 1, _("6 Months")dcgettext (((void*)0), "6 Months", 5), -1);
1106 gtk_list_store_append(duration_store, &iter);
1107 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_YEAR, 1, _("1 Year")dcgettext (((void*)0), "1 Year", 5), -1);
1108
1109 gtk_combo_box_set_active(GTK_COMBO_BOX(duration_combo)((((GtkComboBox*) (void *) ((duration_combo))))), 0);
1110
1111 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), combo, FALSE(0), FALSE(0), 0);
1112 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), duration_combo, FALSE(0), FALSE(0), 0);
1113 gtk_widget_show_all(hbox);
1114
1115 gtk_box_pack_start(GTK_BOX(row->hbox)((((GtkBox*) (void *) ((row->hbox))))), hbox, FALSE(0), FALSE(0), 0);
1116
1117 return hbox;
1118}
1119
1120static void modtime_row_add_to_query(CajaQueryEditorRow *row, CajaQuery *query)
1121{
1122 GList *children = NULL((void*)0);
1123 GtkWidget *combo = NULL((void*)0);
1124 GtkWidget *duration_combo = NULL((void*)0);
1125 GtkTreeModel *model = NULL((void*)0);
1126 GtkTreeModel *duration_model = NULL((void*)0);
1127 GtkTreeIter iter;
1128 GtkTreeIter duration_iter;
1129 gboolean is_greater = FALSE(0);
1130 GDateTime *now, *datetime;
1131 gint duration;
1132 gint64 timestamp;
1133
1134 if (!GTK_IS_CONTAINER(row->type_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(row->type_widget)); GType __t = ((gtk_container_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; }))))
)
1135 return;
1136
1137 children = gtk_container_get_children(GTK_CONTAINER(row->type_widget)((((GtkContainer*) (void *) ((row->type_widget))))));
1138 if (g_list_length(children) != 2)
1139 return;
1140
1141 combo = GTK_WIDGET(g_list_nth(children, 0)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 0)->data))
)))
;
1142 duration_combo = GTK_WIDGET(g_list_nth(children, 1)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 1)->data))
)))
;
1143 if (!combo || !duration_combo)
1144 return;
1145
1146 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter) ||
1147 !gtk_combo_box_get_active_iter(GTK_COMBO_BOX(duration_combo)((((GtkComboBox*) (void *) ((duration_combo))))), &duration_iter)) {
1148 return;
1149 }
1150
1151 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
1152 gtk_tree_model_get(model, &iter, 0, &is_greater, -1);
1153
1154 duration_model = gtk_combo_box_get_model(GTK_COMBO_BOX(duration_combo)((((GtkComboBox*) (void *) ((duration_combo))))));
1155 gtk_tree_model_get(duration_model, &duration_iter, 0, &duration, -1);
1156
1157 now = g_date_time_new_now_local ();
1158 datetime = now;
1159 switch (duration)
1160 {
1161 case DURATION_ONE_HOUR:
1162 datetime = g_date_time_add_hours (now, -1);
1163 break;
1164 case DURATION_ONE_DAY:
1165 datetime = g_date_time_add_days (now, -1);
1166 break;
1167 case DURATION_ONE_WEEK:
1168 datetime = g_date_time_add_weeks (now, -1);
1169 break;
1170 case DURATION_ONE_MONTH:
1171 datetime = g_date_time_add_months (now, -1);
1172 break;
1173 case DURATION_SIX_MONTHS:
1174 datetime = g_date_time_add_months (now, -6);
1175 break;
1176 case DURATION_ONE_YEAR:
1177 datetime = g_date_time_add_years (now, -1);
1178 break;
1179 default:
1180 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-query-editor.c"
, 1180, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1181 }
1182
1183 g_date_time_unref (now);
1184 timestamp = g_date_time_to_unix (datetime);
1185 g_date_time_unref (datetime);
1186
1187 caja_query_set_timestamp(query, is_greater ? timestamp: -timestamp);
1188}
1189
1190static void modtime_row_free_data(CajaQueryEditorRow *row)
1191{
1192}
1193
1194static void modtime_add_rows_from_query(CajaQueryEditor *editor, CajaQuery *query)
1195{
1196}
1197
1198
1199static GtkWidget *size_row_create_widgets(CajaQueryEditorRow *row)
1200{
1201 GtkWidget *hbox = NULL((void*)0);
1202 GtkWidget *combo = NULL((void*)0);
1203 GtkWidget *size_combo = NULL((void*)0);
1204 GtkCellRenderer *cell = NULL((void*)0);
1205 GtkListStore *store = NULL((void*)0);
1206 GtkListStore *size_store = NULL((void*)0);
1207 GtkTreeIter iter;
1208
1209 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7);
1210
1211 store = gtk_list_store_new(2, G_TYPE_BOOLEAN((GType) ((5) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1212 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)((((GtkTreeModel*) (void *) ((store))))));
1213 g_object_unref(store);
1214
1215 cell = gtk_cell_renderer_text_new();
1216 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
1217 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, "text", 1,
1218 NULL((void*)0));
1219
1220 gtk_list_store_append(store, &iter);
1221 gtk_list_store_set(store, &iter, 0, FALSE(0), 1, _("Less than or equal to")dcgettext (((void*)0), "Less than or equal to", 5), -1);
1222 gtk_list_store_append(store, &iter);
1223 gtk_list_store_set(store, &iter, 0, TRUE(!(0)), 1, _("Greater than or equal to")dcgettext (((void*)0), "Greater than or equal to", 5), -1);
1224
1225 gtk_combo_box_set_active(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), 0);
1226
1227 size_store = gtk_list_store_new(2, G_TYPE_INT64((GType) ((10) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1228 size_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(size_store)((((GtkTreeModel*) (void *) ((size_store))))));
1229 g_object_unref(size_store);
1230
1231 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(size_combo)((((GtkCellLayout*) (void *) ((size_combo))))), cell, TRUE(!(0)));
1232 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(size_combo)((((GtkCellLayout*) (void *) ((size_combo))))), cell, "text",
1233 1, NULL((void*)0));
1234
1235 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
1236 {
1237 gtk_list_store_append(size_store, &iter);
1238 gtk_list_store_set(size_store, &iter, 0, 10240, 1, _("10 KiB")dcgettext (((void*)0), "10 KiB", 5), -1);
1239 gtk_list_store_append(size_store, &iter);
1240 gtk_list_store_set(size_store, &iter, 0, 102400, 1, _("100 KiB")dcgettext (((void*)0), "100 KiB", 5), -1);
1241 gtk_list_store_append(size_store, &iter);
1242 gtk_list_store_set(size_store, &iter, 0, 512000, 1, _("500 KiB")dcgettext (((void*)0), "500 KiB", 5), -1);
1243 gtk_list_store_append(size_store, &iter);
1244 gtk_list_store_set(size_store, &iter, 0, 1048576, 1, _("1 MiB")dcgettext (((void*)0), "1 MiB", 5), -1);
1245 gtk_list_store_append(size_store, &iter);
1246 gtk_list_store_set(size_store, &iter, 0, 5242880, 1, _("5 MiB")dcgettext (((void*)0), "5 MiB", 5), -1);
1247 gtk_list_store_append(size_store, &iter);
1248 gtk_list_store_set(size_store, &iter, 0, 10485760, 1, _("10 MiB")dcgettext (((void*)0), "10 MiB", 5), -1);
1249 gtk_list_store_append(size_store, &iter);
1250 gtk_list_store_set(size_store, &iter, 0, 104857600, 1, _("100 MiB")dcgettext (((void*)0), "100 MiB", 5), -1);
1251 gtk_list_store_append(size_store, &iter);
1252 gtk_list_store_set(size_store, &iter, 0, 524288000, 1, _("500 MiB")dcgettext (((void*)0), "500 MiB", 5), -1);
1253 gtk_list_store_append(size_store, &iter);
1254 gtk_list_store_set(size_store, &iter, 0, 1073741824, 1, _("1 GiB")dcgettext (((void*)0), "1 GiB", 5), -1);
1255 gtk_list_store_append(size_store, &iter);
1256 gtk_list_store_set(size_store, &iter, 0, 2147483648, 1, _("2 GiB")dcgettext (((void*)0), "2 GiB", 5), -1);
1257 gtk_list_store_append(size_store, &iter);
1258 gtk_list_store_set(size_store, &iter, 0, 4294967296, 1, _("4 GiB")dcgettext (((void*)0), "4 GiB", 5), -1);
1259 } else {
1260 gtk_list_store_append(size_store, &iter);
1261 gtk_list_store_set(size_store, &iter, 0, 10000, 1, _("10 KB")dcgettext (((void*)0), "10 KB", 5), -1);
1262 gtk_list_store_append(size_store, &iter);
1263 gtk_list_store_set(size_store, &iter, 0, 100000, 1, _("100 KB")dcgettext (((void*)0), "100 KB", 5), -1);
1264 gtk_list_store_append(size_store, &iter);
1265 gtk_list_store_set(size_store, &iter, 0, 500000, 1, _("500 KB")dcgettext (((void*)0), "500 KB", 5), -1);
1266 gtk_list_store_append(size_store, &iter);
1267 gtk_list_store_set(size_store, &iter, 0, 1000000, 1, _("1 MB")dcgettext (((void*)0), "1 MB", 5), -1);
1268 gtk_list_store_append(size_store, &iter);
1269 gtk_list_store_set(size_store, &iter, 0, 5000000, 1, _("5 MB")dcgettext (((void*)0), "5 MB", 5), -1);
1270 gtk_list_store_append(size_store, &iter);
1271 gtk_list_store_set(size_store, &iter, 0, 10000000, 1, _("10 MB")dcgettext (((void*)0), "10 MB", 5), -1);
1272 gtk_list_store_append(size_store, &iter);
1273 gtk_list_store_set(size_store, &iter, 0, 100000000, 1, _("100 MB")dcgettext (((void*)0), "100 MB", 5), -1);
1274 gtk_list_store_append(size_store, &iter);
1275 gtk_list_store_set(size_store, &iter, 0, 500000000, 1, _("500 MB")dcgettext (((void*)0), "500 MB", 5), -1);
1276 gtk_list_store_append(size_store, &iter);
1277 gtk_list_store_set(size_store, &iter, 0, 1000000000, 1, _("1 GB")dcgettext (((void*)0), "1 GB", 5), -1);
1278 gtk_list_store_append(size_store, &iter);
1279 gtk_list_store_set(size_store, &iter, 0, 2000000000, 1, _("2 GB")dcgettext (((void*)0), "2 GB", 5), -1);
1280 gtk_list_store_append(size_store, &iter);
1281 gtk_list_store_set(size_store, &iter, 0, 4000000000, 1, _("4 GB")dcgettext (((void*)0), "4 GB", 5), -1);
1282 }
1283
1284 gtk_combo_box_set_active(GTK_COMBO_BOX(size_combo)((((GtkComboBox*) (void *) ((size_combo))))), 0);
1285
1286 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), combo, FALSE(0), FALSE(0), 0);
1287 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), size_combo, FALSE(0), FALSE(0), 0);
1288 gtk_widget_show_all(hbox);
1289
1290 gtk_box_pack_start(GTK_BOX(row->hbox)((((GtkBox*) (void *) ((row->hbox))))), hbox, FALSE(0), FALSE(0), 0);
1291
1292 return hbox;
1293}
1294
1295static void size_row_add_to_query(CajaQueryEditorRow *row, CajaQuery *query)
1296{
1297 GList *children = NULL((void*)0);
1298 GtkWidget *combo = NULL((void*)0);
1299 GtkWidget *size_combo = NULL((void*)0);
1300 GtkTreeModel *model = NULL((void*)0);
1301 GtkTreeModel *size_model = NULL((void*)0);
1302 GtkTreeIter iter;
1303 GtkTreeIter size_iter;
1304 gboolean is_greater = FALSE(0);
1305 gint64 size;
1306
1307 if (!GTK_IS_CONTAINER(row->type_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(row->type_widget)); GType __t = ((gtk_container_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; }))))
)
1308 return;
1309
1310 children = gtk_container_get_children(GTK_CONTAINER(row->type_widget)((((GtkContainer*) (void *) ((row->type_widget))))));
1311 if (g_list_length(children) != 2)
1312 return;
1313
1314 combo = GTK_WIDGET(g_list_nth(children, 0)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 0)->data))
)))
;
1315 size_combo = GTK_WIDGET(g_list_nth(children, 1)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 1)->data))
)))
;
1316 if (!combo || !size_combo)
1317 return;
1318
1319 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter) ||
1320 !gtk_combo_box_get_active_iter(GTK_COMBO_BOX(size_combo)((((GtkComboBox*) (void *) ((size_combo))))), &size_iter)) {
1321 return;
1322 }
1323
1324 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
1325 gtk_tree_model_get(model, &iter, 0, &is_greater, -1);
1326
1327 size_model = gtk_combo_box_get_model(GTK_COMBO_BOX(size_combo)((((GtkComboBox*) (void *) ((size_combo))))));
1328 gtk_tree_model_get(size_model, &size_iter, 0, &size, -1);
1329
1330 caja_query_set_size(query, is_greater ? size : -size);
1331}
1332
1333static void size_row_free_data(CajaQueryEditorRow *row)
1334{
1335}
1336
1337static void size_add_rows_from_query(CajaQueryEditor *editor, CajaQuery *query)
1338{
1339}
1340
1341static GtkWidget *
1342contained_text_row_create_widgets (CajaQueryEditorRow *row)
1343{
1344 GtkWidget *entry = gtk_entry_new();
1345 gtk_widget_set_tooltip_text (entry,
1346 _("Matches files that contains specified text.")dcgettext (((void*)0), "Matches files that contains specified text."
, 5)
);
1347
1348 gtk_entry_set_placeholder_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))),
1349 _("Matches files that contains specified text.")dcgettext (((void*)0), "Matches files that contains specified text."
, 5)
);
1350
1351 gtk_widget_show (entry);
1352 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), entry, TRUE(!(0)), TRUE(!(0)), 0);
1353 g_signal_connect (entry, "activate", G_CALLBACK (go_search_cb), row->editor)g_signal_connect_data ((entry), ("activate"), (((GCallback) (
go_search_cb))), (row->editor), ((void*)0), (GConnectFlags
) 0)
;
1354
1355 return entry;
1356}
1357
1358static void
1359contained_text_row_add_to_query (CajaQueryEditorRow *row, CajaQuery *query)
1360{
1361 GtkEntry *entry = GTK_ENTRY (row->type_widget)((((GtkEntry*) (void *) ((row->type_widget)))));
1362 const gchar *text = gtk_entry_get_text (entry);
1363
1364 caja_query_set_contained_text (query, text);
1365}
1366
1367static void
1368contained_text_row_free_data (CajaQueryEditorRow *row)
1369{
1370}
1371
1372static void
1373contained_text_add_rows_from_query (CajaQueryEditor *editor, CajaQuery *query)
1374{
1375}
1376
1377static CajaQueryEditorRowType
1378get_next_free_type (CajaQueryEditor *editor)
1379{
1380 CajaQueryEditorRow *row;
1381 CajaQueryEditorRowType type;
1382 gboolean found;
1383 GList *l;
1384
1385
1386 for (type = 0; type < CAJA_QUERY_EDITOR_ROW_LAST; type++)
1387 {
1388 found = FALSE(0);
1389 for (l = editor->details->rows; l != NULL((void*)0); l = l->next)
1390 {
1391 row = l->data;
1392 if (row->type == type)
1393 {
1394 found = TRUE(!(0));
1395 break;
1396 }
1397 }
1398 if (!found)
1399 {
1400 return type;
1401 }
1402 }
1403 return CAJA_QUERY_EDITOR_ROW_TYPE;
1404}
1405
1406static void
1407remove_row_cb (GtkButton *clicked_button, CajaQueryEditorRow *row)
1408{
1409 CajaQueryEditor *editor;
1410
1411 editor = row->editor;
1412 gtk_container_remove (GTK_CONTAINER (editor->details->visible_vbox)((((GtkContainer*) (void *) ((editor->details->visible_vbox
)))))
,
1413 row->hbox);
1414
1415 editor->details->rows = g_list_remove (editor->details->rows, row);
1416
1417 row_type[row->type].free_data (row);
1418 g_free (row);
1419
1420 caja_query_editor_changed (editor);
1421}
1422
1423static void
1424create_type_widgets (CajaQueryEditorRow *row)
1425{
1426 row->type_widget = row_type[row->type].create_widgets (row);
1427}
1428
1429static void
1430row_type_combo_changed_cb (GtkComboBox *combo_box, CajaQueryEditorRow *row)
1431{
1432 CajaQueryEditorRowType type;
1433
1434 type = gtk_combo_box_get_active (combo_box);
1435
1436 if (type == row->type)
1437 {
1438 return;
1439 }
1440
1441 if (row->type_widget != NULL((void*)0))
1442 {
1443 gtk_widget_destroy (row->type_widget);
1444 row->type_widget = NULL((void*)0);
1445 }
1446
1447 row_type[row->type].free_data (row);
1448 row->data = NULL((void*)0);
1449
1450 row->type = type;
1451
1452 create_type_widgets (row);
1453
1454 caja_query_editor_changed (row->editor);
1455}
1456
1457static CajaQueryEditorRow *
1458caja_query_editor_add_row (CajaQueryEditor *editor,
1459 CajaQueryEditorRowType type)
1460{
1461 GtkWidget *hbox, *button, *image, *combo;
1462 CajaQueryEditorRow *row;
1463 int i;
1464
1465 row = g_new0 (CajaQueryEditorRow, 1)(CajaQueryEditorRow *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (CajaQueryEditorRow); 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; }))
;
1466 row->editor = editor;
1467 row->type = type;
1468
1469 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1470 row->hbox = hbox;
1471 gtk_widget_show (hbox);
1472 gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox)((((GtkBox*) (void *) ((editor->details->visible_vbox))
)))
, hbox, FALSE(0), FALSE(0), 0);
1473
1474 combo = gtk_combo_box_text_new ();
1475 row->combo = combo;
1476 for (i = 0; i < CAJA_QUERY_EDITOR_ROW_LAST; i++)
1477 {
1478 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo)((((GtkComboBoxText*) (void *) ((combo))))), gettext (row_type[i].name)dcgettext (((void*)0), row_type[i].name, 5));
1479 }
1480 gtk_widget_show (combo);
1481 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), combo, FALSE(0), FALSE(0), 0);
1482
1483 gtk_combo_box_set_active (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), row->type);
1484
1485 editor->details->rows = g_list_append (editor->details->rows, row);
1486
1487 g_signal_connect (combo, "changed",g_signal_connect_data ((combo), ("changed"), (((GCallback) (row_type_combo_changed_cb
))), (row), ((void*)0), (GConnectFlags) 0)
1488 G_CALLBACK (row_type_combo_changed_cb), row)g_signal_connect_data ((combo), ("changed"), (((GCallback) (row_type_combo_changed_cb
))), (row), ((void*)0), (GConnectFlags) 0)
;
1489
1490 create_type_widgets (row);
1491
1492 button = gtk_button_new ();
1493 image = gtk_image_new_from_icon_name ("remove",
1494 GTK_ICON_SIZE_SMALL_TOOLBAR);
1495 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), image);
1496 gtk_widget_show (image);
1497 gtk_button_set_relief (GTK_BUTTON (button)((((GtkButton*) (void *) ((button))))), GTK_RELIEF_NONE);
1498 gtk_widget_show (button);
1499
1500 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
remove_row_cb))), (row), ((void*)0), (GConnectFlags) 0)
1501 G_CALLBACK (remove_row_cb), row)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
remove_row_cb))), (row), ((void*)0), (GConnectFlags) 0)
;
1502 gtk_widget_set_tooltip_text (button,
1503 _("Remove this criterion from the search")dcgettext (((void*)0), "Remove this criterion from the search"
, 5)
);
1504
1505 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1506
1507 return row;
1508}
1509
1510static void
1511go_search_cb (GtkButton *clicked_button, CajaQueryEditor *editor)
1512{
1513 caja_query_editor_changed_force (editor, TRUE(!(0)));
1514}
1515
1516static void
1517add_new_row_cb (GtkButton *clicked_button, CajaQueryEditor *editor)
1518{
1519 caja_query_editor_add_row (editor, get_next_free_type (editor));
1520 caja_query_editor_changed (editor);
1521}
1522
1523static void
1524caja_query_editor_init (CajaQueryEditor *editor)
1525{
1526 GtkWidget *hbox, *label, *button;
1527 char *label_markup;
1528
1529 editor->details = g_new0 (CajaQueryEditorDetails, 1)(CajaQueryEditorDetails *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (CajaQueryEditorDetails); 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; }))
;
1530 editor->details->is_visible = TRUE(!(0));
1531
1532 editor->details->invisible_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1533 gtk_orientable_set_orientation (GTK_ORIENTABLE (editor)((((GtkOrientable*) (void *) ((editor))))), GTK_ORIENTATION_VERTICAL);
1534 gtk_box_pack_start (GTK_BOX (editor)((((GtkBox*) (void *) ((editor))))), editor->details->invisible_vbox,
1535 FALSE(0), FALSE(0), 0);
1536 editor->details->visible_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1537 gtk_orientable_set_orientation (GTK_ORIENTABLE (editor)((((GtkOrientable*) (void *) ((editor))))), GTK_ORIENTATION_VERTICAL);
1538 gtk_box_pack_start (GTK_BOX (editor)((((GtkBox*) (void *) ((editor))))), editor->details->visible_vbox,
1539 FALSE(0), FALSE(0), 0);
1540 /* Only show visible vbox */
1541 gtk_widget_show (editor->details->visible_vbox);
1542
1543 /* Create invisible part: */
1544 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1545 gtk_box_pack_start (GTK_BOX (editor->details->invisible_vbox)((((GtkBox*) (void *) ((editor->details->invisible_vbox
)))))
,
1546 hbox, FALSE(0), FALSE(0), 0);
1547 gtk_widget_show (hbox);
1548
1549 label = gtk_label_new ("");
1550 label_markup = g_strconcat ("<b>", _("Search Folder")dcgettext (((void*)0), "Search Folder", 5), "</b>", NULL((void*)0));
1551 gtk_label_set_markup (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), label_markup);
1552 g_free (label_markup);
1553 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), label, FALSE(0), FALSE(0), 0);
1554 gtk_widget_show (label);
1555
1556 button = gtk_button_new_with_label (_("Edit")dcgettext (((void*)0), "Edit", 5));
1557 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1558 gtk_widget_show (button);
1559
1560 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
edit_clicked))), (editor), ((void*)0), (GConnectFlags) 0)
1561 G_CALLBACK (edit_clicked), editor)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
edit_clicked))), (editor), ((void*)0), (GConnectFlags) 0)
;
1562
1563 gtk_widget_set_tooltip_text (button,
1564 _("Edit the saved search")dcgettext (((void*)0), "Edit the saved search", 5));
1565}
1566
1567void
1568caja_query_editor_set_default_query (CajaQueryEditor *editor)
1569{
1570 if (!editor->details->is_indexed)
1571 {
1572 caja_query_editor_add_row (editor, CAJA_QUERY_EDITOR_ROW_LOCATION);
1573 caja_query_editor_changed (editor);
1574 }
1575}
1576
1577static void
1578finish_first_line (CajaQueryEditor *editor, GtkWidget *hbox, gboolean use_go)
1579{
1580 GtkWidget *button, *image;
1581
1582 button = gtk_button_new ();
1583 image = gtk_image_new_from_icon_name ("add",
1584 GTK_ICON_SIZE_SMALL_TOOLBAR);
1585 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), image);
1586 gtk_widget_show (image);
1587 gtk_button_set_relief (GTK_BUTTON (button)((((GtkButton*) (void *) ((button))))), GTK_RELIEF_NONE);
1588 gtk_widget_show (button);
1589
1590 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
add_new_row_cb))), (editor), ((void*)0), (GConnectFlags) 0)
1591 G_CALLBACK (add_new_row_cb), editor)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
add_new_row_cb))), (editor), ((void*)0), (GConnectFlags) 0)
;
1592
1593 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1594
1595 gtk_widget_set_tooltip_text (button,
1596 _("Add a new criterion to this search")dcgettext (((void*)0), "Add a new criterion to this search", 5
)
);
1597
1598 if (!editor->details->is_indexed)
1599 {
1600 if (use_go)
1601 {
1602 button = gtk_button_new_with_label (_("Go")dcgettext (((void*)0), "Go", 5));
1603 }
1604 else
1605 {
1606 button = gtk_button_new_with_label (_("Reload")dcgettext (((void*)0), "Reload", 5));
1607 }
1608 gtk_widget_show (button);
1609
1610 gtk_widget_set_tooltip_text (button,
1611 _("Perform or update the search")dcgettext (((void*)0), "Perform or update the search", 5));
1612
1613 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
go_search_cb))), (editor), ((void*)0), (GConnectFlags) 0)
1614 G_CALLBACK (go_search_cb), editor)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
go_search_cb))), (editor), ((void*)0), (GConnectFlags) 0)
;
1615
1616 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1617 }
1618}
1619
1620static void
1621setup_internal_entry (CajaQueryEditor *editor)
1622{
1623 GtkWidget *hbox, *label;
1624 char *label_markup;
1625
1626 /* Create visible part: */
1627 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1628 gtk_widget_show (hbox);
1629 gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox)((((GtkBox*) (void *) ((editor->details->visible_vbox))
)))
, hbox, FALSE(0), FALSE(0), 0);
1630
1631 label = gtk_label_new ("");
1632 label_markup = g_strconcat ("<b>", _("_Search for:")dcgettext (((void*)0), "_Search for:", 5), "</b>", NULL((void*)0));
1633 gtk_label_set_markup_with_mnemonic (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), label_markup);
1634 g_free (label_markup);
1635 gtk_widget_show (label);
1636 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), label, FALSE(0), FALSE(0), 0);
1637
1638 editor->details->entry = gtk_entry_new ();
1639 gtk_label_set_mnemonic_widget (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), editor->details->entry);
1640 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), editor->details->entry, TRUE(!(0)), TRUE(!(0)), 0);
1641
1642 g_signal_connect (editor->details->entry, "activate",g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
1643 G_CALLBACK (entry_activate_cb), editor)g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
;
1644 g_signal_connect (editor->details->entry, "changed",g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
1645 G_CALLBACK (entry_changed_cb), editor)g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
;
1646 gtk_widget_show (editor->details->entry);
1647
1648 finish_first_line (editor, hbox, TRUE(!(0)));
1649}
1650
1651static void
1652setup_external_entry (CajaQueryEditor *editor, GtkWidget *entry)
1653{
1654 GtkWidget *hbox, *label;
1655
1656 /* Create visible part: */
1657 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1658 gtk_widget_show (hbox);
1659 gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox)((((GtkBox*) (void *) ((editor->details->visible_vbox))
)))
, hbox, FALSE(0), FALSE(0), 0);
1660
1661 label = gtk_label_new (_("Search results")dcgettext (((void*)0), "Search results", 5));
1662 gtk_widget_show (label);
1663 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), label, FALSE(0), FALSE(0), 0);
1664
1665 editor->details->entry = entry;
1666 g_signal_connect (editor->details->entry, "activate",g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
1667 G_CALLBACK (entry_activate_cb), editor)g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
;
1668 g_signal_connect (editor->details->entry, "changed",g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
1669 G_CALLBACK (entry_changed_cb), editor)g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
;
1670
1671 finish_first_line (editor, hbox, FALSE(0));
1672
1673}
1674
1675void
1676caja_query_editor_set_visible (CajaQueryEditor *editor,
1677 gboolean visible)
1678{
1679 editor->details->is_visible = visible;
1680 if (visible)
1681 {
1682 gtk_widget_show (editor->details->visible_vbox);
1683 gtk_widget_hide (editor->details->invisible_vbox);
1684 }
1685 else
1686 {
1687 gtk_widget_hide (editor->details->visible_vbox);
1688 gtk_widget_show (editor->details->invisible_vbox);
1689 }
1690}
1691
1692static gboolean
1693query_is_valid (CajaQueryEditor *editor)
1694{
1695 const char *text;
1696
1697 text = gtk_entry_get_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))));
1698
1699 return text != NULL((void*)0) && text[0] != '\0';
1700}
1701
1702static void
1703caja_query_editor_changed_force (CajaQueryEditor *editor, gboolean force_reload)
1704{
1705 if (editor->details->change_frozen)
1706 {
1707 return;
1708 }
1709
1710 if (query_is_valid (editor))
1711 {
1712 CajaQuery *query;
1713
1714 query = caja_query_editor_get_query (editor);
1715 g_signal_emit (editor, signals[CHANGED], 0,
1716 query, editor->details->is_indexed || force_reload);
1717 g_object_unref (query);
1718 }
1719}
1720
1721static void
1722caja_query_editor_changed (CajaQueryEditor *editor)
1723{
1724 caja_query_editor_changed_force (editor, FALSE(0));
1725}
1726
1727void
1728caja_query_editor_grab_focus (CajaQueryEditor *editor)
1729{
1730 if (editor->details->is_visible)
1731 {
1732 gtk_widget_grab_focus (editor->details->entry);
1733 }
1734}
1735
1736CajaQuery *
1737caja_query_editor_get_query (CajaQueryEditor *editor)
1738{
1739 const char *query_text;
1740 CajaQuery *query;
1741 GList *l;
1742 CajaQueryEditorRow *row = NULL((void*)0);
1743
1744 if (editor == NULL((void*)0) || editor->details == NULL((void*)0) || editor->details->entry == NULL((void*)0))
1745 {
1746 return NULL((void*)0);
1747 }
1748
1749 query_text = gtk_entry_get_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))));
1750
1751 /* Empty string is a NULL query */
1752 if (query_text && query_text[0] == '\0')
1753 {
1754 return NULL((void*)0);
1755 }
1756
1757 query = caja_query_new ();
1758 caja_query_set_text (query, query_text);
1759
1760 for (l = editor->details->rows; l != NULL((void*)0); l = l->next)
1761 {
1762 row = l->data;
1763
1764 row_type[row->type].add_to_query (row, query);
1765 }
1766
1767 return query;
1768}
1769
1770void
1771caja_query_editor_clear_query (CajaQueryEditor *editor)
1772{
1773 editor->details->change_frozen = TRUE(!(0));
1774 gtk_entry_set_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))), "");
1775
1776 g_free (editor->details->last_set_query_text);
1777 editor->details->last_set_query_text = g_strdup ("")g_strdup_inline ("");
1778
1779 editor->details->change_frozen = FALSE(0);
1780}
1781
1782GtkWidget *
1783caja_query_editor_new (gboolean start_hidden,
1784 gboolean is_indexed)
1785{
1786 GtkWidget *editor;
1787
1788 editor = g_object_new (CAJA_TYPE_QUERY_EDITORcaja_query_editor_get_type(), NULL((void*)0));
1789
1790 CAJA_QUERY_EDITOR (editor)((((CajaQueryEditor*) (void *) ((editor)))))->details->is_indexed = is_indexed;
1791
1792 caja_query_editor_set_visible (CAJA_QUERY_EDITOR (editor)((((CajaQueryEditor*) (void *) ((editor))))),
1793 !start_hidden);
1794
1795 setup_internal_entry (CAJA_QUERY_EDITOR (editor)((((CajaQueryEditor*) (void *) ((editor))))));
1796
1797 return editor;
1798}
1799
1800static void
1801detach_from_external_entry (CajaQueryEditor *editor)
1802{
1803 if (editor->details->bar != NULL((void*)0))
1804 {
1805 caja_search_bar_return_entry (editor->details->bar);
1806 g_signal_handlers_block_by_func (editor->details->entry,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1807 entry_activate_cb,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1808 editor)g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
;
1809 g_signal_handlers_block_by_func (editor->details->entry,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1810 entry_changed_cb,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1811 editor)g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
;
1812 }
1813}
1814
1815static void
1816attach_to_external_entry (CajaQueryEditor *editor)
1817{
1818 if (editor->details->bar != NULL((void*)0))
1819 {
1820 caja_search_bar_borrow_entry (editor->details->bar);
1821 g_signal_handlers_unblock_by_func (editor->details->entry,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1822 entry_activate_cb,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1823 editor)g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
;
1824 g_signal_handlers_unblock_by_func (editor->details->entry,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1825 entry_changed_cb,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1826 editor)g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
;
1827
1828 editor->details->change_frozen = TRUE(!(0));
1829 gtk_entry_set_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))),
1830 editor->details->last_set_query_text);
1831 editor->details->change_frozen = FALSE(0);
1832 }
1833}
1834
1835GtkWidget*
1836caja_query_editor_new_with_bar (gboolean start_hidden,
1837 gboolean is_indexed,
1838 gboolean start_attached,
1839 CajaSearchBar *bar,
1840 CajaWindowSlot *slot)
1841{
1842 GtkWidget *entry;
1843 CajaQueryEditor *editor;
1844
1845 editor = CAJA_QUERY_EDITOR (g_object_new (CAJA_TYPE_QUERY_EDITOR, NULL))((((CajaQueryEditor*) (void *) ((g_object_new (caja_query_editor_get_type
(), ((void*)0)))))))
;
1846 editor->details->is_indexed = is_indexed;
1847
1848 caja_query_editor_set_visible (editor, !start_hidden);
1849
1850 editor->details->bar = bar;
1851 eel_add_weak_pointer (&editor->details->bar);
1852
1853 editor->details->slot = slot;
1854
1855 entry = caja_search_bar_borrow_entry (bar);
1856 setup_external_entry (editor, entry);
1857 if (!start_attached)
1858 {
1859 detach_from_external_entry (editor);
1860 }
1861
1862 g_signal_connect_object (slot, "active",
1863 G_CALLBACK (attach_to_external_entry)((GCallback) (attach_to_external_entry)),
1864 editor, G_CONNECT_SWAPPED);
1865 g_signal_connect_object (slot, "inactive",
1866 G_CALLBACK (detach_from_external_entry)((GCallback) (detach_from_external_entry)),
1867 editor, G_CONNECT_SWAPPED);
1868
1869 return GTK_WIDGET (editor)((((GtkWidget*) (void *) ((editor)))));
1870}
1871
1872void
1873caja_query_editor_set_query (CajaQueryEditor *editor, CajaQuery *query)
1874{
1875 CajaQueryEditorRowType type;
1876 char *text;
1877
1878 if (!query)
1879 {
1880 caja_query_editor_clear_query (editor);
1881 return;
1882 }
1883
1884 text = caja_query_get_text (query);
1885
1886 if (!text)
1887 {
1888 text = g_strdup ("")g_strdup_inline ("");
1889 }
1890
1891 editor->details->change_frozen = TRUE(!(0));
1892 gtk_entry_set_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))), text);
1893
1894 for (type = 0; type < CAJA_QUERY_EDITOR_ROW_LAST; type++)
1895 {
1896 row_type[type].add_rows_from_query (editor, query);
1897 }
1898
1899 editor->details->change_frozen = FALSE(0);
1900
1901 g_free (editor->details->last_set_query_text);
1902 editor->details->last_set_query_text = text;
1903}
diff --git a/2024-07-29-023715-6438-1/report-493860.html b/2024-07-29-023715-6438-1/report-493860.html new file mode 100644 index 000000000..3b82b1af7 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-493860.html @@ -0,0 +1,12231 @@ + + + +fm-directory-view.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/file-manager/fm-directory-view.c
Warning:line 4747, column 2
Value stored to 'num_applications' 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 fm-directory-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 -fdebug-compilation-dir=/rootdir/src/file-manager -fcoverage-compilation-dir=/rootdir/src/file-manager -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I ../../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D CAJA_DATADIR="/usr/local/share/caja" -D DATADIR="/usr/local/share" -D ICONDIR="/usr/local/share/icons" -D PIXMAPDIR="/usr/local/share/pixmaps" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c fm-directory-view.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* fm-directory-view.c
4 *
5 * Copyright (C) 1999, 2000 Free Software Foundation
6 * Copyright (C) 2000, 2001 Eazel, Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (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 GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 * Authors: Ettore Perazzoli,
24 * John Sullivan <sullivan@eazel.com>,
25 * Darin Adler <darin@bentspoon.com>,
26 * Pavel Cisler <pavel@eazel.com>,
27 * David Emory Watson <dwatson@cs.ucr.edu>
28 */
29
30#include <config.h>
31#include <math.h>
32
33#include <gdk/gdkkeysyms.h>
34#include <gdk/gdkx.h>
35#include <gtk/gtk.h>
36#include <glib/gi18n.h>
37#include <glib/gstdio.h>
38#include <gio/gio.h>
39
40#define MATE_DESKTOP_USE_UNSTABLE_API
41#include <libmate-desktop/mate-desktop-utils.h>
42
43#include <eel/eel-background.h>
44#include <eel/eel-glib-extensions.h>
45#include <eel/eel-mate-extensions.h>
46#include <eel/eel-gtk-extensions.h>
47#include <eel/eel-gtk-macros.h>
48#include <eel/eel-stock-dialogs.h>
49#include <eel/eel-string.h>
50#include <eel/eel-vfs-extensions.h>
51
52#include <libcaja-private/caja-recent.h>
53#include <libcaja-extension/caja-menu-provider.h>
54#include <libcaja-private/caja-clipboard.h>
55#include <libcaja-private/caja-clipboard-monitor.h>
56#include <libcaja-private/caja-debug-log.h>
57#include <libcaja-private/caja-desktop-icon-file.h>
58#include <libcaja-private/caja-desktop-directory.h>
59#include <libcaja-private/caja-extensions.h>
60#include <libcaja-private/caja-search-directory.h>
61#include <libcaja-private/caja-directory-background.h>
62#include <libcaja-private/caja-directory.h>
63#include <libcaja-private/caja-dnd.h>
64#include <libcaja-private/caja-file-attributes.h>
65#include <libcaja-private/caja-file-changes-queue.h>
66#include <libcaja-private/caja-file-dnd.h>
67#include <libcaja-private/caja-file-operations.h>
68#include <libcaja-private/caja-file-utilities.h>
69#include <libcaja-private/caja-file-private.h> /* for caja_file_get_existing_by_uri */
70#include <libcaja-private/caja-global-preferences.h>
71#include <libcaja-private/caja-link.h>
72#include <libcaja-private/caja-metadata.h>
73#include <libcaja-private/caja-mime-actions.h>
74#include <libcaja-private/caja-module.h>
75#include <libcaja-private/caja-program-choosing.h>
76#include <libcaja-private/caja-trash-monitor.h>
77#include <libcaja-private/caja-ui-utilities.h>
78#include <libcaja-private/caja-signaller.h>
79#include <libcaja-private/caja-autorun.h>
80#include <libcaja-private/caja-icon-names.h>
81#include <libcaja-private/caja-undostack-manager.h>
82
83#include "fm-directory-view.h"
84#include "fm-list-view.h"
85#include "fm-desktop-icon-view.h"
86#include "fm-actions.h"
87#include "fm-error-reporting.h"
88#include "fm-marshal.h"
89#include "fm-properties-window.h"
90#include "libcaja-private/caja-open-with-dialog.h"
91
92/* Minimum starting update inverval */
93#define UPDATE_INTERVAL_MIN100 100
94/* Maximum update interval */
95#define UPDATE_INTERVAL_MAX2000 2000
96/* Amount of miliseconds the update interval is increased */
97#define UPDATE_INTERVAL_INC250 250
98/* Interval at which the update interval is increased */
99#define UPDATE_INTERVAL_TIMEOUT_INTERVAL250 250
100/* Milliseconds that have to pass without a change to reset the update interval */
101#define UPDATE_INTERVAL_RESET1000 1000
102
103#define SILENT_WINDOW_OPEN_LIMIT5 5
104
105#define DUPLICATE_HORIZONTAL_ICON_OFFSET70 70
106#define DUPLICATE_VERTICAL_ICON_OFFSET30 30
107
108#define MAX_QUEUED_UPDATES500 500
109
110#define FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER"/MenuBar/File/Open Placeholder/Open With/Applications Placeholder" "/MenuBar/File/Open Placeholder/Open With/Applications Placeholder"
111#define FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER"/MenuBar/File/Open Placeholder/Applications Placeholder" "/MenuBar/File/Open Placeholder/Applications Placeholder"
112#define FM_DIRECTORY_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER"/MenuBar/File/Open Placeholder/Scripts/Scripts Placeholder" "/MenuBar/File/Open Placeholder/Scripts/Scripts Placeholder"
113#define FM_DIRECTORY_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER"/MenuBar/Edit/Extension Actions" "/MenuBar/Edit/Extension Actions"
114#define FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER"/MenuBar/File/New Items Placeholder/New Documents/New Documents Placeholder" "/MenuBar/File/New Items Placeholder/New Documents/New Documents Placeholder"
115#define FM_DIRECTORY_VIEW_MENU_PATH_OPEN"/MenuBar/File/Open Placeholder/Open" "/MenuBar/File/Open Placeholder/Open"
116
117#define FM_DIRECTORY_VIEW_POPUP_PATH_SELECTION"/selection" "/selection"
118#define FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER"/selection/Open Placeholder/Open With/Applications Placeholder" "/selection/Open Placeholder/Open With/Applications Placeholder"
119#define FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER"/selection/Open Placeholder/Applications Placeholder" "/selection/Open Placeholder/Applications Placeholder"
120#define FM_DIRECTORY_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER"/selection/Open Placeholder/Scripts/Scripts Placeholder" "/selection/Open Placeholder/Scripts/Scripts Placeholder"
121#define FM_DIRECTORY_VIEW_POPUP_PATH_EXTENSION_ACTIONS"/selection/Extension Actions" "/selection/Extension Actions"
122#define FM_DIRECTORY_VIEW_POPUP_PATH_OPEN"/selection/Open Placeholder/Open" "/selection/Open Placeholder/Open"
123
124#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND"/background" "/background"
125#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER"/background/Before Zoom Items/New Object Items/Scripts/Scripts Placeholder" "/background/Before Zoom Items/New Object Items/Scripts/Scripts Placeholder"
126#define FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER"/background/Before Zoom Items/New Object Items/New Documents/New Documents Placeholder" "/background/Before Zoom Items/New Object Items/New Documents/New Documents Placeholder"
127
128#define FM_DIRECTORY_VIEW_POPUP_PATH_LOCATION"/location" "/location"
129
130#define MAX_MENU_LEVELS5 5
131#define TEMPLATE_LIMIT30 30
132
133enum {
134 ADD_FILE,
135 BEGIN_FILE_CHANGES,
136 BEGIN_LOADING,
137 CLEAR,
138 END_FILE_CHANGES,
139 FLUSH_ADDED_FILES,
140 END_LOADING,
141 FILE_CHANGED,
142 LOAD_ERROR,
143 MOVE_COPY_ITEMS,
144 REMOVE_FILE,
145 TRASH,
146 DELETE,
147 LAST_SIGNAL
148};
149
150enum
151{
152 PROP_0,
153 PROP_WINDOW_SLOT
154};
155
156
157static guint signals[LAST_SIGNAL] = { 0 };
158
159static GdkAtom copied_files_atom;
160
161static char *scripts_directory_uri;
162static int scripts_directory_uri_length;
163
164struct FMDirectoryViewDetails
165{
166 CajaWindowInfo *window;
167 CajaWindowSlotInfo *slot;
168 CajaDirectory *model;
169 CajaFile *directory_as_file;
170 CajaFile *location_popup_directory_as_file;
171 GdkEventButton *location_popup_event;
172 GtkActionGroup *dir_action_group;
173 guint dir_merge_id;
174
175 GList *scripts_directory_list;
176 GtkActionGroup *scripts_action_group;
177 guint scripts_merge_id;
178
179 GList *templates_directory_list;
180 GtkActionGroup *templates_action_group;
181 guint templates_merge_id;
182
183 GtkActionGroup *extensions_menu_action_group;
184 guint extensions_menu_merge_id;
185
186 guint display_selection_idle_id;
187 guint update_menus_timeout_id;
188 guint update_status_idle_id;
189 guint reveal_selection_idle_id;
190
191 guint display_pending_source_id;
192 guint changes_timeout_id;
193
194 guint update_interval;
195 guint64 last_queued;
196
197 guint files_added_handler_id;
198 guint files_changed_handler_id;
199 guint load_error_handler_id;
200 guint done_loading_handler_id;
201 guint file_changed_handler_id;
202
203 guint delayed_rename_file_id;
204
205 GList *new_added_files;
206 GList *new_changed_files;
207
208 GHashTable *non_ready_files;
209
210 GList *old_added_files;
211 GList *old_changed_files;
212
213 GList *pending_locations_selected;
214
215 /* whether we are in the active slot */
216 gboolean active;
217
218 /* loading indicates whether this view has begun loading a directory.
219 * This flag should need not be set inside subclasses. FMDirectoryView automatically
220 * sets 'loading' to TRUE before it begins loading a directory's contents and to FALSE
221 * after it finishes loading the directory and its view.
222 */
223 gboolean loading;
224 gboolean menu_states_untrustworthy;
225 gboolean scripts_invalid;
226 gboolean templates_invalid;
227 gboolean reported_load_error;
228
229 /* flag to indicate that no file updates should be dispatched to subclasses.
230 * This is a workaround for bug #87701 that prevents the list view from
231 * losing focus when the underlying GtkTreeView is updated.
232 */
233 gboolean updates_frozen;
234 guint updates_queued;
235 gboolean needs_reload;
236
237 gboolean sort_directories_first;
238
239 gboolean show_foreign_files;
240 gboolean show_hidden_files;
241 gboolean ignore_hidden_file_preferences;
242
243 gboolean show_backup_files;
244
245 gboolean batching_selection_level;
246 gboolean selection_changed_while_batched;
247
248 gboolean selection_was_removed;
249
250 gboolean metadata_for_directory_as_file_pending;
251 gboolean metadata_for_files_in_directory_pending;
252
253 gboolean selection_change_is_due_to_shell;
254 gboolean send_selection_change_to_shell;
255
256 GtkActionGroup *open_with_action_group;
257 guint open_with_merge_id;
258
259 GList *subdirectory_list;
260
261 gboolean allow_moves;
262
263 GdkPoint context_menu_position;
264
265 gboolean undo_active;
266 gboolean redo_active;
267 gchar* undo_action_description;
268 gchar* undo_action_label;
269 gchar* redo_action_description;
270 gchar* redo_action_label;
271};
272
273typedef struct {
274 CajaFile *file;
275 CajaDirectory *directory;
276} FileAndDirectory;
277
278/* forward declarations */
279
280static gboolean display_selection_info_idle_callback (gpointer data);
281static void fm_directory_view_class_init (FMDirectoryViewClass *klass);
282static void fm_directory_view_init (FMDirectoryView *view);
283static void fm_directory_view_duplicate_selection (FMDirectoryView *view,
284 GList *files,
285 GArray *item_locations);
286static void fm_directory_view_create_links_for_files (FMDirectoryView *view,
287 GList *files,
288 GArray *item_locations);
289static void trash_or_delete_files (GtkWindow *parent_window,
290 const GList *files,
291 gboolean delete_if_all_already_in_trash,
292 FMDirectoryView *view);
293static void load_directory (FMDirectoryView *view,
294 CajaDirectory *directory);
295static void fm_directory_view_merge_menus (FMDirectoryView *view);
296static void fm_directory_view_unmerge_menus (FMDirectoryView *view);
297static void fm_directory_view_init_show_hidden_files (FMDirectoryView *view);
298static void fm_directory_view_init_show_backup_files (FMDirectoryView *view);
299static void fm_directory_view_load_location (CajaView *caja_view,
300 const char *location);
301static void fm_directory_view_stop_loading (CajaView *caja_view);
302static void fm_directory_view_drop_proxy_received_uris (FMDirectoryView *view,
303 const GList *source_uri_list,
304 const char *target_uri,
305 GdkDragAction action);
306static void fm_directory_view_drop_proxy_received_netscape_url (FMDirectoryView *view,
307 const char *netscape_url,
308 const char *target_uri,
309 GdkDragAction action);
310static void clipboard_changed_callback (CajaClipboardMonitor *monitor,
311 FMDirectoryView *view);
312static void open_one_in_new_window (gpointer data,
313 gpointer callback_data);
314static void open_one_in_folder_window (gpointer data,
315 gpointer callback_data);
316static void schedule_update_menus (FMDirectoryView *view);
317static void schedule_update_menus_callback (gpointer callback_data);
318static void remove_update_menus_timeout_callback (FMDirectoryView *view);
319static void schedule_update_status (FMDirectoryView *view);
320static void remove_update_status_idle_callback (FMDirectoryView *view);
321static void reset_update_interval (FMDirectoryView *view);
322static void schedule_idle_display_of_pending_files (FMDirectoryView *view);
323static void unschedule_display_of_pending_files (FMDirectoryView *view);
324static void disconnect_model_handlers (FMDirectoryView *view);
325static void metadata_for_directory_as_file_ready_callback (CajaFile *file,
326 gpointer callback_data);
327static void metadata_for_files_in_directory_ready_callback (CajaDirectory *directory,
328 GList *files,
329 gpointer callback_data);
330static void fm_directory_view_trash_state_changed_callback (CajaTrashMonitor *trash,
331 gboolean state,
332 gpointer callback_data);
333static void fm_directory_view_select_file (FMDirectoryView *view,
334 CajaFile *file);
335
336static GdkDragAction ask_link_action (FMDirectoryView *view);
337static void update_templates_directory (FMDirectoryView *view);
338static void user_dirs_changed (FMDirectoryView *view);
339static void fm_directory_view_set_is_active (FMDirectoryView *view,
340 gboolean is_active);
341
342static gboolean file_list_all_are_folders (GList *file_list);
343
344static void action_open_scripts_folder_callback (GtkAction *action,
345 gpointer callback_data);
346static void action_cut_files_callback (GtkAction *action,
347 gpointer callback_data);
348static void action_copy_files_callback (GtkAction *action,
349 gpointer callback_data);
350static void action_paste_files_callback (GtkAction *action,
351 gpointer callback_data);
352static void action_copy_to_next_pane_callback (GtkAction *action,
353 gpointer callback_data);
354static void action_move_to_next_pane_callback (GtkAction *action,
355 gpointer callback_data);
356static void action_rename_callback (GtkAction *action,
357 gpointer callback_data);
358static void action_rename_select_all_callback (GtkAction *action,
359 gpointer callback_data);
360static void action_paste_files_into_callback (GtkAction *action,
361 gpointer callback_data);
362static void action_connect_to_server_link_callback (GtkAction *action,
363 gpointer data);
364static void action_mount_volume_callback (GtkAction *action,
365 gpointer data);
366static void action_unmount_volume_callback (GtkAction *action,
367 gpointer data);
368static void action_format_volume_callback (GtkAction *action,
369 gpointer data);
370static void action_start_volume_callback (GtkAction *action,
371 gpointer data);
372static void action_stop_volume_callback (GtkAction *action,
373 gpointer data);
374static void action_detect_media_callback (GtkAction *action,
375 gpointer data);
376
377/* location popup-related actions */
378
379static void action_location_open_alternate_callback (GtkAction *action,
380 gpointer callback_data);
381static void action_location_open_folder_window_callback (GtkAction *action,
382 gpointer callback_data);
383
384static void action_location_cut_callback (GtkAction *action,
385 gpointer callback_data);
386static void action_location_copy_callback (GtkAction *action,
387 gpointer callback_data);
388static void action_location_trash_callback (GtkAction *action,
389 gpointer callback_data);
390static void action_location_delete_callback (GtkAction *action,
391 gpointer callback_data);
392static void action_location_properties_callback (GtkAction *action,
393 gpointer callback_data);
394
395static void unschedule_pop_up_location_context_menu (FMDirectoryView *view);
396
397static inline void fm_directory_view_widget_to_file_operation_position (FMDirectoryView *view,
398 GdkPoint *position);
399static void fm_directory_view_widget_to_file_operation_position_xy (FMDirectoryView *view,
400 int *x, int *y);
401
402/* undo-related actions */
403
404static void undo_redo_menu_update_callback (CajaUndoStackManager* manager, gpointer arg1, gpointer data);
405
406static void undo_update_menu (FMDirectoryView *view);
407
408static void finish_undoredo_callback (gpointer data);
409
410static void real_action_undo (FMDirectoryView *view);
411
412static void real_action_redo (FMDirectoryView *view);
413
414static void action_undo_callback (GtkAction *action, gpointer callback_data);
415
416static void action_redo_callback (GtkAction *action, gpointer callback_data);
417
418EEL_CLASS_BOILERPLATE (FMDirectoryView, fm_directory_view, GTK_TYPE_SCROLLED_WINDOW)static gpointer parent_class; GType fm_directory_view_get_type
(void) { GType parent_type; static GType type; if (type == 0
) { static GTypeInfo info = { sizeof (FMDirectoryViewClass), (
(void*)0), ((void*)0), (GClassInitFunc) fm_directory_view_class_init
, ((void*)0), ((void*)0), sizeof (FMDirectoryView), 0, (GInstanceInitFunc
) fm_directory_view_init, ((void*)0) }; parent_type = ((gtk_scrolled_window_get_type
())); type = g_type_register_static (parent_type, "FMDirectoryView"
, &info, 0); parent_class = g_type_class_ref (parent_type
); } return type; }
419
420EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, add_file)static void fm_directory_view_unimplemented_add_file (void) {
g_warning ("failed to override signal " "fm_directory_view" "->"
"add_file"); }
421EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, bump_zoom_level)static void fm_directory_view_unimplemented_bump_zoom_level (
void) { g_warning ("failed to override signal " "fm_directory_view"
"->" "bump_zoom_level"); }
422EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, can_zoom_in)static void fm_directory_view_unimplemented_can_zoom_in (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "can_zoom_in"); }
423EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, can_zoom_out)static void fm_directory_view_unimplemented_can_zoom_out (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "can_zoom_out"); }
424EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, clear)static void fm_directory_view_unimplemented_clear (void) { g_warning
("failed to override signal " "fm_directory_view" "->" "clear"
); }
425EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, file_changed)static void fm_directory_view_unimplemented_file_changed (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "file_changed"); }
426EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_background_widget)static void fm_directory_view_unimplemented_get_background_widget
(void) { g_warning ("failed to override signal " "fm_directory_view"
"->" "get_background_widget"); }
427EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_selection)static void fm_directory_view_unimplemented_get_selection (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "get_selection"); }
428EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_selection_for_file_transfer)static void fm_directory_view_unimplemented_get_selection_for_file_transfer
(void) { g_warning ("failed to override signal " "fm_directory_view"
"->" "get_selection_for_file_transfer"); }
429EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_item_count)static void fm_directory_view_unimplemented_get_item_count (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "get_item_count"); }
430EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, is_empty)static void fm_directory_view_unimplemented_is_empty (void) {
g_warning ("failed to override signal " "fm_directory_view" "->"
"is_empty"); }
431EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, reset_to_defaults)static void fm_directory_view_unimplemented_reset_to_defaults
(void) { g_warning ("failed to override signal " "fm_directory_view"
"->" "reset_to_defaults"); }
432EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, restore_default_zoom_level)static void fm_directory_view_unimplemented_restore_default_zoom_level
(void) { g_warning ("failed to override signal " "fm_directory_view"
"->" "restore_default_zoom_level"); }
433EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, select_all)static void fm_directory_view_unimplemented_select_all (void)
{ g_warning ("failed to override signal " "fm_directory_view"
"->" "select_all"); }
434EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, set_selection)static void fm_directory_view_unimplemented_set_selection (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "set_selection"); }
435EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, zoom_to_level)static void fm_directory_view_unimplemented_zoom_to_level (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "zoom_to_level"); }
436EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, get_zoom_level)static void fm_directory_view_unimplemented_get_zoom_level (void
) { g_warning ("failed to override signal " "fm_directory_view"
"->" "get_zoom_level"); }
437EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, invert_selection)static void fm_directory_view_unimplemented_invert_selection (
void) { g_warning ("failed to override signal " "fm_directory_view"
"->" "invert_selection"); }
438
439typedef struct {
440 GAppInfo *application;
441 GList *files;
442 FMDirectoryView *directory_view;
443} ApplicationLaunchParameters;
444
445typedef struct {
446 CajaFile *file;
447 FMDirectoryView *directory_view;
448} ScriptLaunchParameters;
449
450typedef struct {
451 CajaFile *file;
452 FMDirectoryView *directory_view;
453} CreateTemplateParameters;
454
455static ApplicationLaunchParameters *
456application_launch_parameters_new (GAppInfo *application,
457 GList *files,
458 FMDirectoryView *directory_view)
459{
460 ApplicationLaunchParameters *result;
461
462 result = g_new0 (ApplicationLaunchParameters, 1)(ApplicationLaunchParameters *) (__extension__ ({ gsize __n =
(gsize) (1); gsize __s = sizeof (ApplicationLaunchParameters
); 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; }))
;
463 result->application = g_object_ref (application)((__typeof__ (application)) (g_object_ref) (application));
464 result->files = caja_file_list_copy (files);
465
466 if (directory_view != NULL((void*)0)) {
467 g_object_ref (directory_view)((__typeof__ (directory_view)) (g_object_ref) (directory_view
))
;
468 result->directory_view = directory_view;
469 }
470
471 return result;
472}
473
474static void
475application_launch_parameters_free (ApplicationLaunchParameters *parameters)
476{
477 g_object_unref (parameters->application);
478 caja_file_list_free (parameters->files);
479
480 if (parameters->directory_view != NULL((void*)0)) {
481 g_object_unref (parameters->directory_view);
482 }
483
484 g_free (parameters);
485}
486
487static GList *
488file_and_directory_list_to_files (GList *fad_list)
489{
490 GList *res, *l;
491 FileAndDirectory *fad = NULL((void*)0);
492
493 res = NULL((void*)0);
494 for (l = fad_list; l != NULL((void*)0); l = l->next) {
495 fad = l->data;
496 res = g_list_prepend (res, caja_file_ref (fad->file));
497 }
498 return g_list_reverse (res);
499}
500
501
502static GList *
503file_and_directory_list_from_files (CajaDirectory *directory, GList *files)
504{
505 GList *res, *l;
506 FileAndDirectory *fad = NULL((void*)0);
507
508 res = NULL((void*)0);
509 for (l = files; l != NULL((void*)0); l = l->next) {
510 fad = g_new0 (FileAndDirectory, 1)(FileAndDirectory *) (__extension__ ({ gsize __n = (gsize) (1
); gsize __s = sizeof (FileAndDirectory); 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; }))
;
511 fad->directory = caja_directory_ref (directory);
512 fad->file = caja_file_ref (l->data);
513 res = g_list_prepend (res, fad);
514 }
515 return g_list_reverse (res);
516}
517
518static void
519file_and_directory_free (FileAndDirectory *fad)
520{
521 caja_directory_unref (fad->directory);
522 caja_file_unref (fad->file);
523 g_free (fad);
524}
525
526
527static void
528file_and_directory_list_free (GList *list)
529{
530 GList *l;
531
532 for (l = list; l != NULL((void*)0); l = l->next) {
533 file_and_directory_free (l->data);
534 }
535
536 g_list_free (list);
537}
538
539static gboolean
540file_and_directory_equal (gconstpointer v1,
541 gconstpointer v2)
542{
543 const FileAndDirectory *fad1, *fad2;
544 fad1 = v1;
545 fad2 = v2;
546
547 return (fad1->file == fad2->file &&
548 fad1->directory == fad2->directory);
549}
550
551static guint
552file_and_directory_hash (gconstpointer v)
553{
554 const FileAndDirectory *fad;
555
556 fad = v;
557 return GPOINTER_TO_UINT (fad->file)((guint) (gulong) (fad->file)) ^ GPOINTER_TO_UINT (fad->directory)((guint) (gulong) (fad->directory));
558}
559
560
561
562
563static ScriptLaunchParameters *
564script_launch_parameters_new (CajaFile *file,
565 FMDirectoryView *directory_view)
566{
567 ScriptLaunchParameters *result;
568
569 result = g_new0 (ScriptLaunchParameters, 1)(ScriptLaunchParameters *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (ScriptLaunchParameters); 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; }))
;
570 g_object_ref (directory_view)((__typeof__ (directory_view)) (g_object_ref) (directory_view
))
;
571 result->directory_view = directory_view;
572 caja_file_ref (file);
573 result->file = file;
574
575 return result;
576}
577
578static void
579script_launch_parameters_free (ScriptLaunchParameters *parameters)
580{
581 g_object_unref (parameters->directory_view);
582 caja_file_unref (parameters->file);
583 g_free (parameters);
584}
585
586static CreateTemplateParameters *
587create_template_parameters_new (CajaFile *file,
588 FMDirectoryView *directory_view)
589{
590 CreateTemplateParameters *result;
591
592 result = g_new0 (CreateTemplateParameters, 1)(CreateTemplateParameters *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (CreateTemplateParameters); 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; }))
;
593 g_object_ref (directory_view)((__typeof__ (directory_view)) (g_object_ref) (directory_view
))
;
594 result->directory_view = directory_view;
595 caja_file_ref (file);
596 result->file = file;
597
598 return result;
599}
600
601static void
602create_templates_parameters_free (CreateTemplateParameters *parameters)
603{
604 g_object_unref (parameters->directory_view);
605 caja_file_unref (parameters->file);
606 g_free (parameters);
607}
608
609CajaWindowInfo *
610fm_directory_view_get_caja_window (FMDirectoryView *view)
611{
612 g_assert (view->details->window != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if (view->details->window != ((void*)0)) _g_boolean_var_178
= 1; else _g_boolean_var_178 = 0; _g_boolean_var_178; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 612, ((const char*) (__func__)), "view->details->window != NULL"
); } while (0)
;
613
614 return view->details->window;
615}
616
617CajaWindowSlotInfo *
618fm_directory_view_get_caja_window_slot (FMDirectoryView *view)
619{
620 g_assert (view->details->slot != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (view->details->slot != ((void*)0)) _g_boolean_var_179
= 1; else _g_boolean_var_179 = 0; _g_boolean_var_179; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 620, ((const char*) (__func__)), "view->details->slot != NULL"
); } while (0)
;
621
622 return view->details->slot;
623}
624
625/* Returns the GtkWindow that this directory view occupies, or NULL
626 * if at the moment this directory view is not in a GtkWindow or the
627 * GtkWindow cannot be determined. Primarily used for parenting dialogs.
628 */
629GtkWindow *
630fm_directory_view_get_containing_window (FMDirectoryView *view)
631{
632 GtkWidget *window;
633
634 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_180
= 1; else _g_boolean_var_180 = 0; _g_boolean_var_180; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 634, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
635
636 window = gtk_widget_get_ancestor (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))), GTK_TYPE_WINDOW(gtk_window_get_type ()));
637 if (window == NULL((void*)0)) {
638 return NULL((void*)0);
639 }
640
641 return GTK_WINDOW (window)((((GtkWindow*) (void *) ((window)))));
642}
643
644static gboolean
645fm_directory_view_confirm_multiple (GtkWindow *parent_window,
646 int count,
647 gboolean tabs)
648{
649 GtkDialog *dialog;
650 char *prompt;
651 char *detail;
652 int response;
653
654 if (count <= SILENT_WINDOW_OPEN_LIMIT5) {
655 return TRUE(!(0));
656 }
657
658 prompt = _("Are you sure you want to open all files?")dcgettext (((void*)0), "Are you sure you want to open all files?"
, 5)
;
659 if (tabs) {
660 detail = g_strdup_printf (ngettext("This will open %'d separate tab.",dcngettext (((void*)0), "This will open %'d separate tab.", "This will open %'d separate tabs."
, count, 5)
661 "This will open %'d separate tabs.", count)dcngettext (((void*)0), "This will open %'d separate tab.", "This will open %'d separate tabs."
, count, 5)
, count);
662 } else {
663 detail = g_strdup_printf (ngettext("This will open %'d separate window.",dcngettext (((void*)0), "This will open %'d separate window."
, "This will open %'d separate windows.", count, 5)
664 "This will open %'d separate windows.", count)dcngettext (((void*)0), "This will open %'d separate window."
, "This will open %'d separate windows.", count, 5)
, count);
665 }
666 dialog = eel_show_yes_no_dialog (prompt, detail,
667 "gtk-ok", "process-stop",
668 parent_window);
669 g_free (detail);
670
671 response = gtk_dialog_run (dialog);
672 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
673
674 return response == GTK_RESPONSE_YES;
675}
676
677static gboolean
678selection_contains_one_item_in_menu_callback (FMDirectoryView *view, GList *selection)
679{
680 if (eel_g_list_exactly_one_item (selection)) {
681 return TRUE(!(0));
682 }
683
684 /* If we've requested a menu update that hasn't yet occurred, then
685 * the mismatch here doesn't surprise us, and we won't complain.
686 * Otherwise, we will complain.
687 */
688 if (!view->details->menu_states_untrustworthy) {
689 g_warning ("Expected one selected item, found %'d. No action will be performed.",
690 g_list_length (selection));
691 }
692
693 return FALSE(0);
694}
695
696static gboolean
697selection_not_empty_in_menu_callback (FMDirectoryView *view, GList *selection)
698{
699 if (selection != NULL((void*)0)) {
700 return TRUE(!(0));
701 }
702
703 /* If we've requested a menu update that hasn't yet occurred, then
704 * the mismatch here doesn't surprise us, and we won't complain.
705 * Otherwise, we will complain.
706 */
707 if (!view->details->menu_states_untrustworthy) {
708 g_warning ("Empty selection found when selection was expected. No action will be performed.");
709 }
710
711 return FALSE(0);
712}
713
714static char *
715get_view_directory (FMDirectoryView *view)
716{
717 char *uri, *path;
718 GFile *f;
719
720 uri = caja_directory_get_uri (view->details->model);
721 if (eel_uri_is_desktop (uri)) {
722 g_free (uri);
723 uri = caja_get_desktop_directory_uri ();
724
725 }
726 f = g_file_new_for_uri (uri);
727 path = g_file_get_path (f);
728 g_object_unref (f);
729 g_free (uri);
730
731 return path;
732}
733
734void
735fm_directory_view_activate_files (FMDirectoryView *view,
736 GList *files,
737 CajaWindowOpenMode mode,
738 CajaWindowOpenFlags flags,
739 gboolean confirm_multiple)
740{
741 char *path;
742
743 path = get_view_directory (view);
744 caja_mime_activate_files (fm_directory_view_get_containing_window (view),
745 view->details->slot,
746 files,
747 path,
748 mode,
749 flags,
750 confirm_multiple);
751
752 g_free (path);
753}
754
755void
756fm_directory_view_activate_file (FMDirectoryView *view,
757 CajaFile *file,
758 CajaWindowOpenMode mode,
759 CajaWindowOpenFlags flags)
760{
761 char *path;
762
763 path = get_view_directory (view);
764 caja_mime_activate_file (fm_directory_view_get_containing_window (view),
765 view->details->slot,
766 file,
767 path,
768 mode,
769 flags);
770
771 g_free (path);
772}
773
774static void
775action_open_callback (GtkAction *action,
776 gpointer callback_data)
777{
778 GList *selection;
779 FMDirectoryView *view;
780
781 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
782
783 selection = fm_directory_view_get_selection (view);
784 fm_directory_view_activate_files (view,
785 selection,
786 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
787 0,
788 TRUE(!(0)));
789 caja_file_list_free (selection);
790}
791
792static void
793action_open_close_parent_callback (GtkAction *action,
794 gpointer callback_data)
795{
796 GList *selection;
797 FMDirectoryView *view;
798
799 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
800
801 selection = fm_directory_view_get_selection (view);
802 fm_directory_view_activate_files (view,
803 selection,
804 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
805 CAJA_WINDOW_OPEN_FLAG_CLOSE_BEHIND,
806 TRUE(!(0)));
807 caja_file_list_free (selection);
808}
809
810
811static void
812action_open_alternate_callback (GtkAction *action,
813 gpointer callback_data)
814{
815 FMDirectoryView *view;
816 GList *selection;
817 GtkWindow *window;
818
819 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
820 selection = fm_directory_view_get_selection (view);
821
822 window = fm_directory_view_get_containing_window (view);
823
824 if (fm_directory_view_confirm_multiple (window, g_list_length (selection), FALSE(0))) {
825 g_list_foreach (selection, open_one_in_new_window, view);
826 }
827
828 caja_file_list_free (selection);
829}
830
831static void
832action_open_new_tab_callback (GtkAction *action,
833 gpointer callback_data)
834{
835 FMDirectoryView *view;
836 GList *selection;
837 GtkWindow *window;
838
839 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
840 selection = fm_directory_view_get_selection (view);
841
842 window = fm_directory_view_get_containing_window (view);
843
844 if (fm_directory_view_confirm_multiple (window, g_list_length (selection), TRUE(!(0)))) {
845 fm_directory_view_activate_files (view,
846 selection,
847 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
848 CAJA_WINDOW_OPEN_FLAG_NEW_TAB,
849 FALSE(0));
850 }
851
852 caja_file_list_free (selection);
853}
854
855static void
856action_open_folder_window_callback (GtkAction *action,
857 gpointer callback_data)
858{
859 FMDirectoryView *view;
860 GList *selection;
861 GtkWindow *window;
862
863 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
864 selection = fm_directory_view_get_selection (view);
865
866 window = fm_directory_view_get_containing_window (view);
867
868 if (fm_directory_view_confirm_multiple (window, g_list_length (selection), FALSE(0))) {
869 g_list_foreach (selection, open_one_in_folder_window, view);
870 }
871
872 caja_file_list_free (selection);
873}
874
875static void
876open_location (FMDirectoryView *directory_view,
877 const char *new_uri,
878 CajaWindowOpenMode mode,
879 CajaWindowOpenFlags flags)
880{
881 GtkWindow *window;
882 GFile *location;
883
884 g_assert (FM_IS_DIRECTORY_VIEW (directory_view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory_view)); GType __t = (fm_directory_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_181 = 1; else _g_boolean_var_181 =
0; _g_boolean_var_181; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 884, ((const char*) (__func__
)), "FM_IS_DIRECTORY_VIEW (directory_view)"); } while (0)
;
885 g_assert (new_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if (new_uri != ((void*)0)) _g_boolean_var_182 = 1; else _g_boolean_var_182
= 0; _g_boolean_var_182; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 885, ((const char*) (__func__
)), "new_uri != NULL"); } while (0)
;
886
887 window = fm_directory_view_get_containing_window (directory_view);
888 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
889 "directory view open_location window=%p: %s", window, new_uri);
890 location = g_file_new_for_uri (new_uri);
891 caja_window_slot_info_open_location (directory_view->details->slot,caja_window_slot_info_open_location_full(directory_view->details
->slot, location, mode, flags, ((void*)0), ((void*)0), ((void
*)0))
892 location, mode, flags, NULL)caja_window_slot_info_open_location_full(directory_view->details
->slot, location, mode, flags, ((void*)0), ((void*)0), ((void
*)0))
;
893 g_object_unref (location);
894}
895
896static void
897application_selected_cb (CajaOpenWithDialog *dialog,
898 GAppInfo *app,
899 gpointer user_data)
900{
901 GtkWindow *parent_window;
902 CajaFile *file;
903 GList files;
904
905 parent_window = GTK_WINDOW (user_data)((((GtkWindow*) (void *) ((user_data)))));
906
907 file = g_object_get_data (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "directory-view:file");
908
909 files.next = NULL((void*)0);
910 files.prev = NULL((void*)0);
911 files.data = file;
912 caja_launch_application (app, &files, parent_window);
913}
914
915static void
916choose_program (FMDirectoryView *view,
917 CajaFile *file)
918{
919 GtkWidget *dialog;
920 char *uri;
921 char *mime_type;
922
923 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_183
= 1; else _g_boolean_var_183 = 0; _g_boolean_var_183; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 923, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
924 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_184
= 1; else _g_boolean_var_184 = 0; _g_boolean_var_184; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 924, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
925
926 caja_file_ref (file);
927 uri = caja_file_get_uri (file);
928 mime_type = caja_file_get_mime_type (file);
929
930 dialog = caja_open_with_dialog_new (uri, mime_type, NULL((void*)0));
931 g_object_set_data_full (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))),
932 "directory-view:file",
933 g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)),
934 (GDestroyNotify)g_object_unref);
935
936 gtk_window_set_screen (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))),
937 gtk_widget_get_screen (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))));
938 gtk_widget_show (dialog);
939
940 g_signal_connect_object (dialog,
941 "application_selected",
942 G_CALLBACK (application_selected_cb)((GCallback) (application_selected_cb)),
943 fm_directory_view_get_containing_window (view),
944 0);
945
946 g_free (uri);
947 g_free (mime_type);
948 caja_file_unref (file);
949}
950
951static void
952open_with_other_program (FMDirectoryView *view)
953{
954 GList *selection;
955
956 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_185
= 1; else _g_boolean_var_185 = 0; _g_boolean_var_185; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 956, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
957
958 selection = fm_directory_view_get_selection (view);
959
960 if (selection_contains_one_item_in_menu_callback (view, selection)) {
961 choose_program (view, CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data))))));
962 }
963
964 caja_file_list_free (selection);
965}
966
967static void
968action_other_application_callback (GtkAction *action,
969 gpointer callback_data)
970{
971 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_186 = 1; else _g_boolean_var_186 =
0; _g_boolean_var_186; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 971, ((const char*) (__func__
)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (0)
;
972
973 open_with_other_program (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))));
974}
975
976static void
977trash_or_delete_selected_files (FMDirectoryView *view)
978{
979 /* This might be rapidly called multiple times for the same selection
980 * when using keybindings. So we remember if the current selection
981 * was already removed (but the view doesn't know about it yet).
982 */
983 if (!view->details->selection_was_removed) {
984 GList *selection;
985
986 selection = fm_directory_view_get_selection_for_file_transfer (view);
987 trash_or_delete_files (fm_directory_view_get_containing_window (view),
988 selection, TRUE(!(0)),
989 view);
990 caja_file_list_free (selection);
991 view->details->selection_was_removed = TRUE(!(0));
992 }
993}
994
995static gboolean
996real_trash (FMDirectoryView *view)
997{
998 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
999 GtkAction *action;
1000
1001 action = gtk_action_group_get_action (view->details->dir_action_group,
1002 FM_ACTION_TRASH"Trash");
1003 if (gtk_action_get_sensitive (action) &&
1004 gtk_action_get_visible (action)) {
1005 trash_or_delete_selected_files (view);
1006 return TRUE(!(0));
1007 }
1008 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
1009 return FALSE(0);
1010}
1011
1012static void
1013action_trash_callback (GtkAction *action,
1014 gpointer callback_data)
1015{
1016 trash_or_delete_selected_files (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))));
1017}
1018
1019static void
1020delete_selected_files (FMDirectoryView *view)
1021{
1022 GList *selection;
1023 GList *node;
1024 GList *locations;
1025
1026 selection = fm_directory_view_get_selection_for_file_transfer (view);
1027 if (selection == NULL((void*)0)) {
1028 return;
1029 }
1030
1031 locations = NULL((void*)0);
1032 for (node = selection; node != NULL((void*)0); node = node->next) {
1033 locations = g_list_prepend (locations,
1034 caja_file_get_location ((CajaFile *) node->data));
1035 }
1036 locations = g_list_reverse (locations);
1037
1038 caja_file_operations_delete (locations, fm_directory_view_get_containing_window (view), NULL((void*)0), NULL((void*)0));
1039
1040 g_list_free_full (locations, g_object_unref);
1041 caja_file_list_free (selection);
1042}
1043
1044static void
1045action_delete_callback (GtkAction *action,
1046 gpointer callback_data)
1047{
1048 delete_selected_files (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))));
1049}
1050
1051static void
1052action_restore_from_trash_callback (GtkAction *action,
1053 gpointer callback_data)
1054{
1055 FMDirectoryView *view;
1056 GList *selection;
1057
1058 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1059
1060 selection = fm_directory_view_get_selection_for_file_transfer (view);
1061 caja_restore_files_from_trash (selection,
1062 fm_directory_view_get_containing_window (view));
1063
1064 caja_file_list_free (selection);
1065
1066}
1067
1068static gboolean
1069real_delete (FMDirectoryView *view)
1070{
1071 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
1072 GtkAction *action;
1073
1074 action = gtk_action_group_get_action (view->details->dir_action_group,
1075 FM_ACTION_TRASH"Trash");
1076 if (gtk_action_get_sensitive (action) &&
1077 gtk_action_get_visible (action)) {
1078 delete_selected_files (view);
1079 return TRUE(!(0));
1080 }
1081 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
1082 return FALSE(0);
1083}
1084
1085static void
1086action_duplicate_callback (GtkAction *action,
1087 gpointer callback_data)
1088{
1089 FMDirectoryView *view;
1090 GList *selection;
1091
1092 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1093 selection = fm_directory_view_get_selection_for_file_transfer (view);
1094 if (selection_not_empty_in_menu_callback (view, selection)) {
1095 GArray *selected_item_locations;
1096
1097 /* FIXME bugzilla.gnome.org 45061:
1098 * should change things here so that we use a get_icon_locations (view, selection).
1099 * Not a problem in this case but in other places the selection may change by
1100 * the time we go and retrieve the icon positions, relying on the selection
1101 * staying intact to ensure the right sequence and count of positions is fragile.
1102 */
1103 selected_item_locations = fm_directory_view_get_selected_icon_locations (view);
1104 fm_directory_view_duplicate_selection (view, selection, selected_item_locations);
1105 g_array_free (selected_item_locations, TRUE(!(0)));
1106 }
1107
1108 caja_file_list_free (selection);
1109}
1110
1111static void
1112action_create_link_callback (GtkAction *action,
1113 gpointer callback_data)
1114{
1115 FMDirectoryView *view;
1116 GList *selection;
1117
1118 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_187 = 1; else _g_boolean_var_187 =
0; _g_boolean_var_187; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1118, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1119
1120 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1121 selection = fm_directory_view_get_selection (view);
1122 if (selection_not_empty_in_menu_callback (view, selection)) {
1123 GArray *selected_item_locations;
1124
1125 selected_item_locations = fm_directory_view_get_selected_icon_locations (view);
1126 fm_directory_view_create_links_for_files (view, selection, selected_item_locations);
1127 g_array_free (selected_item_locations, TRUE(!(0)));
1128 }
1129
1130 caja_file_list_free (selection);
1131}
1132
1133static void
1134action_select_all_callback (GtkAction *action,
1135 gpointer callback_data)
1136{
1137 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_188 = 1; else _g_boolean_var_188 =
0; _g_boolean_var_188; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1137, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1138
1139 fm_directory_view_select_all (callback_data);
1140}
1141
1142static void
1143action_invert_selection_callback (GtkAction *action,
1144 gpointer callback_data)
1145{
1146 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_189 = 1; else _g_boolean_var_189 =
0; _g_boolean_var_189; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1146, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1147
1148 fm_directory_view_invert_selection (callback_data);
1149}
1150
1151
1152static void
1153pattern_select_response_cb (GtkWidget *dialog, int response, gpointer user_data)
1154{
1155 FMDirectoryView *view;
1156 CajaDirectory *directory;
1157 GtkWidget *entry;
1158 GList *selection;
1159 GError *error;
1160
1161 view = FM_DIRECTORY_VIEW (user_data)((((FMDirectoryView*) (void *) ((user_data)))));
1162
1163 switch (response) {
1164 case GTK_RESPONSE_OK :
1165 entry = g_object_get_data (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "entry");
1166 directory = fm_directory_view_get_model (view);
1167 selection = caja_directory_match_pattern (directory,
1168 gtk_entry_get_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry)))))));
1169
1170 if (selection) {
1171 fm_directory_view_set_selection (view, selection);
1172 caja_file_list_free (selection);
1173
1174 fm_directory_view_reveal_selection(view);
1175 }
1176 /* fall through */
1177 case GTK_RESPONSE_NONE :
1178 case GTK_RESPONSE_DELETE_EVENT :
1179 case GTK_RESPONSE_CANCEL :
1180 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1181 break;
1182 case GTK_RESPONSE_HELP :
1183 error = NULL((void*)0);
1184 gtk_show_uri_on_window (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))),
1185 "help:mate-user-guide/caja-select-pattern",
1186 gtk_get_current_event_time (), &error);
1187 if (error) {
1188 eel_show_error_dialog (_("There was an error displaying help.")dcgettext (((void*)0), "There was an error displaying help.",
5)
, error->message,
1189 GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))));
1190 g_error_free (error);
1191 }
1192 break;
1193 default :
1194 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 1194, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1195 }
1196}
1197
1198static void
1199select_pattern (FMDirectoryView *view)
1200{
1201 GtkWidget *dialog;
1202 GtkWidget *label;
1203 GtkWidget *example;
1204 GtkWidget *grid;
1205 GtkWidget *entry;
1206 char *example_pattern;
1207
1208 dialog = gtk_dialog_new ();
1209 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), _("Select Items Matching")dcgettext (((void*)0), "Select Items Matching", 5));
1210 gtk_window_set_transient_for (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), fm_directory_view_get_containing_window (view));
1211 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
1212
1213 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1214 _("_Help")dcgettext (((void*)0), "_Help", 5),
1215 "help-browser",
1216 GTK_RESPONSE_HELP);
1217
1218 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1219 _("_Cancel")dcgettext (((void*)0), "_Cancel", 5),
1220 "process-stop",
1221 GTK_RESPONSE_CANCEL);
1222
1223 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1224 _("_OK")dcgettext (((void*)0), "_OK", 5),
1225 "gtk-ok",
1226 GTK_RESPONSE_OK);
1227
1228 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1229 GTK_RESPONSE_OK);
1230 gtk_container_set_border_width (GTK_CONTAINER (dialog)((((GtkContainer*) (void *) ((dialog))))), 5);
1231 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dialog)))))))))))
, 2);
1232
1233 label = gtk_label_new_with_mnemonic (_("_Pattern:")dcgettext (((void*)0), "_Pattern:", 5));
1234
1235 gtk_widget_set_halign (label, GTK_ALIGN_START);
1236
1237 example = gtk_label_new (NULL((void*)0));
1238 gtk_widget_set_halign (example, GTK_ALIGN_START);
1239 example_pattern = g_strdup_printf ("<b>%s</b><i>%s</i>",
1240 _("Examples: ")dcgettext (((void*)0), "Examples: ", 5),
1241 "*.png, file\?\?.txt, pict*.\?\?\?");
1242 gtk_label_set_markup (GTK_LABEL (example)((((GtkLabel*) (void *) ((example))))), example_pattern);
1243 g_free (example_pattern);
1244 gtk_widget_set_halign (example, GTK_ALIGN_START);
1245
1246 entry = gtk_entry_new ();
1247 gtk_entry_set_activates_default (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))), TRUE(!(0)));
1248 gtk_widget_set_hexpand (entry, TRUE(!(0)));
1249
1250 grid = gtk_grid_new ();
1251 g_object_set (grid,
1252 "orientation", GTK_ORIENTATION_VERTICAL,
1253 "border-width", 6,
1254 "row-spacing", 6,
1255 "column-spacing", 12,
1256 NULL((void*)0));
1257
1258 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), label);
1259 gtk_grid_attach_next_to (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), entry, label,
1260 GTK_POS_RIGHT, 1, 1);
1261 gtk_grid_attach_next_to (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), example, entry,
1262 GTK_POS_BOTTOM, 1, 1);
1263
1264 gtk_label_set_mnemonic_widget (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), entry);
1265 gtk_widget_show_all (grid);
1266 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkContainer*) (void *) ((gtk_dialog_get_content_area (((
((GtkDialog*) (void *) ((dialog)))))))))))
, grid);
1267
1268 g_object_set_data (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "entry", entry);
1269 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
pattern_select_response_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1270 G_CALLBACK (pattern_select_response_cb),g_signal_connect_data ((dialog), ("response"), (((GCallback) (
pattern_select_response_cb))), (view), ((void*)0), (GConnectFlags
) 0)
1271 view)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
pattern_select_response_cb))), (view), ((void*)0), (GConnectFlags
) 0)
;
1272 gtk_widget_show_all (dialog);
1273}
1274
1275static void
1276action_select_pattern_callback (GtkAction *action,
1277 gpointer callback_data)
1278{
1279 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_190 = 1; else _g_boolean_var_190 =
0; _g_boolean_var_190; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1279, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1280
1281 select_pattern(callback_data);
1282}
1283
1284static void
1285action_reset_to_defaults_callback (GtkAction *action,
1286 gpointer callback_data)
1287{
1288 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_191 = 1; else _g_boolean_var_191 =
0; _g_boolean_var_191; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1288, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1289
1290 fm_directory_view_reset_to_defaults (callback_data);
1291}
1292
1293
1294static void
1295hidden_files_mode_changed (CajaWindow *window,
1296 gpointer callback_data)
1297{
1298 FMDirectoryView *directory_view;
1299
1300 directory_view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1301
1302 fm_directory_view_init_show_hidden_files (directory_view);
1303}
1304
1305static void
1306backup_files_mode_changed (CajaWindow *window,
1307 gpointer callback_data)
1308{
1309 FMDirectoryView *directory_view;
1310
1311 directory_view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1312
1313 fm_directory_view_init_show_backup_files (directory_view);
1314}
1315
1316static void
1317action_save_search_callback (GtkAction *action,
1318 gpointer callback_data)
1319{
1320 FMDirectoryView *directory_view;
1321
1322 directory_view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1323
1324 if (directory_view->details->model &&
1325 CAJA_IS_SEARCH_DIRECTORY (directory_view->details->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory_view->details->model)); GType __t = (caja_search_directory_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; }))))
) {
1326 CajaSearchDirectory *search;
1327
1328 search = CAJA_SEARCH_DIRECTORY (directory_view->details->model)((((CajaSearchDirectory*) (void *) ((directory_view->details
->model)))))
;
1329 caja_search_directory_save_search (search);
1330
1331 /* Save search is disabled */
1332 schedule_update_menus (directory_view);
1333 }
1334}
1335
1336static void
1337query_name_entry_changed_cb (GtkWidget *entry, GtkWidget *button)
1338{
1339 const char *text;
1340 gboolean sensitive;
1341
1342 text = gtk_entry_get_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))));
1343
1344 sensitive = (text != NULL((void*)0)) && (*text != 0);
1345
1346 gtk_widget_set_sensitive (button, sensitive);
1347}
1348
1349
1350static void
1351action_save_search_as_callback (GtkAction *action,
1352 gpointer callback_data)
1353{
1354 FMDirectoryView *directory_view;
1355
1356 directory_view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1357
1358 if (directory_view->details->model &&
1359 CAJA_IS_SEARCH_DIRECTORY (directory_view->details->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory_view->details->model)); GType __t = (caja_search_directory_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; }))))
) {
1360 CajaSearchDirectory *search;
1361 GtkWidget *dialog, *grid, *label, *entry, *chooser, *save_button;
1362
1363 search = CAJA_SEARCH_DIRECTORY (directory_view->details->model)((((CajaSearchDirectory*) (void *) ((directory_view->details
->model)))))
;
1364
1365 dialog = gtk_dialog_new ();
1366 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), _("Save Search as")dcgettext (((void*)0), "Save Search as", 5));
1367 gtk_window_set_transient_for (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), fm_directory_view_get_containing_window (directory_view));
1368
1369 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1370 _("_Cancel")dcgettext (((void*)0), "_Cancel", 5),
1371 "process-stop",
1372 GTK_RESPONSE_CANCEL);
1373
1374 save_button = eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), _("_Save")dcgettext (((void*)0), "_Save", 5),
1375 "document-save", GTK_RESPONSE_OK);
1376
1377 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1378 GTK_RESPONSE_OK);
1379 gtk_container_set_border_width (GTK_CONTAINER (dialog)((((GtkContainer*) (void *) ((dialog))))), 5);
1380 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dialog)))))))))))
, 2);
1381 gtk_window_set_resizable (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), FALSE(0));
1382
1383 grid = gtk_grid_new ();
1384 g_object_set (grid,
1385 "orientation", GTK_ORIENTATION_VERTICAL,
1386 "border-width", 5,
1387 "row-spacing", 6,
1388 "column-spacing", 12,
1389 NULL((void*)0));
1390 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dialog)))))))))))
, grid, TRUE(!(0)), TRUE(!(0)), 0);
1391 gtk_widget_show (grid);
1392
1393 label = gtk_label_new_with_mnemonic (_("Search _name:")dcgettext (((void*)0), "Search _name:", 5));
1394 gtk_label_set_xalign (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), 0.0);
1395 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), label);
1396 gtk_widget_show (label);
1397 entry = gtk_entry_new ();
1398 gtk_widget_set_hexpand (entry, TRUE(!(0)));
1399 gtk_grid_attach_next_to (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), entry, label,
1400 GTK_POS_RIGHT, 1, 1);
1401 gtk_entry_set_activates_default (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))), TRUE(!(0)));
1402 gtk_label_set_mnemonic_widget (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), entry);
1403
1404 gtk_widget_set_sensitive (save_button, FALSE(0));
1405 g_signal_connect (entry, "changed",g_signal_connect_data ((entry), ("changed"), (((GCallback) (query_name_entry_changed_cb
))), (save_button), ((void*)0), (GConnectFlags) 0)
1406 G_CALLBACK (query_name_entry_changed_cb), save_button)g_signal_connect_data ((entry), ("changed"), (((GCallback) (query_name_entry_changed_cb
))), (save_button), ((void*)0), (GConnectFlags) 0)
;
1407
1408 gtk_widget_show (entry);
1409 label = gtk_label_new_with_mnemonic (_("_Folder:")dcgettext (((void*)0), "_Folder:", 5));
1410 gtk_label_set_xalign (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), 0.0);
1411 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), label);
1412 gtk_widget_show (label);
1413
1414 chooser = gtk_file_chooser_button_new (_("Select Folder to Save Search In")dcgettext (((void*)0), "Select Folder to Save Search In", 5),
1415 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
1416 gtk_widget_set_hexpand (chooser, TRUE(!(0)));
1417 gtk_grid_attach_next_to (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), chooser, label,
1418 GTK_POS_RIGHT, 1, 1);
1419 gtk_label_set_mnemonic_widget (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), chooser);
1420 gtk_widget_show (chooser);
1421
1422 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser)((((GtkFileChooser*) (void *) ((chooser))))), TRUE(!(0)));
1423
1424 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser)((((GtkFileChooser*) (void *) ((chooser))))),
1425 g_get_home_dir ());
1426
1427 if (gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog)))))) == GTK_RESPONSE_OK) {
1428 const char *entry_text;
1429 char *filename, *filename_utf8, *dirname, *path, *uri;
1430 GFile *location;
1431
1432 entry_text = gtk_entry_get_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))));
1433 if (g_str_has_suffix (entry_text, CAJA_SAVED_SEARCH_EXTENSION)(__builtin_constant_p (".savedSearch")? __extension__ ({ const
char * const __str = (entry_text); const char * const __suffix
= (".savedSearch"); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_192; if (__str == ((void
*)0) || __suffix == ((void*)0)) _g_boolean_var_192 = 1; else _g_boolean_var_192
= 0; _g_boolean_var_192; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (entry_text, ".savedSearch") )
) {
1434 filename_utf8 = g_strdup (entry_text)g_strdup_inline (entry_text);
1435 } else {
1436 filename_utf8 = g_strconcat (entry_text, CAJA_SAVED_SEARCH_EXTENSION".savedSearch", NULL((void*)0));
1437 }
1438
1439 filename = g_filename_from_utf8 (filename_utf8, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
1440 g_free (filename_utf8);
1441
1442 dirname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)((((GtkFileChooser*) (void *) ((chooser))))));
1443
1444 path = g_build_filename (dirname, filename, NULL((void*)0));
1445 g_free (filename);
1446 g_free (dirname);
1447
1448 uri = g_filename_to_uri (path, NULL((void*)0), NULL((void*)0));
1449 g_free (path);
1450
1451 caja_search_directory_save_to_file (search, uri);
1452 location = g_file_new_for_uri (uri);
1453 caja_file_changes_queue_file_added (location);
1454 g_object_unref (location);
1455 caja_file_changes_consume_changes (TRUE(!(0)));
1456 g_free (uri);
1457 }
1458
1459 gtk_widget_destroy (dialog);
1460 }
1461}
1462
1463
1464static void
1465action_empty_trash_callback (GtkAction *action,
1466 gpointer callback_data)
1467{
1468 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_193 = 1; else _g_boolean_var_193 =
0; _g_boolean_var_193; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1468, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1469
1470 caja_file_operations_empty_trash (GTK_WIDGET (callback_data)((((GtkWidget*) (void *) ((callback_data))))));
1471}
1472
1473static void
1474action_new_folder_callback (GtkAction *action,
1475 gpointer callback_data)
1476{
1477 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_194 = 1; else _g_boolean_var_194 =
0; _g_boolean_var_194; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1477, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1478
1479 fm_directory_view_new_folder (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))));
1480}
1481
1482static void
1483action_new_empty_file_callback (GtkAction *action,
1484 gpointer callback_data)
1485{
1486 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_195 = 1; else _g_boolean_var_195 =
0; _g_boolean_var_195; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1486, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1487
1488 fm_directory_view_new_file (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))), NULL((void*)0), NULL((void*)0));
1489}
1490
1491static void
1492action_new_launcher_callback (GtkAction *action,
1493 gpointer callback_data)
1494{
1495 char *parent_uri;
1496 FMDirectoryView *view;
1497 GtkWindow *window;
1498
1499 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_196 = 1; else _g_boolean_var_196 =
0; _g_boolean_var_196; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1499, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1500
1501 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1502
1503 parent_uri = fm_directory_view_get_backing_uri (view);
1504
1505 window = fm_directory_view_get_containing_window (view);
1506 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1507 "directory view create new launcher in window=%p: %s", window, parent_uri);
1508 caja_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))),
1509 "mate-desktop-item-edit",
1510 "mate-desktop-item-edit",
1511 FALSE(0),
1512 "--create-new", parent_uri, NULL((void*)0));
1513
1514 g_free (parent_uri);
1515}
1516
1517static void
1518action_properties_callback (GtkAction *action,
1519 gpointer callback_data)
1520{
1521 FMDirectoryView *view;
1522 GList *selection;
1523
1524 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_197 = 1; else _g_boolean_var_197 =
0; _g_boolean_var_197; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1524, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1525
1526 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1527 selection = fm_directory_view_get_selection (view);
1528 if (g_list_length (selection) == 0) {
1529 if (view->details->directory_as_file != NULL((void*)0)) {
1530 GList *files;
1531
1532 files = g_list_append (NULL((void*)0), caja_file_ref (view->details->directory_as_file));
1533
1534 fm_properties_window_present (files, GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
1535
1536 caja_file_list_free (files);
1537 }
1538 } else {
1539 fm_properties_window_present (selection, GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
1540 }
1541 caja_file_list_free (selection);
1542}
1543
1544static void
1545action_location_properties_callback (GtkAction *action,
1546 gpointer callback_data)
1547{
1548 FMDirectoryView *view;
1549 GList *files;
1550
1551 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_198 = 1; else _g_boolean_var_198 =
0; _g_boolean_var_198; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1551, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
1552
1553 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1554 g_assert (CAJA_IS_FILE (view->details->location_popup_directory_as_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view->details->location_popup_directory_as_file));
GType __t = (caja_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_199 = 1; else _g_boolean_var_199
= 0; _g_boolean_var_199; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1554, ((const char*) (
__func__)), "CAJA_IS_FILE (view->details->location_popup_directory_as_file)"
); } while (0)
;
1555
1556 files = g_list_append (NULL((void*)0), caja_file_ref (view->details->location_popup_directory_as_file));
1557
1558 fm_properties_window_present (files, GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
1559
1560 caja_file_list_free (files);
1561}
1562
1563static gboolean
1564all_files_in_trash (GList *files)
1565{
1566 GList *node;
1567
1568 /* Result is ambiguous if called on NULL, so disallow. */
1569 g_return_val_if_fail (files != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if (files != ((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__)), "files != NULL");
return ((0)); } } while (0)
;
1570
1571 for (node = files; node != NULL((void*)0); node = node->next) {
1572 if (!caja_file_is_in_trash (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))))) {
1573 return FALSE(0);
1574 }
1575 }
1576
1577 return TRUE(!(0));
1578}
1579
1580static gboolean
1581all_selected_items_in_trash (FMDirectoryView *view)
1582{
1583 GList *selection;
1584 gboolean result;
1585
1586 /* If the contents share a parent directory, we need only
1587 * check that parent directory. Otherwise we have to inspect
1588 * each selected item.
1589 */
1590 selection = fm_directory_view_get_selection (view);
1591 result = (selection == NULL((void*)0)) ? FALSE(0) : all_files_in_trash (selection);
1592 caja_file_list_free (selection);
1593
1594 return result;
1595}
1596
1597static gboolean
1598we_are_in_vfolder_desktop_dir (FMDirectoryView *view)
1599{
1600 CajaFile *file;
1601 char *mime_type;
1602
1603 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_201
= 1; else _g_boolean_var_201 = 0; _g_boolean_var_201; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
1604
1605 if (view->details->model == NULL((void*)0)) {
1606 return FALSE(0);
1607 }
1608
1609 file = caja_directory_get_corresponding_file (view->details->model);
1610 mime_type = caja_file_get_mime_type (file);
1611 caja_file_unref (file);
1612
1613 if (mime_type != NULL((void*)0)
1614 && strcmp (mime_type, "x-directory/vfolder-desktop") == 0) {
1615 g_free (mime_type);
1616 return TRUE(!(0));
1617 } else {
1618 g_free (mime_type);
1619 return FALSE(0);
1620 }
1621}
1622
1623/* Preferences changed callbacks */
1624static void
1625text_attribute_names_changed_callback (gpointer callback_data)
1626{
1627 FMDirectoryView *view;
1628
1629 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1630
1631 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->text_attribute_names_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->text_attribute_names_changed) (view); } } while (0)
1632 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->text_attribute_names_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->text_attribute_names_changed) (view); } } while (0)
1633 text_attribute_names_changed, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->text_attribute_names_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->text_attribute_names_changed) (view); } } while (0)
;
1634}
1635
1636static void
1637image_display_policy_changed_callback (gpointer callback_data)
1638{
1639 FMDirectoryView *view;
1640
1641 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1642
1643 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->image_display_policy_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->image_display_policy_changed) (view); } } while (0)
1644 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->image_display_policy_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->image_display_policy_changed) (view); } } while (0)
1645 image_display_policy_changed, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->image_display_policy_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->image_display_policy_changed) (view); } } while (0)
;
1646}
1647
1648static void
1649click_policy_changed_callback (gpointer callback_data)
1650{
1651 FMDirectoryView *view;
1652
1653 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1654
1655 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->click_policy_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->click_policy_changed) (view); } } while (0)
1656 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->click_policy_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->click_policy_changed) (view); } } while (0)
1657 click_policy_changed, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->click_policy_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->click_policy_changed) (view); } } while (0)
;
1658}
1659
1660gboolean
1661fm_directory_view_should_sort_directories_first (FMDirectoryView *view)
1662{
1663 return view->details->sort_directories_first;
1664}
1665
1666static void
1667sort_directories_first_changed_callback (gpointer callback_data)
1668{
1669 FMDirectoryView *view;
1670 gboolean preference_value;
1671
1672 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1673
1674 preference_value =
1675 g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SORT_DIRECTORIES_FIRST"sort-directories-first");
1676
1677 if (preference_value != view->details->sort_directories_first) {
1678 view->details->sort_directories_first = preference_value;
1679 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->sort_directories_first_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->sort_directories_first_changed) (view); } } while (
0)
1680 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->sort_directories_first_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->sort_directories_first_changed) (view); } } while (
0)
1681 sort_directories_first_changed, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->sort_directories_first_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->sort_directories_first_changed) (view); } } while (
0)
;
1682 }
1683}
1684
1685static void set_up_scripts_directory_global(void)
1686{
1687 if (scripts_directory_uri != NULL((void*)0))
1688 {
1689 return;
1690 }
1691
1692 char* scripts_directory_path;
1693 scripts_directory_path = g_build_filename (g_get_user_config_dir (), "caja", "scripts", NULL((void*)0));
1694
1695 if (g_mkdir_with_parents(scripts_directory_path, 0755) == 0)
1696 {
1697 scripts_directory_uri = g_filename_to_uri(scripts_directory_path, NULL((void*)0), NULL((void*)0));
1698 scripts_directory_uri_length = strlen(scripts_directory_uri);
1699
1700 /* Support for GNOME Nautilus scripts
1701 */
1702 char* nautilus_scripts_path = g_build_filename(g_get_home_dir(), ".gnome2", "nautilus-scripts", NULL((void*)0));
1703
1704 if (g_file_test(nautilus_scripts_path, G_FILE_TEST_IS_DIR) == TRUE(!(0)))
1705 {
1706 char* nautilus_syslink = g_build_filename(g_get_user_config_dir(), "caja", "scripts", "nautilus", NULL((void*)0));
1707 /* If link already exists, or also any other kind of file/dir with same name, ignore it */
1708 if (g_file_test(nautilus_syslink, G_FILE_TEST_IS_SYMLINK) == FALSE(0) &&
1709 g_file_test(nautilus_syslink, G_FILE_TEST_EXISTS) == FALSE(0) &&
1710 g_file_test(nautilus_syslink, G_FILE_TEST_IS_DIR) == FALSE(0))
1711 {
1712 /* Check if we need to create a link */
1713 GDir* dir = g_dir_open(nautilus_scripts_path, 0, NULL((void*)0));
1714
1715 if (dir)
1716 {
1717 /* If directory contains files, we can create the link */
1718 int count = 0;
1719
1720 while (g_dir_read_name(dir) != NULL((void*)0))
1721 {
1722 count++;
1723 }
1724
1725 if (count > 0)
1726 {
1727 /* Create link to nautilus folder */
1728 int res = symlink (nautilus_scripts_path, nautilus_syslink);
1729 if (res != 0)
1730 g_warning ("Can't create symlink to nautilus scripts folder");
1731 }
1732
1733 g_dir_close(dir);
1734 }
1735 }
1736
1737 g_free(nautilus_syslink);
1738 }
1739
1740 g_free(nautilus_scripts_path);
1741 }
1742
1743 g_free(scripts_directory_path);
1744}
1745
1746static void
1747scripts_added_or_changed_callback (CajaDirectory *directory,
1748 GList *files,
1749 gpointer callback_data)
1750{
1751 FMDirectoryView *view;
1752
1753 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1754
1755 view->details->scripts_invalid = TRUE(!(0));
1756 if (view->details->active) {
1757 schedule_update_menus (view);
1758 }
1759}
1760
1761static void
1762templates_added_or_changed_callback (CajaDirectory *directory,
1763 GList *files,
1764 gpointer callback_data)
1765{
1766 FMDirectoryView *view;
1767
1768 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
1769
1770 view->details->templates_invalid = TRUE(!(0));
1771 if (view->details->active) {
1772 schedule_update_menus (view);
1773 }
1774}
1775
1776static void
1777add_directory_to_directory_list (FMDirectoryView *view,
1778 CajaDirectory *directory,
1779 GList **directory_list,
1780 GCallback changed_callback)
1781{
1782 CajaFileAttributes attributes;
1783
1784 if (g_list_find (*directory_list, directory) == NULL((void*)0)) {
1785 caja_directory_ref (directory);
1786
1787 attributes =
1788 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
|
1789 CAJA_FILE_ATTRIBUTE_INFO |
1790 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT;
1791
1792 caja_directory_file_monitor_add (directory, directory_list,
1793 FALSE(0), attributes,
1794 (CajaDirectoryCallback)changed_callback, view);
1795
1796 g_signal_connect_object (directory, "files_added",
1797 G_CALLBACK (changed_callback)((GCallback) (changed_callback)), view, 0);
1798 g_signal_connect_object (directory, "files_changed",
1799 G_CALLBACK (changed_callback)((GCallback) (changed_callback)), view, 0);
1800
1801 *directory_list = g_list_append (*directory_list, directory);
1802 }
1803}
1804
1805static void
1806remove_directory_from_directory_list (FMDirectoryView *view,
1807 CajaDirectory *directory,
1808 GList **directory_list,
1809 GCallback changed_callback)
1810{
1811 *directory_list = g_list_remove (*directory_list, directory);
1812
1813 g_signal_handlers_disconnect_by_func (directory,g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (changed_callback))), (view))
1814 G_CALLBACK (changed_callback),g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (changed_callback))), (view))
1815 view)g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (changed_callback))), (view))
;
1816
1817 caja_directory_file_monitor_remove (directory, directory_list);
1818
1819 caja_directory_unref (directory);
1820}
1821
1822
1823static void
1824add_directory_to_scripts_directory_list (FMDirectoryView *view,
1825 CajaDirectory *directory)
1826{
1827 add_directory_to_directory_list (view, directory,
1828 &view->details->scripts_directory_list,
1829 G_CALLBACK (scripts_added_or_changed_callback)((GCallback) (scripts_added_or_changed_callback)));
1830}
1831
1832static void
1833remove_directory_from_scripts_directory_list (FMDirectoryView *view,
1834 CajaDirectory *directory)
1835{
1836 remove_directory_from_directory_list (view, directory,
1837 &view->details->scripts_directory_list,
1838 G_CALLBACK (scripts_added_or_changed_callback)((GCallback) (scripts_added_or_changed_callback)));
1839}
1840
1841static void
1842add_directory_to_templates_directory_list (FMDirectoryView *view,
1843 CajaDirectory *directory)
1844{
1845 add_directory_to_directory_list (view, directory,
1846 &view->details->templates_directory_list,
1847 G_CALLBACK (templates_added_or_changed_callback)((GCallback) (templates_added_or_changed_callback)));
1848}
1849
1850static void
1851remove_directory_from_templates_directory_list (FMDirectoryView *view,
1852 CajaDirectory *directory)
1853{
1854 remove_directory_from_directory_list (view, directory,
1855 &view->details->templates_directory_list,
1856 G_CALLBACK (templates_added_or_changed_callback)((GCallback) (templates_added_or_changed_callback)));
1857}
1858
1859static void
1860slot_active (CajaWindowSlot *slot,
1861 FMDirectoryView *view)
1862{
1863 g_assert (!view->details->active)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (!view->details->active) _g_boolean_var_202 = 1; else
_g_boolean_var_202 = 0; _g_boolean_var_202; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 1863, ((const char*) (
__func__)), "!view->details->active"); } while (0)
;
1864 view->details->active = TRUE(!(0));
1865
1866 fm_directory_view_merge_menus (view);
1867 schedule_update_menus (view);
1868}
1869
1870static void
1871slot_inactive (CajaWindowSlot *slot,
1872 FMDirectoryView *view)
1873{
1874 g_assert (view->details->active ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if (view->details->active || gtk_widget_get_parent ((
(((GtkWidget*) (void *) ((view)))))) == ((void*)0)) _g_boolean_var_203
= 1; else _g_boolean_var_203 = 0; _g_boolean_var_203; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 1875, ((const char*) (__func__)), "view->details->active || gtk_widget_get_parent (GTK_WIDGET (view)) == NULL"
); } while (0)
1875 gtk_widget_get_parent (GTK_WIDGET (view)) == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if (view->details->active || gtk_widget_get_parent ((
(((GtkWidget*) (void *) ((view)))))) == ((void*)0)) _g_boolean_var_203
= 1; else _g_boolean_var_203 = 0; _g_boolean_var_203; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 1875, ((const char*) (__func__)), "view->details->active || gtk_widget_get_parent (GTK_WIDGET (view)) == NULL"
); } while (0)
;
1876 view->details->active = FALSE(0);
1877
1878 fm_directory_view_unmerge_menus (view);
1879 remove_update_menus_timeout_callback (view);
1880}
1881
1882static void
1883fm_directory_view_grab_focus (CajaView *view)
1884{
1885 /* focus the child of the scrolled window if it exists */
1886 GtkWidget *child;
1887 child = gtk_bin_get_child (GTK_BIN (view)((((GtkBin*) (void *) ((view))))));
1888 if (child) {
1889 gtk_widget_grab_focus (GTK_WIDGET (child)((((GtkWidget*) (void *) ((child))))));
1890 }
1891}
1892
1893static void
1894view_iface_update_menus (CajaView *view)
1895{
1896 fm_directory_view_update_menus (FM_DIRECTORY_VIEW (view)((((FMDirectoryView*) (void *) ((view))))));
1897}
1898
1899static GtkWidget *
1900fm_directory_view_get_widget (CajaView *view)
1901{
1902 return GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))));
1903}
1904
1905static int
1906fm_directory_view_get_selection_count (CajaView *view)
1907{
1908 /* FIXME: This could be faster if we special cased it in subclasses */
1909 GList *files;
1910 int len;
1911
1912 files = fm_directory_view_get_selection (FM_DIRECTORY_VIEW (view)((((FMDirectoryView*) (void *) ((view))))));
1913 len = g_list_length (files);
1914 caja_file_list_free (files);
1915
1916 return len;
1917}
1918
1919static GList *
1920fm_directory_view_get_selection_locations (CajaView *view)
1921{
1922 GList *files;
1923 GList *locations;
1924 GList *l;
1925 GFile *location = NULL((void*)0);
1926
1927 files = fm_directory_view_get_selection (FM_DIRECTORY_VIEW (view)((((FMDirectoryView*) (void *) ((view))))));
1928 locations = NULL((void*)0);
1929 for (l = files; l != NULL((void*)0); l = l->next) {
1930 location = caja_file_get_location (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))));
1931 locations = g_list_prepend (locations, location);
1932 }
1933 caja_file_list_free (files);
1934
1935 return g_list_reverse (locations);
1936}
1937
1938static GList *
1939file_list_from_location_list (const GList *uri_list)
1940{
1941 GList *file_list;
1942 const GList *node;
1943
1944 file_list = NULL((void*)0);
1945 for (node = uri_list; node != NULL((void*)0); node = node->next) {
1946 file_list = g_list_prepend
1947 (file_list,
1948 caja_file_get (node->data));
1949 }
1950 return g_list_reverse (file_list);
1951}
1952
1953static void
1954fm_directory_view_set_selection_locations (CajaView *caja_view,
1955 GList *selection_locations)
1956{
1957 FMDirectoryView *view;
1958
1959 view = FM_DIRECTORY_VIEW (caja_view)((((FMDirectoryView*) (void *) ((caja_view)))));
1960
1961 if (!view->details->loading) {
1962 GList *selection;
1963
1964 /* If we aren't still loading, set the selection right now,
1965 * and reveal the new selection.
1966 */
1967 selection = file_list_from_location_list (selection_locations);
1968 view->details->selection_change_is_due_to_shell = TRUE(!(0));
1969 fm_directory_view_set_selection (view, selection);
1970 view->details->selection_change_is_due_to_shell = FALSE(0);
1971 fm_directory_view_reveal_selection (view);
1972 caja_file_list_free (selection);
1973 } else {
1974 /* If we are still loading, set the list of pending URIs instead.
1975 * done_loading() will eventually select the pending URIs and reveal them.
1976 */
1977 g_list_free_full (view->details->pending_locations_selected, g_object_unref);
1978 view->details->pending_locations_selected =
1979 g_list_copy_deep (selection_locations, (GCopyFunc) g_object_ref, NULL((void*)0));
1980 }
1981}
1982
1983
1984void
1985fm_directory_view_init_view_iface (CajaViewIface *iface)
1986{
1987 iface->grab_focus = fm_directory_view_grab_focus;
1988 iface->update_menus = view_iface_update_menus;
1989
1990 iface->get_widget = fm_directory_view_get_widget;
1991 iface->load_location = fm_directory_view_load_location;
1992 iface->stop_loading = fm_directory_view_stop_loading;
1993
1994 iface->get_selection_count = fm_directory_view_get_selection_count;
1995 iface->get_selection = fm_directory_view_get_selection_locations;
1996 iface->set_selection = fm_directory_view_set_selection_locations;
1997 iface->set_is_active = (gpointer)fm_directory_view_set_is_active;
1998
1999 iface->supports_zooming = (gpointer)fm_directory_view_supports_zooming;
2000 iface->bump_zoom_level = (gpointer)fm_directory_view_bump_zoom_level;
2001 iface->zoom_to_level = (gpointer)fm_directory_view_zoom_to_level;
2002 iface->restore_default_zoom_level = (gpointer)fm_directory_view_restore_default_zoom_level;
2003 iface->can_zoom_in = (gpointer)fm_directory_view_can_zoom_in;
2004 iface->can_zoom_out = (gpointer)fm_directory_view_can_zoom_out;
2005 iface->get_zoom_level = (gpointer)fm_directory_view_get_zoom_level;
2006
2007 iface->pop_up_location_context_menu = (gpointer)fm_directory_view_pop_up_location_context_menu;
2008 iface->drop_proxy_received_uris = (gpointer)fm_directory_view_drop_proxy_received_uris;
2009 iface->drop_proxy_received_netscape_url = (gpointer)fm_directory_view_drop_proxy_received_netscape_url;
2010}
2011
2012static void
2013fm_directory_view_init (FMDirectoryView *view)
2014{
2015 CajaDirectory *scripts_directory;
2016
2017 view->details = g_new0 (FMDirectoryViewDetails, 1)(FMDirectoryViewDetails *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (FMDirectoryViewDetails); 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; }))
;
2018
2019 /* Default to true; desktop-icon-view sets to false */
2020 view->details->show_foreign_files = TRUE(!(0));
2021
2022 view->details->non_ready_files =
2023 g_hash_table_new_full (file_and_directory_hash,
2024 file_and_directory_equal,
2025 (GDestroyNotify)file_and_directory_free,
2026 NULL((void*)0));
2027
2028 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view)((((GtkScrolledWindow*) (void *) ((view))))),
2029 GTK_POLICY_AUTOMATIC,
2030 GTK_POLICY_AUTOMATIC);
2031 gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (view)((((GtkScrolledWindow*) (void *) ((view))))), NULL((void*)0));
2032 gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (view)((((GtkScrolledWindow*) (void *) ((view))))), NULL((void*)0));
2033 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view)((((GtkScrolledWindow*) (void *) ((view))))), GTK_SHADOW_ETCHED_IN);
2034 gtk_scrolled_window_set_overlay_scrolling (GTK_SCROLLED_WINDOW (view)((((GtkScrolledWindow*) (void *) ((view))))), FALSE(0));
2035
2036 set_up_scripts_directory_global ();
2037 scripts_directory = caja_directory_get_by_uri (scripts_directory_uri);
2038 add_directory_to_scripts_directory_list (view, scripts_directory);
2039 caja_directory_unref (scripts_directory);
2040
2041 if (caja_should_use_templates_directory ()) {
2042 CajaDirectory *templates_directory;
2043 char *templates_uri;
2044
2045 templates_uri = caja_get_templates_directory_uri ();
2046 templates_directory = caja_directory_get_by_uri (templates_uri);
2047 g_free (templates_uri);
2048 add_directory_to_templates_directory_list (view, templates_directory);
2049 caja_directory_unref (templates_directory);
2050 }
2051 update_templates_directory (view);
2052 g_signal_connect_object (caja_signaller_get_current (),
2053 "user_dirs_changed",
2054 G_CALLBACK (user_dirs_changed)((GCallback) (user_dirs_changed)),
2055 view, G_CONNECT_SWAPPED);
2056
2057 view->details->sort_directories_first =
2058 g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SORT_DIRECTORIES_FIRST"sort-directories-first");
2059
2060 g_signal_connect_object (caja_trash_monitor_get (), "trash_state_changed",
2061 G_CALLBACK (fm_directory_view_trash_state_changed_callback)((GCallback) (fm_directory_view_trash_state_changed_callback)
)
, view, 0);
2062
2063 /* React to clipboard changes */
2064 g_signal_connect_object (caja_clipboard_monitor_get (), "clipboard_changed",
2065 G_CALLBACK (clipboard_changed_callback)((GCallback) (clipboard_changed_callback)), view, 0);
2066
2067 /* Register to menu provider extension signal managing menu updates */
2068 g_signal_connect_object (caja_signaller_get_current (), "popup_menu_changed",
2069 G_CALLBACK (fm_directory_view_update_menus)((GCallback) (fm_directory_view_update_menus)), view, G_CONNECT_SWAPPED);
2070
2071 gtk_widget_show (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
2072
2073 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "enable-delete"
), (((GCallback) (schedule_update_menus_callback))), (view), (
(void*)0), G_CONNECT_SWAPPED)
2074 "changed::" CAJA_PREFERENCES_ENABLE_DELETE,g_signal_connect_data ((caja_preferences), ("changed::" "enable-delete"
), (((GCallback) (schedule_update_menus_callback))), (view), (
(void*)0), G_CONNECT_SWAPPED)
2075 G_CALLBACK (schedule_update_menus_callback), view)g_signal_connect_data ((caja_preferences), ("changed::" "enable-delete"
), (((GCallback) (schedule_update_menus_callback))), (view), (
(void*)0), G_CONNECT_SWAPPED)
;
2076 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"captions"), (((GCallback) (text_attribute_names_changed_callback
))), (view), ((void*)0), G_CONNECT_SWAPPED)
2077 "changed::" CAJA_PREFERENCES_ICON_VIEW_CAPTIONS,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"captions"), (((GCallback) (text_attribute_names_changed_callback
))), (view), ((void*)0), G_CONNECT_SWAPPED)
2078 G_CALLBACK(text_attribute_names_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"captions"), (((GCallback) (text_attribute_names_changed_callback
))), (view), ((void*)0), G_CONNECT_SWAPPED)
2079 view)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"captions"), (((GCallback) (text_attribute_names_changed_callback
))), (view), ((void*)0), G_CONNECT_SWAPPED)
;
2080 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (image_display_policy_changed_callback))), (
view), ((void*)0), G_CONNECT_SWAPPED)
2081 "changed::" CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (image_display_policy_changed_callback))), (
view), ((void*)0), G_CONNECT_SWAPPED)
2082 G_CALLBACK (image_display_policy_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (image_display_policy_changed_callback))), (
view), ((void*)0), G_CONNECT_SWAPPED)
2083 view)g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (image_display_policy_changed_callback))), (
view), ((void*)0), G_CONNECT_SWAPPED)
;
2084 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "click-policy"
), (((GCallback) (click_policy_changed_callback))), (view), (
(void*)0), G_CONNECT_SWAPPED)
2085 "changed::" CAJA_PREFERENCES_CLICK_POLICY,g_signal_connect_data ((caja_preferences), ("changed::" "click-policy"
), (((GCallback) (click_policy_changed_callback))), (view), (
(void*)0), G_CONNECT_SWAPPED)
2086 G_CALLBACK(click_policy_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "click-policy"
), (((GCallback) (click_policy_changed_callback))), (view), (
(void*)0), G_CONNECT_SWAPPED)
2087 view)g_signal_connect_data ((caja_preferences), ("changed::" "click-policy"
), (((GCallback) (click_policy_changed_callback))), (view), (
(void*)0), G_CONNECT_SWAPPED)
;
2088 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "sort-directories-first"
), (((GCallback) (sort_directories_first_changed_callback))),
(view), ((void*)0), G_CONNECT_SWAPPED)
2089 "changed::" CAJA_PREFERENCES_SORT_DIRECTORIES_FIRST,g_signal_connect_data ((caja_preferences), ("changed::" "sort-directories-first"
), (((GCallback) (sort_directories_first_changed_callback))),
(view), ((void*)0), G_CONNECT_SWAPPED)
2090 G_CALLBACK(sort_directories_first_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "sort-directories-first"
), (((GCallback) (sort_directories_first_changed_callback))),
(view), ((void*)0), G_CONNECT_SWAPPED)
2091 view)g_signal_connect_data ((caja_preferences), ("changed::" "sort-directories-first"
), (((GCallback) (sort_directories_first_changed_callback))),
(view), ((void*)0), G_CONNECT_SWAPPED)
;
2092 g_signal_connect_swapped (mate_lockdown_preferences,g_signal_connect_data ((mate_lockdown_preferences), ("changed::"
"disable-command-line"), (((GCallback) (schedule_update_menus
))), (view), ((void*)0), G_CONNECT_SWAPPED)
2093 "changed::" CAJA_PREFERENCES_LOCKDOWN_COMMAND_LINE,g_signal_connect_data ((mate_lockdown_preferences), ("changed::"
"disable-command-line"), (((GCallback) (schedule_update_menus
))), (view), ((void*)0), G_CONNECT_SWAPPED)
2094 G_CALLBACK (schedule_update_menus), view)g_signal_connect_data ((mate_lockdown_preferences), ("changed::"
"disable-command-line"), (((GCallback) (schedule_update_menus
))), (view), ((void*)0), G_CONNECT_SWAPPED)
;
2095
2096 /* Update undo actions stuff and connect signals from the undostack manager */
2097 view->details->undo_active = FALSE(0);
2098 view->details->redo_active = FALSE(0);
2099 view->details->undo_action_description = NULL((void*)0);
2100 view->details->undo_action_label = NULL((void*)0);
2101 view->details->redo_action_description = NULL((void*)0);
2102 view->details->redo_action_label = NULL((void*)0);
2103
2104 CajaUndoStackManager* manager = caja_undostack_manager_instance ();
2105
2106 g_signal_connect_object (G_OBJECT(manager)((((GObject*) (void *) ((manager))))), "request-menu-update",
2107 G_CALLBACK(undo_redo_menu_update_callback)((GCallback) (undo_redo_menu_update_callback)), view, 0);
2108
2109 caja_undostack_manager_request_menu_update (caja_undostack_manager_instance());
2110}
2111
2112static void
2113real_unmerge_menus (FMDirectoryView *view)
2114{
2115 GtkUIManager *ui_manager;
2116
2117 if (view->details->window == NULL((void*)0)) {
2118 return;
2119 }
2120
2121 ui_manager = caja_window_info_get_ui_manager (view->details->window);
2122
2123 caja_ui_unmerge_ui (ui_manager,
2124 &view->details->dir_merge_id,
2125 &view->details->dir_action_group);
2126 caja_ui_unmerge_ui (ui_manager,
2127 &view->details->extensions_menu_merge_id,
2128 &view->details->extensions_menu_action_group);
2129 caja_ui_unmerge_ui (ui_manager,
2130 &view->details->open_with_merge_id,
2131 &view->details->open_with_action_group);
2132 caja_ui_unmerge_ui (ui_manager,
2133 &view->details->scripts_merge_id,
2134 &view->details->scripts_action_group);
2135 caja_ui_unmerge_ui (ui_manager,
2136 &view->details->templates_merge_id,
2137 &view->details->templates_action_group);
2138}
2139
2140static void
2141fm_directory_view_destroy (GtkWidget *object)
2142{
2143 FMDirectoryView *view;
2144 GList *node, *next;
2145
2146 view = FM_DIRECTORY_VIEW (object)((((FMDirectoryView*) (void *) ((object)))));
2147
2148 disconnect_model_handlers (view);
2149
2150 fm_directory_view_unmerge_menus (view);
2151
2152 /* We don't own the window, so no unref */
2153 view->details->slot = NULL((void*)0);
2154 view->details->window = NULL((void*)0);
2155
2156 fm_directory_view_stop (view);
2157 fm_directory_view_clear (view);
2158
2159 for (node = view->details->scripts_directory_list; node != NULL((void*)0); node = next) {
2160 next = node->next;
2161 remove_directory_from_scripts_directory_list (view, node->data);
2162 }
2163
2164 for (node = view->details->templates_directory_list; node != NULL((void*)0); node = next) {
2165 next = node->next;
2166 remove_directory_from_templates_directory_list (view, node->data);
2167 }
2168
2169 while (view->details->subdirectory_list != NULL((void*)0)) {
2170 fm_directory_view_remove_subdirectory (view,
2171 view->details->subdirectory_list->data);
2172 }
2173
2174 remove_update_menus_timeout_callback (view);
2175 remove_update_status_idle_callback (view);
2176
2177 if (view->details->display_selection_idle_id != 0) {
2178 g_source_remove (view->details->display_selection_idle_id);
2179 view->details->display_selection_idle_id = 0;
2180 }
2181
2182 if (view->details->reveal_selection_idle_id != 0) {
2183 g_source_remove (view->details->reveal_selection_idle_id);
2184 view->details->reveal_selection_idle_id = 0;
2185 }
2186
2187 if (view->details->delayed_rename_file_id != 0) {
2188 g_source_remove (view->details->delayed_rename_file_id);
2189 view->details->delayed_rename_file_id = 0;
2190 }
2191
2192 if (view->details->model) {
2193 caja_directory_unref (view->details->model);
2194 view->details->model = NULL((void*)0);
2195 }
2196
2197 if (view->details->directory_as_file) {
2198 caja_file_unref (view->details->directory_as_file);
2199 view->details->directory_as_file = NULL((void*)0);
2200 }
2201
2202 EEL_CALL_PARENT (GTK_WIDGET_CLASS, destroy, (object))do { if (((((GtkWidgetClass*) (void *) ((parent_class)))))->
destroy != ((void*)0)) { (* ((((GtkWidgetClass*) (void *) ((parent_class
)))))->destroy) (object); } } while (0)
;
2203}
2204
2205static void
2206fm_directory_view_finalize (GObject *object)
2207{
2208 FMDirectoryView *view;
2209
2210 view = FM_DIRECTORY_VIEW (object)((((FMDirectoryView*) (void *) ((object)))));
2211
2212 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (schedule_update_menus_callback), (view))
2213 schedule_update_menus_callback, view)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (schedule_update_menus_callback), (view))
;
2214 g_signal_handlers_disconnect_by_func (caja_icon_view_preferences,g_signal_handlers_disconnect_matched ((caja_icon_view_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_attribute_names_changed_callback),
(view))
2215 text_attribute_names_changed_callback, view)g_signal_handlers_disconnect_matched ((caja_icon_view_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_attribute_names_changed_callback),
(view))
;
2216 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (image_display_policy_changed_callback), (view))
2217 image_display_policy_changed_callback, view)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (image_display_policy_changed_callback), (view))
;
2218 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (click_policy_changed_callback), (view))
2219 click_policy_changed_callback, view)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (click_policy_changed_callback), (view))
;
2220 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (sort_directories_first_changed_callback), (view))
2221 sort_directories_first_changed_callback, view)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (sort_directories_first_changed_callback), (view))
;
2222 g_signal_handlers_disconnect_by_func (mate_lockdown_preferences,g_signal_handlers_disconnect_matched ((mate_lockdown_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (schedule_update_menus), (view))
2223 schedule_update_menus, view)g_signal_handlers_disconnect_matched ((mate_lockdown_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (schedule_update_menus), (view))
;
2224
2225 unschedule_pop_up_location_context_menu (view);
2226 if (view->details->location_popup_event != NULL((void*)0)) {
2227 gdk_event_free ((GdkEvent *) view->details->location_popup_event);
2228 }
2229
2230 g_hash_table_destroy (view->details->non_ready_files);
2231
2232 g_free (view->details);
2233
2234 EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object))do { if (((((GObjectClass*) (void *) ((parent_class)))))->
finalize != ((void*)0)) { (* ((((GObjectClass*) (void *) ((parent_class
)))))->finalize) (object); } } while (0)
;
2235}
2236
2237/**
2238 * fm_directory_view_display_selection_info:
2239 *
2240 * Display information about the current selection, and notify the view frame of the changed selection.
2241 * @view: FMDirectoryView for which to display selection info.
2242 *
2243 **/
2244void
2245fm_directory_view_display_selection_info (FMDirectoryView *view)
2246{
2247 GList *selection;
2248 goffset non_folder_size;
2249 gboolean non_folder_size_known;
2250 guint non_folder_count, folder_count, folder_item_count;
2251 gboolean folder_item_count_known;
2252 guint file_item_count;
2253 GList *p;
2254 char *first_item_name;
2255 char *non_folder_str;
2256 char *folder_count_str;
2257 char *folder_item_count_str;
2258 char *status_string;
2259 char *free_space_str;
2260 char *obj_selected_free_space_str;
2261 CajaFile *file = NULL((void*)0);
2262
2263 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_204
= 1; else _g_boolean_var_204 = 0; _g_boolean_var_204; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
2264
2265 selection = fm_directory_view_get_selection (view);
2266
2267 folder_item_count_known = TRUE(!(0));
2268 folder_count = 0;
2269 folder_item_count = 0;
2270 non_folder_count = 0;
2271 non_folder_size_known = FALSE(0);
2272 non_folder_size = 0;
2273 first_item_name = NULL((void*)0);
2274 folder_count_str = NULL((void*)0);
2275 non_folder_str = NULL((void*)0);
2276 folder_item_count_str = NULL((void*)0);
2277 free_space_str = NULL((void*)0);
2278 obj_selected_free_space_str = NULL((void*)0);
2279
2280 for (p = selection; p != NULL((void*)0); p = p->next) {
2281 file = p->data;
2282 if (caja_file_is_directory (file)) {
2283 folder_count++;
2284 if (caja_file_get_directory_item_count (file, &file_item_count, NULL((void*)0))) {
2285 folder_item_count += file_item_count;
2286 } else {
2287 folder_item_count_known = FALSE(0);
2288 }
2289 } else {
2290 non_folder_count++;
2291 if (!caja_file_can_get_size (file)) {
2292 non_folder_size_known = TRUE(!(0));
2293 non_folder_size += caja_file_get_size (file);
2294 }
2295 }
2296
2297 if (first_item_name == NULL((void*)0)) {
2298 first_item_name = caja_file_get_display_name (file);
2299 }
2300 }
2301
2302 caja_file_list_free (selection);
2303
2304 /* Break out cases for localization's sake. But note that there are still pieces
2305 * being assembled in a particular order, which may be a problem for some localizers.
2306 */
2307
2308 if (folder_count != 0) {
2309 if (folder_count == 1 && non_folder_count == 0) {
2310 folder_count_str = g_strdup_printf (_("\"%s\" selected")dcgettext (((void*)0), "\"%s\" selected", 5), first_item_name);
2311 } else {
2312 folder_count_str = g_strdup_printf (ngettext("%'d folder selected",dcngettext (((void*)0), "%'d folder selected", "%'d folders selected"
, folder_count, 5)
2313 "%'d folders selected",dcngettext (((void*)0), "%'d folder selected", "%'d folders selected"
, folder_count, 5)
2314 folder_count)dcngettext (((void*)0), "%'d folder selected", "%'d folders selected"
, folder_count, 5)
,
2315 folder_count);
2316 }
2317
2318 if (folder_count == 1) {
2319 if (!folder_item_count_known) {
2320 folder_item_count_str = g_strdup ("")g_strdup_inline ("");
2321 } else {
2322 folder_item_count_str = g_strdup_printf (ngettext(" (containing %'d item)",dcngettext (((void*)0), " (containing %'d item)", " (containing %'d items)"
, folder_item_count, 5)
2323 " (containing %'d items)",dcngettext (((void*)0), " (containing %'d item)", " (containing %'d items)"
, folder_item_count, 5)
2324 folder_item_count)dcngettext (((void*)0), " (containing %'d item)", " (containing %'d items)"
, folder_item_count, 5)
,
2325 folder_item_count);
2326 }
2327 }
2328 else {
2329 if (!folder_item_count_known) {
2330 folder_item_count_str = g_strdup ("")g_strdup_inline ("");
2331 } else {
2332 /* Translators: this is preceded with a string of form 'N folders' (N more than 1) */
2333 folder_item_count_str = g_strdup_printf (ngettext(" (containing a total of %'d item)",dcngettext (((void*)0), " (containing a total of %'d item)", " (containing a total of %'d items)"
, folder_item_count, 5)
2334 " (containing a total of %'d items)",dcngettext (((void*)0), " (containing a total of %'d item)", " (containing a total of %'d items)"
, folder_item_count, 5)
2335 folder_item_count)dcngettext (((void*)0), " (containing a total of %'d item)", " (containing a total of %'d items)"
, folder_item_count, 5)
,
2336 folder_item_count);
2337 }
2338
2339 }
2340 }
2341
2342 if (non_folder_count != 0) {
2343 char *items_string;
2344
2345 if (folder_count == 0) {
2346 if (non_folder_count == 1) {
2347 items_string = g_strdup_printf (_("\"%s\" selected")dcgettext (((void*)0), "\"%s\" selected", 5),
2348 first_item_name);
2349 } else {
2350 items_string = g_strdup_printf (ngettext("%'d item selected",dcngettext (((void*)0), "%'d item selected", "%'d items selected"
, non_folder_count, 5)
2351 "%'d items selected",dcngettext (((void*)0), "%'d item selected", "%'d items selected"
, non_folder_count, 5)
2352 non_folder_count)dcngettext (((void*)0), "%'d item selected", "%'d items selected"
, non_folder_count, 5)
,
2353 non_folder_count);
2354 }
2355 } else {
2356 /* Folders selected also, use "other" terminology */
2357 items_string = g_strdup_printf (ngettext("%'d other item selected",dcngettext (((void*)0), "%'d other item selected", "%'d other items selected"
, non_folder_count, 5)
2358 "%'d other items selected",dcngettext (((void*)0), "%'d other item selected", "%'d other items selected"
, non_folder_count, 5)
2359 non_folder_count)dcngettext (((void*)0), "%'d other item selected", "%'d other items selected"
, non_folder_count, 5)
,
2360 non_folder_count);
2361 }
2362
2363 if (non_folder_size_known) {
2364 char *size_string;
2365
2366 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
2367 size_string = g_format_size_full (non_folder_size, G_FORMAT_SIZE_IEC_UNITS);
2368 else
2369 size_string = g_format_size(non_folder_size);
2370
2371 /* Translators: This is marked for translation in case a localiser
2372 * needs to use something other than parentheses. The
2373 * first message gives the number of items selected;
2374 * the message in parentheses the size of those items.
2375 */
2376 non_folder_str = g_strdup_printf (_("%s (%s)")dcgettext (((void*)0), "%s (%s)", 5),
2377 items_string,
2378 size_string);
2379
2380 g_free (size_string);
2381 g_free (items_string);
2382 } else {
2383 non_folder_str = items_string;
2384 }
2385 }
2386
2387 free_space_str = caja_file_get_volume_free_space (view->details->directory_as_file);
2388 if (free_space_str != NULL((void*)0)) {
2389 obj_selected_free_space_str = g_strdup_printf (_("Free space: %s")dcgettext (((void*)0), "Free space: %s", 5), free_space_str);
2390 }
2391 if (folder_count == 0 && non_folder_count == 0) {
2392 char *item_count_str;
2393 guint item_count;
2394
2395 item_count = fm_directory_view_get_item_count (view);
2396
2397 item_count_str = g_strdup_printf (ngettext ("%'u item", "%'u items", item_count)dcngettext (((void*)0), "%'u item", "%'u items", item_count, 5
)
, item_count);
2398
2399 if (free_space_str != NULL((void*)0)) {
2400 status_string = g_strdup_printf (_("%s, Free space: %s")dcgettext (((void*)0), "%s, Free space: %s", 5), item_count_str, free_space_str);
2401 g_free (item_count_str);
2402 } else {
2403 status_string = item_count_str;
2404 }
2405
2406 } else if (folder_count == 0) {
2407 if (free_space_str == NULL((void*)0)) {
2408 status_string = g_strdup (non_folder_str)g_strdup_inline (non_folder_str);
2409 } else {
2410 /* Marking this for translation, since you
2411 * might want to change "," to something else.
2412 * After the comma the amount of free space will
2413 * be shown.
2414 */
2415 status_string = g_strdup_printf (_("%s, %s")dcgettext (((void*)0), "%s, %s", 5),
2416 non_folder_str,
2417 obj_selected_free_space_str);
2418 }
2419 } else if (non_folder_count == 0) {
2420 if (free_space_str == NULL((void*)0)) {
2421 /* No use marking this for translation, since you
2422 * can't reorder the strings, which is the main thing
2423 * you'd want to do.
2424 */
2425 status_string = g_strdup_printf ("%s%s",
2426 folder_count_str,
2427 folder_item_count_str);
2428 } else {
2429 /* Marking this for translation, since you
2430 * might want to change "," to something else.
2431 * After the comma the amount of free space will
2432 * be shown.
2433 */
2434 status_string = g_strdup_printf (_("%s%s, %s")dcgettext (((void*)0), "%s%s, %s", 5),
2435 folder_count_str,
2436 folder_item_count_str,
2437 obj_selected_free_space_str);
2438 }
2439 } else {
2440 if (obj_selected_free_space_str == NULL((void*)0)) {
2441 /* This is marked for translation in case a localizer
2442 * needs to change ", " to something else. The comma
2443 * is between the message about the number of folders
2444 * and the number of items in those folders and the
2445 * message about the number of other items and the
2446 * total size of those items.
2447 */
2448 status_string = g_strdup_printf (_("%s%s, %s")dcgettext (((void*)0), "%s%s, %s", 5),
2449 folder_count_str,
2450 folder_item_count_str,
2451 non_folder_str);
2452 } else {
2453 /* This is marked for translation in case a localizer
2454 * needs to change ", " to something else. The first comma
2455 * is between the message about the number of folders
2456 * and the number of items in those folders and the
2457 * message about the number of other items and the
2458 * total size of those items. After the second comma
2459 * the free space is written.
2460 */
2461 status_string = g_strdup_printf (_("%s%s, %s, %s")dcgettext (((void*)0), "%s%s, %s, %s", 5),
2462 folder_count_str,
2463 folder_item_count_str,
2464 non_folder_str,
2465 obj_selected_free_space_str);
2466 }
2467 }
2468
2469 g_free (free_space_str);
2470 g_free (obj_selected_free_space_str);
2471 g_free (first_item_name);
2472 g_free (folder_count_str);
2473 g_free (folder_item_count_str);
2474 g_free (non_folder_str);
2475
2476 caja_window_slot_info_set_status (view->details->slot,
2477 status_string);
2478 g_free (status_string);
2479}
2480
2481void
2482fm_directory_view_send_selection_change (FMDirectoryView *view)
2483{
2484 caja_window_info_report_selection_changed (view->details->window);
2485
2486 view->details->send_selection_change_to_shell = FALSE(0);
2487}
2488
2489gboolean
2490fm_directory_view_get_allow_moves (FMDirectoryView *view)
2491{
2492 return view->details->allow_moves;
2493}
2494
2495static void
2496fm_directory_view_load_location (CajaView *caja_view,
2497 const char *location)
2498{
2499 CajaDirectory *directory;
2500 FMDirectoryView *directory_view;
2501
2502 directory_view = FM_DIRECTORY_VIEW (caja_view)((((FMDirectoryView*) (void *) ((caja_view)))));
2503
2504 if (eel_uri_is_search (location)) {
2505 directory_view->details->allow_moves = FALSE(0);
2506 } else {
2507 directory_view->details->allow_moves = TRUE(!(0));
2508 }
2509
2510 directory = caja_directory_get_by_uri (location);
2511 load_directory (directory_view, directory);
2512 caja_directory_unref (directory);
2513}
2514
2515static void
2516fm_directory_view_stop_loading (CajaView *caja_view)
2517{
2518 fm_directory_view_stop (FM_DIRECTORY_VIEW (caja_view)((((FMDirectoryView*) (void *) ((caja_view))))));
2519}
2520
2521static gboolean
2522reveal_selection_idle_callback (gpointer data)
2523{
2524 FMDirectoryView *view;
2525
2526 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
2527
2528 view->details->reveal_selection_idle_id = 0;
2529 fm_directory_view_reveal_selection (view);
2530
2531 return FALSE(0);
2532}
2533
2534static void
2535done_loading (FMDirectoryView *view,
2536 gboolean all_files_seen)
2537{
2538 if (!view->details->loading) {
2539 return;
2540 }
2541
2542 /* This can be called during destruction, in which case there
2543 * is no CajaWindowInfo any more.
2544 */
2545 if (view->details->window != NULL((void*)0)) {
2546 GList *locations_selected;
2547
2548 if (all_files_seen) {
2549 caja_window_info_report_load_complete (view->details->window, CAJA_VIEW (view)((((CajaView*) (void *) ((view))))));
2550 }
2551
2552 schedule_update_menus (view);
2553 schedule_update_status (view);
2554 reset_update_interval (view);
2555
2556 locations_selected = view->details->pending_locations_selected;
2557
2558 if (locations_selected != NULL((void*)0) && all_files_seen) {
2559 GList *selection;
2560
2561 view->details->pending_locations_selected = NULL((void*)0);
2562
2563 selection = file_list_from_location_list (locations_selected);
2564
2565 view->details->selection_change_is_due_to_shell = TRUE(!(0));
2566 fm_directory_view_set_selection (view, selection);
2567 view->details->selection_change_is_due_to_shell = FALSE(0);
2568 caja_file_list_free (selection);
2569
2570 if (FM_IS_LIST_VIEW (view)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view)); GType __t = (fm_list_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; }))))
) {
2571 /* HACK: We should be able to directly call reveal_selection here,
2572 * but at this point the GtkTreeView hasn't allocated the new nodes
2573 * yet, and it has a bug in the scroll calculation dealing with this
2574 * special case. It would always make the selection the top row, even
2575 * if no scrolling would be neccessary to reveal it. So we let it
2576 * allocate before revealing.
2577 */
2578 if (view->details->reveal_selection_idle_id != 0) {
2579 g_source_remove (view->details->reveal_selection_idle_id);
2580 }
2581 view->details->reveal_selection_idle_id =
2582 g_idle_add (reveal_selection_idle_callback, view);
2583 } else {
2584 fm_directory_view_reveal_selection (view);
2585 }
2586 }
2587 g_list_free_full (locations_selected, g_object_unref);
2588 fm_directory_view_display_selection_info (view);
2589 }
2590
2591 fm_directory_view_end_loading (view, all_files_seen);
2592
2593 view->details->loading = FALSE(0);
2594}
2595
2596
2597typedef struct {
2598 GHashTable *debuting_files;
2599 GList *added_files;
2600} DebutingFilesData;
2601
2602static void
2603debuting_files_data_free (DebutingFilesData *data)
2604{
2605 g_hash_table_unref (data->debuting_files);
2606 caja_file_list_free (data->added_files);
2607 g_free (data);
2608}
2609
2610/* This signal handler watch for the arrival of the icons created
2611 * as the result of a file operation. Once the last one is detected
2612 * it selects and reveals them all.
2613 */
2614static void
2615debuting_files_add_file_callback (FMDirectoryView *view,
2616 CajaFile *new_file,
2617 CajaDirectory *directory,
2618 DebutingFilesData *data)
2619{
2620 GFile *location;
2621
2622 location = caja_file_get_location (new_file);
2623
2624 if (g_hash_table_remove (data->debuting_files, location)) {
2625 caja_file_ref (new_file);
2626 data->added_files = g_list_prepend (data->added_files, new_file);
2627
2628 if (g_hash_table_size (data->debuting_files) == 0) {
2629 fm_directory_view_set_selection (view, data->added_files);
2630 fm_directory_view_reveal_selection (view);
2631 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) (debuting_files_add_file_callback))), (data
))
2632 G_CALLBACK (debuting_files_add_file_callback),g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (debuting_files_add_file_callback))), (data
))
2633 data)g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (debuting_files_add_file_callback))), (data
))
;
2634 }
2635 }
2636
2637 g_object_unref (location);
2638}
2639
2640typedef struct {
2641 GList *added_files;
2642 FMDirectoryView *directory_view;
2643} CopyMoveDoneData;
2644
2645static void
2646copy_move_done_data_free (CopyMoveDoneData *data)
2647{
2648 g_assert (data != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if (data != ((void*)0)) _g_boolean_var_205 = 1; else _g_boolean_var_205
= 0; _g_boolean_var_205; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 2648, ((const char*) (
__func__)), "data != NULL"); } while (0)
;
2649
2650 eel_remove_weak_pointer (&data->directory_view);
2651 caja_file_list_free (data->added_files);
2652 g_free (data);
2653}
2654
2655static void
2656pre_copy_move_add_file_callback (FMDirectoryView *view,
2657 CajaFile *new_file,
2658 CajaDirectory *directory,
2659 CopyMoveDoneData *data)
2660{
2661 caja_file_ref (new_file);
2662 data->added_files = g_list_prepend (data->added_files, new_file);
2663}
2664
2665/* This needs to be called prior to caja_file_operations_copy_move.
2666 * It hooks up a signal handler to catch any icons that get added before
2667 * the copy_done_callback is invoked. The return value should be passed
2668 * as the data for uri_copy_move_done_callback.
2669 */
2670static CopyMoveDoneData *
2671pre_copy_move (FMDirectoryView *directory_view)
2672{
2673 CopyMoveDoneData *copy_move_done_data;
2674
2675 copy_move_done_data = g_new0 (CopyMoveDoneData, 1)(CopyMoveDoneData *) (__extension__ ({ gsize __n = (gsize) (1
); gsize __s = sizeof (CopyMoveDoneData); 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; }))
;
2676 copy_move_done_data->directory_view = directory_view;
2677
2678 eel_add_weak_pointer (&copy_move_done_data->directory_view);
2679
2680 /* We need to run after the default handler adds the folder we want to
2681 * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
2682 * must use connect_after.
2683 */
2684 g_signal_connect (directory_view, "add_file",g_signal_connect_data ((directory_view), ("add_file"), (((GCallback
) (pre_copy_move_add_file_callback))), (copy_move_done_data),
((void*)0), (GConnectFlags) 0)
2685 G_CALLBACK (pre_copy_move_add_file_callback), copy_move_done_data)g_signal_connect_data ((directory_view), ("add_file"), (((GCallback
) (pre_copy_move_add_file_callback))), (copy_move_done_data),
((void*)0), (GConnectFlags) 0)
;
2686
2687 return copy_move_done_data;
2688}
2689
2690/* This function is used to pull out any debuting uris that were added
2691 * and (as a side effect) remove them from the debuting uri hash table.
2692 */
2693static gboolean
2694copy_move_done_partition_func (gpointer data, gpointer callback_data)
2695{
2696 GFile *location;
2697 gboolean result;
2698
2699 location = caja_file_get_location (CAJA_FILE (data)((((CajaFile*) (void *) ((data))))));
2700 result = g_hash_table_remove ((GHashTable *) callback_data, location);
2701 g_object_unref (location);
2702
2703 return result;
2704}
2705
2706static gboolean
2707remove_not_really_moved_files (gpointer key,
2708 gpointer value,
2709 gpointer callback_data)
2710{
2711 GList **added_files;
2712 GFile *loc;
2713
2714 loc = key;
2715
2716 if (GPOINTER_TO_INT (value)((gint) (glong) (value))) {
2717 return FALSE(0);
2718 }
2719
2720 added_files = callback_data;
2721 *added_files = g_list_prepend (*added_files,
2722 caja_file_get (loc));
2723 return TRUE(!(0));
2724}
2725
2726
2727/* When this function is invoked, the file operation is over, but all
2728 * the icons may not have been added to the directory view yet, so
2729 * we can't select them yet.
2730 *
2731 * We're passed a hash table of the uri's to look out for, we hook
2732 * up a signal handler to await their arrival.
2733 */
2734static void
2735copy_move_done_callback (GHashTable *debuting_files, gpointer data)
2736{
2737 FMDirectoryView *directory_view;
2738 CopyMoveDoneData *copy_move_done_data;
2739 DebutingFilesData *debuting_files_data;
2740
2741 copy_move_done_data = (CopyMoveDoneData *) data;
2742 directory_view = copy_move_done_data->directory_view;
2743
2744 if (directory_view != NULL((void*)0)) {
2745 g_assert (FM_IS_DIRECTORY_VIEW (directory_view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory_view)); GType __t = (fm_directory_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_206 = 1; else _g_boolean_var_206 =
0; _g_boolean_var_206; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 2745, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (directory_view)"); } while
(0)
;
2746
2747 debuting_files_data = g_new (DebutingFilesData, 1)(DebutingFilesData *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (DebutingFilesData); 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; }))
;
2748 debuting_files_data->debuting_files = g_hash_table_ref (debuting_files);
2749 debuting_files_data->added_files = eel_g_list_partition
2750 (copy_move_done_data->added_files,
2751 copy_move_done_partition_func,
2752 debuting_files,
2753 &copy_move_done_data->added_files);
2754
2755 /* We're passed the same data used by pre_copy_move_add_file_callback, so disconnecting
2756 * it will free data. We've already siphoned off the added_files we need, and stashed the
2757 * directory_view pointer.
2758 */
2759 g_signal_handlers_disconnect_by_func (directory_view,g_signal_handlers_disconnect_matched ((directory_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pre_copy_move_add_file_callback))), (data)
)
2760 G_CALLBACK (pre_copy_move_add_file_callback),g_signal_handlers_disconnect_matched ((directory_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pre_copy_move_add_file_callback))), (data)
)
2761 data)g_signal_handlers_disconnect_matched ((directory_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pre_copy_move_add_file_callback))), (data)
)
;
2762
2763 /* Any items in the debuting_files hash table that have
2764 * "FALSE" as their value aren't really being copied
2765 * or moved, so we can't wait for an add_file signal
2766 * to come in for those.
2767 */
2768 g_hash_table_foreach_remove (debuting_files,
2769 remove_not_really_moved_files,
2770 &debuting_files_data->added_files);
2771
2772 if (g_hash_table_size (debuting_files) == 0) {
2773 /* on the off-chance that all the icons have already been added */
2774 if (debuting_files_data->added_files != NULL((void*)0)) {
2775 fm_directory_view_set_selection (directory_view,
2776 debuting_files_data->added_files);
2777 fm_directory_view_reveal_selection (directory_view);
2778 }
2779 debuting_files_data_free (debuting_files_data);
2780 } else {
2781 /* We need to run after the default handler adds the folder we want to
2782 * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
2783 * must use connect_after.
2784 */
2785 g_signal_connect_data (directory_view,
2786 "add_file",
2787 G_CALLBACK (debuting_files_add_file_callback)((GCallback) (debuting_files_add_file_callback)),
2788 debuting_files_data,
2789 (GClosureNotify) debuting_files_data_free,
2790 G_CONNECT_AFTER);
2791 }
2792
2793 /* Schedule menu update for undo items */
2794 schedule_update_menus (directory_view);
2795
2796 }
2797
2798 copy_move_done_data_free (copy_move_done_data);
2799}
2800
2801static gboolean
2802real_file_still_belongs (FMDirectoryView *view, CajaFile *file, CajaDirectory *directory)
2803{
2804 if (view->details->model != directory &&
2805 g_list_find (view->details->subdirectory_list, directory) == NULL((void*)0)) {
2806 return FALSE(0);
2807 }
2808
2809 return caja_directory_contains_file (directory, file);
2810}
2811
2812static gboolean
2813still_should_show_file (FMDirectoryView *view, CajaFile *file, CajaDirectory *directory)
2814{
2815 return fm_directory_view_should_show_file (view, file)
2816 && EEL_INVOKE_METHOD (FM_DIRECTORY_VIEW_CLASS, view, file_still_belongs, (view, file, directory))((* (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*)
(((GTypeInstance*) ((view)))->g_class)))))))))->file_still_belongs
)) (view, file, directory))
;
2817}
2818
2819static gboolean
2820ready_to_load (CajaFile *file)
2821{
2822 return caja_file_check_if_ready (file,
2823 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
);
2824}
2825
2826static int
2827compare_files_cover (gconstpointer a, gconstpointer b, gpointer callback_data)
2828{
2829 const FileAndDirectory *fad1, *fad2;
2830 FMDirectoryView *view;
2831
2832 view = callback_data;
2833 fad1 = a; fad2 = b;
2834
2835 if (fad1->directory < fad2->directory) {
2836 return -1;
2837 } else if (fad1->directory > fad2->directory) {
2838 return 1;
2839 } else {
2840 return EEL_INVOKE_METHOD (FM_DIRECTORY_VIEW_CLASS, view, compare_files,((* (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*)
(((GTypeInstance*) ((view)))->g_class)))))))))->compare_files
)) (view, fad1->file, fad2->file))
2841 (view, fad1->file, fad2->file))((* (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*)
(((GTypeInstance*) ((view)))->g_class)))))))))->compare_files
)) (view, fad1->file, fad2->file))
;
2842 }
2843}
2844static void
2845sort_files (FMDirectoryView *view, GList **list)
2846{
2847 *list = g_list_sort_with_data (*list, compare_files_cover, view);
2848
2849}
2850
2851/* Go through all the new added and changed files.
2852 * Put any that are not ready to load in the non_ready_files hash table.
2853 * Add all the rest to the old_added_files and old_changed_files lists.
2854 * Sort the old_*_files lists if anything was added to them.
2855 */
2856static void
2857process_new_files (FMDirectoryView *view)
2858{
2859 GList *new_added_files, *new_changed_files, *old_added_files, *old_changed_files;
2860 GHashTable *non_ready_files;
2861 GList *node, *next;
2862 FileAndDirectory *pending;
2863 gboolean in_non_ready;
2864
2865 new_added_files = view->details->new_added_files;
2866 view->details->new_added_files = NULL((void*)0);
2867 new_changed_files = view->details->new_changed_files;
2868 view->details->new_changed_files = NULL((void*)0);
2869
2870 non_ready_files = view->details->non_ready_files;
2871
2872 old_added_files = view->details->old_added_files;
2873 old_changed_files = view->details->old_changed_files;
2874
2875 /* Newly added files go into the old_added_files list if they're
2876 * ready, and into the hash table if they're not.
2877 */
2878 for (node = new_added_files; node != NULL((void*)0); node = next) {
2879 next = node->next;
2880 pending = (FileAndDirectory *)node->data;
2881 in_non_ready = g_hash_table_lookup (non_ready_files, pending) != NULL((void*)0);
2882 if (fm_directory_view_should_show_file (view, pending->file)) {
2883 if (ready_to_load (pending->file)) {
2884 if (in_non_ready) {
2885 g_hash_table_remove (non_ready_files, pending);
2886 }
2887 new_added_files = g_list_delete_link (new_added_files, node);
2888 old_added_files = g_list_prepend (old_added_files, pending);
2889 } else {
2890 if (!in_non_ready) {
2891 new_added_files = g_list_delete_link (new_added_files, node);
2892 g_hash_table_insert (non_ready_files, pending, pending);
2893 }
2894 }
2895 }
2896 }
2897 file_and_directory_list_free (new_added_files);
2898
2899 /* Newly changed files go into the old_added_files list if they're ready
2900 * and were seen non-ready in the past, into the old_changed_files list
2901 * if they are read and were not seen non-ready in the past, and into
2902 * the hash table if they're not ready.
2903 */
2904 for (node = new_changed_files; node != NULL((void*)0); node = next) {
2905 next = node->next;
2906 pending = (FileAndDirectory *)node->data;
2907 if (!still_should_show_file (view, pending->file, pending->directory) || ready_to_load (pending->file)) {
2908 if (g_hash_table_lookup (non_ready_files, pending) != NULL((void*)0)) {
2909 g_hash_table_remove (non_ready_files, pending);
2910 if (still_should_show_file (view, pending->file, pending->directory)) {
2911 new_changed_files = g_list_delete_link (new_changed_files, node);
2912 old_added_files = g_list_prepend (old_added_files, pending);
2913 }
2914 } else if (fm_directory_view_should_show_file (view, pending->file)) {
2915 new_changed_files = g_list_delete_link (new_changed_files, node);
2916 old_changed_files = g_list_prepend (old_changed_files, pending);
2917 }
2918 }
2919 }
2920 file_and_directory_list_free (new_changed_files);
2921
2922 /* If any files were added to old_added_files, then resort it. */
2923 if (old_added_files != view->details->old_added_files) {
2924 view->details->old_added_files = old_added_files;
2925 sort_files (view, &view->details->old_added_files);
2926 }
2927
2928 /* Resort old_changed_files too, since file attributes
2929 * relevant to sorting could have changed.
2930 */
2931 if (old_changed_files != view->details->old_changed_files) {
2932 view->details->old_changed_files = old_changed_files;
2933 sort_files (view, &view->details->old_changed_files);
2934 }
2935
2936}
2937
2938static void
2939process_old_files (FMDirectoryView *view)
2940{
2941 GList *files_added, *files_changed, *node;
2942 GList *selection, *files;
2943 gboolean send_selection_change;
2944
2945 files_added = view->details->old_added_files;
2946 files_changed = view->details->old_changed_files;
2947
2948 send_selection_change = FALSE(0);
2949
2950 if (files_added != NULL((void*)0) || files_changed != NULL((void*)0)) {
2951 FileAndDirectory *pending = NULL((void*)0);
2952
2953 g_signal_emit (view, signals[BEGIN_FILE_CHANGES], 0);
2954
2955 for (node = files_added; node != NULL((void*)0); node = node->next) {
2956 pending = node->data;
2957 g_signal_emit (view,
2958 signals[ADD_FILE], 0, pending->file, pending->directory);
2959 }
2960
2961 for (node = files_changed; node != NULL((void*)0); node = node->next) {
2962 pending = node->data;
2963 g_signal_emit (view,
2964 signals[still_should_show_file (view, pending->file, pending->directory)
2965 ? FILE_CHANGED : REMOVE_FILE], 0,
2966 pending->file, pending->directory);
2967 }
2968
2969 g_signal_emit (view, signals[END_FILE_CHANGES], 0);
2970
2971 if (files_changed != NULL((void*)0)) {
2972 selection = fm_directory_view_get_selection (view);
2973 files = file_and_directory_list_to_files (files_changed);
2974 send_selection_change = eel_g_lists_sort_and_check_for_intersection
2975 (&files, &selection);
2976 caja_file_list_free (files);
2977 caja_file_list_free (selection);
2978 }
2979
2980 file_and_directory_list_free (view->details->old_added_files);
2981 view->details->old_added_files = NULL((void*)0);
2982
2983 file_and_directory_list_free (view->details->old_changed_files);
2984 view->details->old_changed_files = NULL((void*)0);
2985 }
2986
2987 if (send_selection_change) {
2988 /* Send a selection change since some file names could
2989 * have changed.
2990 */
2991 fm_directory_view_send_selection_change (view);
2992 }
2993}
2994
2995static void
2996display_pending_files (FMDirectoryView *view)
2997{
2998
2999 /* Don't dispatch any updates while the view is frozen. */
3000 if (view->details->updates_frozen) {
3001 return;
3002 }
3003
3004 process_new_files (view);
3005 process_old_files (view);
3006
3007 if (view->details->model != NULL((void*)0)
3008 && caja_directory_are_all_files_seen (view->details->model)
3009 && g_hash_table_size (view->details->non_ready_files) == 0) {
3010 done_loading (view, TRUE(!(0)));
3011 }
3012}
3013
3014void
3015fm_directory_view_freeze_updates (FMDirectoryView *view)
3016{
3017 view->details->updates_frozen = TRUE(!(0));
3018 view->details->updates_queued = 0;
3019 view->details->needs_reload = FALSE(0);
3020}
3021
3022void
3023fm_directory_view_unfreeze_updates (FMDirectoryView *view)
3024{
3025 view->details->updates_frozen = FALSE(0);
3026
3027 if (view->details->needs_reload) {
3028 view->details->needs_reload = FALSE(0);
3029 if (view->details->model != NULL((void*)0)) {
3030 load_directory (view, view->details->model);
3031 }
3032 } else {
3033 schedule_idle_display_of_pending_files (view);
3034 }
3035}
3036
3037static gboolean
3038display_selection_info_idle_callback (gpointer data)
3039{
3040 FMDirectoryView *view;
3041
3042 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
3043
3044 g_object_ref (G_OBJECT (view))((__typeof__ (((((GObject*) (void *) ((view))))))) (g_object_ref
) (((((GObject*) (void *) ((view)))))))
;
3045
3046 view->details->display_selection_idle_id = 0;
3047 fm_directory_view_display_selection_info (view);
3048 if (view->details->send_selection_change_to_shell) {
3049 fm_directory_view_send_selection_change (view);
3050 }
3051
3052 g_object_unref (G_OBJECT (view)((((GObject*) (void *) ((view))))));
3053
3054 return FALSE(0);
3055}
3056
3057static void
3058remove_update_menus_timeout_callback (FMDirectoryView *view)
3059{
3060 if (view->details->update_menus_timeout_id != 0) {
3061 g_source_remove (view->details->update_menus_timeout_id);
3062 view->details->update_menus_timeout_id = 0;
3063 }
3064}
3065
3066static void
3067update_menus_if_pending (FMDirectoryView *view)
3068{
3069 if (!view->details->menu_states_untrustworthy) {
3070 return;
3071 }
3072
3073 remove_update_menus_timeout_callback (view);
3074 fm_directory_view_update_menus (view);
3075}
3076
3077static gboolean
3078update_menus_timeout_callback (gpointer data)
3079{
3080 FMDirectoryView *view;
3081
3082 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
3083
3084 g_object_ref (G_OBJECT (view))((__typeof__ (((((GObject*) (void *) ((view))))))) (g_object_ref
) (((((GObject*) (void *) ((view)))))))
;
3085
3086 view->details->update_menus_timeout_id = 0;
3087 fm_directory_view_update_menus (view);
3088
3089 g_object_unref (G_OBJECT (view)((((GObject*) (void *) ((view))))));
3090
3091 return FALSE(0);
3092}
3093
3094static gboolean
3095display_pending_callback (gpointer data)
3096{
3097 FMDirectoryView *view;
3098
3099 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
3100
3101 g_object_ref (G_OBJECT (view))((__typeof__ (((((GObject*) (void *) ((view))))))) (g_object_ref
) (((((GObject*) (void *) ((view)))))))
;
3102
3103 view->details->display_pending_source_id = 0;
3104
3105 display_pending_files (view);
3106
3107 g_object_unref (G_OBJECT (view)((((GObject*) (void *) ((view))))));
3108
3109 return FALSE(0);
3110}
3111
3112static void
3113schedule_idle_display_of_pending_files (FMDirectoryView *view)
3114{
3115 /* Get rid of a pending source as it might be a timeout */
3116 unschedule_display_of_pending_files (view);
3117
3118 /* We want higher priority than the idle that handles the relayout
3119 to avoid a resort on each add. But we still want to allow repaints
3120 and other hight prio events while we have pending files to show. */
3121 view->details->display_pending_source_id =
3122 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE200 - 20,
3123 display_pending_callback, view, NULL((void*)0));
3124}
3125
3126static void
3127schedule_timeout_display_of_pending_files (FMDirectoryView *view, guint interval)
3128{
3129 /* No need to schedule an update if there's already one pending. */
3130 if (view->details->display_pending_source_id != 0) {
3131 return;
3132 }
3133
3134 view->details->display_pending_source_id =
3135 g_timeout_add (interval, display_pending_callback, view);
3136}
3137
3138static void
3139unschedule_display_of_pending_files (FMDirectoryView *view)
3140{
3141 /* Get rid of source if it's active. */
3142 if (view->details->display_pending_source_id != 0) {
3143 g_source_remove (view->details->display_pending_source_id);
3144 view->details->display_pending_source_id = 0;
3145 }
3146}
3147
3148static void
3149queue_pending_files (FMDirectoryView *view,
3150 CajaDirectory *directory,
3151 GList *files,
3152 GList **pending_list)
3153{
3154 if (files == NULL((void*)0)) {
3155 return;
3156 }
3157
3158 /* Don't queue any more updates if we need to reload anyway */
3159 if (view->details->needs_reload) {
3160 return;
3161 }
3162
3163 if (view->details->updates_frozen) {
3164 view->details->updates_queued += g_list_length (files);
3165 /* Mark the directory for reload when there are too much queued
3166 * changes to prevent the pending list from growing infinitely.
3167 */
3168 if (view->details->updates_queued > MAX_QUEUED_UPDATES500) {
3169 view->details->needs_reload = TRUE(!(0));
3170 return;
3171 }
3172 }
3173
3174
3175
3176 *pending_list = g_list_concat (file_and_directory_list_from_files (directory, files),
3177 *pending_list);
3178
3179 if (! view->details->loading || caja_directory_are_all_files_seen (directory)) {
3180 schedule_timeout_display_of_pending_files (view, view->details->update_interval);
3181 }
3182}
3183
3184static void
3185remove_changes_timeout_callback (FMDirectoryView *view)
3186{
3187 if (view->details->changes_timeout_id != 0) {
3188 g_source_remove (view->details->changes_timeout_id);
3189 view->details->changes_timeout_id = 0;
3190 }
3191}
3192
3193static void
3194reset_update_interval (FMDirectoryView *view)
3195{
3196 view->details->update_interval = UPDATE_INTERVAL_MIN100;
3197 remove_changes_timeout_callback (view);
3198 /* Reschedule a pending timeout to idle */
3199 if (view->details->display_pending_source_id != 0) {
3200 schedule_idle_display_of_pending_files (view);
3201 }
3202}
3203
3204static gboolean
3205changes_timeout_callback (gpointer data)
3206{
3207 gint64 now;
3208 gint64 time_delta;
3209 gboolean ret;
3210 FMDirectoryView *view;
3211
3212 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
3213
3214 g_object_ref (G_OBJECT (view))((__typeof__ (((((GObject*) (void *) ((view))))))) (g_object_ref
) (((((GObject*) (void *) ((view)))))))
;
3215
3216 now = g_get_monotonic_time();
3217 time_delta = now - view->details->last_queued;
3218
3219 if (time_delta < UPDATE_INTERVAL_RESET1000*1000) {
3220 if (view->details->update_interval < UPDATE_INTERVAL_MAX2000 &&
3221 view->details->loading) {
3222 /* Increase */
3223 view->details->update_interval += UPDATE_INTERVAL_INC250;
3224 }
3225 ret = TRUE(!(0));
3226 } else {
3227 /* Reset */
3228 reset_update_interval (view);
3229 ret = FALSE(0);
3230 }
3231
3232 g_object_unref (G_OBJECT (view)((((GObject*) (void *) ((view))))));
3233
3234 return ret;
3235}
3236
3237static void
3238schedule_changes (FMDirectoryView *view)
3239{
3240 /* Remember when the change was queued */
3241 view->details->last_queued = g_get_monotonic_time();
3242
3243 /* No need to schedule if there are already changes pending or during loading */
3244 if (view->details->changes_timeout_id != 0 ||
3245 view->details->loading) {
3246 return;
3247 }
3248
3249 view->details->changes_timeout_id =
3250 g_timeout_add (UPDATE_INTERVAL_TIMEOUT_INTERVAL250, changes_timeout_callback, view);
3251}
3252
3253static void
3254action_undo_callback (GtkAction *action,
3255 gpointer callback_data)
3256{
3257 real_action_undo (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))));
3258}
3259
3260static void
3261action_redo_callback (GtkAction *action,
3262 gpointer callback_data)
3263{
3264 real_action_redo (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))));
3265}
3266
3267static void
3268files_added_callback (CajaDirectory *directory,
3269 GList *files,
3270 gpointer callback_data)
3271{
3272 FMDirectoryView *view;
3273 GtkWindow *window;
3274 char *uri;
3275
3276 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
3277
3278 window = fm_directory_view_get_containing_window (view);
3279 uri = fm_directory_view_get_uri (view);
3280 caja_debug_log_with_file_list (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_ASYNC"async", files,
3281 "files added in window %p: %s",
3282 window,
3283 uri ? uri : "(no directory)");
3284 g_free (uri);
3285
3286 schedule_changes (view);
3287
3288 queue_pending_files (view, directory, files, &view->details->new_added_files);
3289
3290 /* The number of items could have changed */
3291 schedule_update_status (view);
3292}
3293
3294static void
3295files_changed_callback (CajaDirectory *directory,
3296 GList *files,
3297 gpointer callback_data)
3298{
3299 FMDirectoryView *view;
3300 GtkWindow *window;
3301 char *uri;
3302
3303 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
3304
3305 window = fm_directory_view_get_containing_window (view);
3306 uri = fm_directory_view_get_uri (view);
3307 caja_debug_log_with_file_list (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_ASYNC"async", files,
3308 "files changed in window %p: %s",
3309 window,
3310 uri ? uri : "(no directory)");
3311 g_free (uri);
3312
3313 schedule_changes (view);
3314
3315 queue_pending_files (view, directory, files, &view->details->new_changed_files);
3316
3317 /* The free space or the number of items could have changed */
3318 schedule_update_status (view);
3319
3320 /* A change in MIME type could affect the Open with menu, for
3321 * one thing, so we need to update menus when files change.
3322 */
3323 schedule_update_menus (view);
3324}
3325
3326static void
3327done_loading_callback (CajaDirectory *directory,
3328 gpointer callback_data)
3329{
3330 FMDirectoryView *view;
3331
3332 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
3333
3334 process_new_files (view);
3335 if (g_hash_table_size (view->details->non_ready_files) == 0) {
3336 /* Unschedule a pending update and schedule a new one with the minimal
3337 * update interval. This gives the view a short chance at gathering the
3338 * (cached) deep counts.
3339 */
3340 unschedule_display_of_pending_files (view);
3341 schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN100);
3342 }
3343}
3344
3345static void
3346load_error_callback (CajaDirectory *directory,
3347 GError *error,
3348 gpointer callback_data)
3349{
3350 FMDirectoryView *view;
3351
3352 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
3353
3354 /* FIXME: By doing a stop, we discard some pending files. Is
3355 * that OK?
3356 */
3357 fm_directory_view_stop (view);
3358
3359 /* Emit a signal to tell subclasses that a load error has
3360 * occurred, so they can handle it in the UI.
3361 */
3362 g_signal_emit (view,
3363 signals[LOAD_ERROR], 0, error);
3364}
3365
3366static void
3367real_load_error (FMDirectoryView *view, GError *error)
3368{
3369 /* Report only one error per failed directory load (from the UI
3370 * point of view, not from the CajaDirectory point of view).
3371 * Otherwise you can get multiple identical errors caused by
3372 * unrelated code that just happens to try to iterate this
3373 * directory.
3374 */
3375 if (!view->details->reported_load_error) {
3376 fm_report_error_loading_directory
3377 (fm_directory_view_get_directory_as_file (view),
3378 error,
3379 fm_directory_view_get_containing_window (view));
3380 }
3381 view->details->reported_load_error = TRUE(!(0));
3382}
3383
3384void
3385fm_directory_view_add_subdirectory (FMDirectoryView *view,
3386 CajaDirectory*directory)
3387{
3388 CajaFileAttributes attributes;
3389
3390 g_assert (!g_list_find (view->details->subdirectory_list, directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if (!g_list_find (view->details->subdirectory_list, directory
)) _g_boolean_var_207 = 1; else _g_boolean_var_207 = 0; _g_boolean_var_207
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 3390, ((const char*) (__func__)), "!g_list_find (view->details->subdirectory_list, directory)"
); } while (0)
;
3391
3392 caja_directory_ref (directory);
3393
3394 attributes =
3395 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
|
3396 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
3397 CAJA_FILE_ATTRIBUTE_INFO |
3398 CAJA_FILE_ATTRIBUTE_LINK_INFO |
3399 CAJA_FILE_ATTRIBUTE_MOUNT |
3400 CAJA_FILE_ATTRIBUTE_EXTENSION_INFO;
3401
3402 caja_directory_file_monitor_add (directory,
3403 &view->details->model,
3404 view->details->show_hidden_files,
3405 attributes,
3406 files_added_callback, view);
3407
3408 g_signal_connectg_signal_connect_data ((directory), ("files_added"), (((GCallback
) (files_added_callback))), (view), ((void*)0), (GConnectFlags
) 0)
3409 (directory, "files_added",g_signal_connect_data ((directory), ("files_added"), (((GCallback
) (files_added_callback))), (view), ((void*)0), (GConnectFlags
) 0)
3410 G_CALLBACK (files_added_callback), view)g_signal_connect_data ((directory), ("files_added"), (((GCallback
) (files_added_callback))), (view), ((void*)0), (GConnectFlags
) 0)
;
3411 g_signal_connectg_signal_connect_data ((directory), ("files_changed"), (((GCallback
) (files_changed_callback))), (view), ((void*)0), (GConnectFlags
) 0)
3412 (directory, "files_changed",g_signal_connect_data ((directory), ("files_changed"), (((GCallback
) (files_changed_callback))), (view), ((void*)0), (GConnectFlags
) 0)
3413 G_CALLBACK (files_changed_callback), view)g_signal_connect_data ((directory), ("files_changed"), (((GCallback
) (files_changed_callback))), (view), ((void*)0), (GConnectFlags
) 0)
;
3414
3415 view->details->subdirectory_list = g_list_prepend (
3416 view->details->subdirectory_list, directory);
3417}
3418
3419void
3420fm_directory_view_remove_subdirectory (FMDirectoryView *view,
3421 CajaDirectory*directory)
3422{
3423 g_assert (g_list_find (view->details->subdirectory_list, directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (g_list_find (view->details->subdirectory_list, directory
)) _g_boolean_var_208 = 1; else _g_boolean_var_208 = 0; _g_boolean_var_208
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 3423, ((const char*) (__func__)), "g_list_find (view->details->subdirectory_list, directory)"
); } while (0)
;
3424
3425 view->details->subdirectory_list = g_list_remove (
3426 view->details->subdirectory_list, directory);
3427
3428 g_signal_handlers_disconnect_by_func (directory,g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (files_added_callback))), (view))
3429 G_CALLBACK (files_added_callback),g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (files_added_callback))), (view))
3430 view)g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (files_added_callback))), (view))
;
3431 g_signal_handlers_disconnect_by_func (directory,g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (files_changed_callback))), (view))
3432 G_CALLBACK (files_changed_callback),g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (files_changed_callback))), (view))
3433 view)g_signal_handlers_disconnect_matched ((directory), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (files_changed_callback))), (view))
;
3434
3435 caja_directory_file_monitor_remove (directory, &view->details->model);
3436
3437 caja_directory_unref (directory);
3438}
3439
3440/**
3441 * fm_directory_view_clear:
3442 *
3443 * Emit the signal to clear the contents of the view. Subclasses must
3444 * override the signal handler for this signal. This is normally called
3445 * only by FMDirectoryView.
3446 * @view: FMDirectoryView to empty.
3447 *
3448 **/
3449void
3450fm_directory_view_clear (FMDirectoryView *view)
3451{
3452 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_209
= 1; else _g_boolean_var_209 = 0; _g_boolean_var_209; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3453
3454 g_signal_emit (view, signals[CLEAR], 0);
3455}
3456
3457/**
3458 * fm_directory_view_begin_loading:
3459 *
3460 * Emit the signal to prepare for loading the contents of a new location.
3461 * Subclasses might want to override the signal handler for this signal.
3462 * This is normally called only by FMDirectoryView.
3463 * @view: FMDirectoryView that is switching to view a new location.
3464 *
3465 **/
3466void
3467fm_directory_view_begin_loading (FMDirectoryView *view)
3468{
3469 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_210
= 1; else _g_boolean_var_210 = 0; _g_boolean_var_210; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3470
3471 g_signal_emit (view, signals[BEGIN_LOADING], 0);
3472}
3473
3474/**
3475 * fm_directory_view_end_loading:
3476 *
3477 * Emit the signal after loading the contents of a new location.
3478 * Subclasses might want to override the signal handler for this signal.
3479 * This is normally called only by FMDirectoryView.
3480 * @view: FMDirectoryView that is switching to view a new location.
3481 *
3482 **/
3483void
3484fm_directory_view_end_loading (FMDirectoryView *view,
3485 gboolean all_files_seen)
3486{
3487 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_211
= 1; else _g_boolean_var_211 = 0; _g_boolean_var_211; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3488
3489 g_signal_emit (view, signals[END_LOADING], 0, all_files_seen);
3490}
3491
3492/**
3493 * fm_directory_view_get_loading:
3494 * @view: an #FMDirectoryView.
3495 *
3496 * Return value: #gboolean inicating whether @view is currently loaded.
3497 *
3498 **/
3499gboolean
3500fm_directory_view_get_loading (FMDirectoryView *view)
3501{
3502 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_212
= 1; else _g_boolean_var_212 = 0; _g_boolean_var_212; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
3503
3504 return view->details->loading;
3505}
3506
3507/**
3508 * fm_directory_view_bump_zoom_level:
3509 *
3510 * bump the current zoom level by invoking the relevant subclass through the slot
3511 *
3512 **/
3513void
3514fm_directory_view_bump_zoom_level (FMDirectoryView *view, int zoom_increment)
3515{
3516 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_213
= 1; else _g_boolean_var_213 = 0; _g_boolean_var_213; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3517
3518 if (!fm_directory_view_supports_zooming (view)) {
3519 return;
3520 }
3521
3522 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->bump_zoom_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->bump_zoom_level) (view, zoom_increment); } } while (
0)
3523 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->bump_zoom_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->bump_zoom_level) (view, zoom_increment); } } while (
0)
3524 bump_zoom_level, (view, zoom_increment))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->bump_zoom_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->bump_zoom_level) (view, zoom_increment); } } while (
0)
;
3525}
3526
3527/**
3528 * fm_directory_view_zoom_to_level:
3529 *
3530 * Set the current zoom level by invoking the relevant subclass through the slot
3531 *
3532 **/
3533void
3534fm_directory_view_zoom_to_level (FMDirectoryView *view,
3535 CajaZoomLevel zoom_level)
3536{
3537 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_214
= 1; else _g_boolean_var_214 = 0; _g_boolean_var_214; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3538
3539 if (!fm_directory_view_supports_zooming (view)) {
3540 return;
3541 }
3542
3543 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->zoom_to_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->zoom_to_level) (view, zoom_level); } } while (0)
3544 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->zoom_to_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->zoom_to_level) (view, zoom_level); } } while (0)
3545 zoom_to_level, (view, zoom_level))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->zoom_to_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->zoom_to_level) (view, zoom_level); } } while (0)
;
3546}
3547
3548
3549CajaZoomLevel
3550fm_directory_view_get_zoom_level (FMDirectoryView *view)
3551{
3552 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), CAJA_ZOOM_LEVEL_STANDARD)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_215
= 1; else _g_boolean_var_215 = 0; _g_boolean_var_215; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
CAJA_ZOOM_LEVEL_STANDARD); } } while (0)
;
3553
3554 if (!fm_directory_view_supports_zooming (view)) {
3555 return CAJA_ZOOM_LEVEL_STANDARD;
3556 }
3557
3558 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_zoom_level
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_zoom_level) (view))
3559 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_zoom_level
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_zoom_level) (view))
3560 get_zoom_level, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_zoom_level
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_zoom_level) (view))
;
3561}
3562
3563/**
3564 * fm_directory_view_restore_default_zoom_level:
3565 *
3566 * restore to the default zoom level by invoking the relevant subclass through the slot
3567 *
3568 **/
3569void
3570fm_directory_view_restore_default_zoom_level (FMDirectoryView *view)
3571{
3572 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_216
= 1; else _g_boolean_var_216 = 0; _g_boolean_var_216; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3573
3574 if (!fm_directory_view_supports_zooming (view)) {
3575 return;
3576 }
3577
3578 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->restore_default_zoom_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->restore_default_zoom_level) (view); } } while (0)
3579 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->restore_default_zoom_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->restore_default_zoom_level) (view); } } while (0)
3580 restore_default_zoom_level, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->restore_default_zoom_level
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->restore_default_zoom_level) (view); } } while (0)
;
3581}
3582
3583/**
3584 * fm_directory_view_can_zoom_in:
3585 *
3586 * Determine whether the view can be zoomed any closer.
3587 * @view: The zoomable FMDirectoryView.
3588 *
3589 * Return value: TRUE if @view can be zoomed any closer, FALSE otherwise.
3590 *
3591 **/
3592gboolean
3593fm_directory_view_can_zoom_in (FMDirectoryView *view)
3594{
3595 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_217
= 1; else _g_boolean_var_217 = 0; _g_boolean_var_217; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
3596
3597 if (!fm_directory_view_supports_zooming (view)) {
3598 return FALSE(0);
3599 }
3600
3601 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_zoom_in
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_zoom_in) (view))
3602 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_zoom_in
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_zoom_in) (view))
3603 can_zoom_in, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_zoom_in
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_zoom_in) (view))
;
3604}
3605
3606/**
3607 * fm_directory_view_can_rename_file
3608 *
3609 * Determine whether a file can be renamed.
3610 * @file: A CajaFile
3611 *
3612 * Return value: TRUE if @file can be renamed, FALSE otherwise.
3613 *
3614 **/
3615static gboolean
3616fm_directory_view_can_rename_file (FMDirectoryView *view, CajaFile *file)
3617{
3618 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_rename_file
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_rename_file) (view, file))
3619 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_rename_file
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_rename_file) (view, file))
3620 can_rename_file, (view, file))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_rename_file
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_rename_file) (view, file))
;
3621}
3622
3623/**
3624 * fm_directory_view_can_zoom_out:
3625 *
3626 * Determine whether the view can be zoomed any further away.
3627 * @view: The zoomable FMDirectoryView.
3628 *
3629 * Return value: TRUE if @view can be zoomed any further away, FALSE otherwise.
3630 *
3631 **/
3632gboolean
3633fm_directory_view_can_zoom_out (FMDirectoryView *view)
3634{
3635 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_218
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_218
= 1; else _g_boolean_var_218 = 0; _g_boolean_var_218; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
3636
3637 if (!fm_directory_view_supports_zooming (view)) {
3638 return FALSE(0);
3639 }
3640
3641 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_zoom_out
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_zoom_out) (view))
3642 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_zoom_out
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_zoom_out) (view))
3643 can_zoom_out, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->can_zoom_out
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->can_zoom_out) (view))
;
3644}
3645
3646GtkWidget *
3647fm_directory_view_get_background_widget (FMDirectoryView *view)
3648{
3649 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_219
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_219
= 1; else _g_boolean_var_219 = 0; _g_boolean_var_219; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
3650
3651 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_background_widget
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_background_widget) (view))
3652 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_background_widget
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_background_widget) (view))
3653 get_background_widget, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_background_widget
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_background_widget) (view))
;
3654}
3655
3656EelBackground *
3657fm_directory_view_get_background (FMDirectoryView *view)
3658{
3659 return eel_get_widget_background (fm_directory_view_get_background_widget (view));
3660}
3661
3662static void
3663real_set_is_active (FMDirectoryView *view,
3664 gboolean is_active)
3665{
3666 EelBackground *bg;
3667
3668 bg = fm_directory_view_get_background (view);
3669 eel_background_set_active (bg, is_active);
3670}
3671
3672static void
3673fm_directory_view_set_is_active (FMDirectoryView *view,
3674 gboolean is_active)
3675{
3676 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_220
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_220
= 1; else _g_boolean_var_220 = 0; _g_boolean_var_220; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3677
3678 EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->set_is_active
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->set_is_active) (view, is_active); } } while (0)
3679 set_is_active, (view, is_active))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->set_is_active
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->set_is_active) (view, is_active); } } while (0)
;
3680}
3681
3682/**
3683 * fm_directory_view_get_selection:
3684 *
3685 * Get a list of CajaFile pointers that represents the
3686 * currently-selected items in this view. Subclasses must override
3687 * the signal handler for the 'get_selection' signal. Callers are
3688 * responsible for g_free-ing the list (but not its data).
3689 * @view: FMDirectoryView whose selected items are of interest.
3690 *
3691 * Return value: GList of CajaFile pointers representing the selection.
3692 *
3693 **/
3694GList *
3695fm_directory_view_get_selection (FMDirectoryView *view)
3696{
3697 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_221
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_221
= 1; else _g_boolean_var_221 = 0; _g_boolean_var_221; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
3698
3699 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selection
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selection) (view))
3700 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selection
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selection) (view))
3701 get_selection, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selection
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selection) (view))
;
3702}
3703
3704void
3705fm_directory_view_invert_selection (FMDirectoryView *view)
3706{
3707 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_222
= 1; else _g_boolean_var_222 = 0; _g_boolean_var_222; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
3708
3709 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->invert_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->invert_selection) (view); } } while (0)
3710 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->invert_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->invert_selection) (view); } } while (0)
3711 invert_selection, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->invert_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->invert_selection) (view); } } while (0)
;
3712}
3713
3714GList *
3715fm_directory_view_get_selection_for_file_transfer (FMDirectoryView *view)
3716{
3717 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_223
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_223
= 1; else _g_boolean_var_223 = 0; _g_boolean_var_223; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
3718
3719 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selection_for_file_transfer
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selection_for_file_transfer) (view))
3720 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selection_for_file_transfer
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selection_for_file_transfer) (view))
3721 get_selection_for_file_transfer, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selection_for_file_transfer
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selection_for_file_transfer) (view))
;
3722}
3723
3724guint
3725fm_directory_view_get_item_count (FMDirectoryView *view)
3726{
3727 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_224
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_224
= 1; else _g_boolean_var_224 = 0; _g_boolean_var_224; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
0); } } while (0)
;
3728
3729 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_item_count
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_item_count) (view))
3730 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_item_count
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_item_count) (view))
3731 get_item_count, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_item_count
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_item_count) (view))
;
3732}
3733
3734GtkUIManager *
3735fm_directory_view_get_ui_manager (FMDirectoryView *view)
3736{
3737 if (view->details->window == NULL((void*)0)) {
3738 return NULL((void*)0);
3739 }
3740 return caja_window_info_get_ui_manager (view->details->window);
3741}
3742
3743/**
3744 * fm_directory_view_get_model:
3745 *
3746 * Get the model for this FMDirectoryView.
3747 * @view: FMDirectoryView of interest.
3748 *
3749 * Return value: CajaDirectory for this view.
3750 *
3751 **/
3752CajaDirectory *
3753fm_directory_view_get_model (FMDirectoryView *view)
3754{
3755 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_225
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_225
= 1; else _g_boolean_var_225 = 0; _g_boolean_var_225; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
3756
3757 return view->details->model;
3758}
3759
3760GdkAtom
3761fm_directory_view_get_copied_files_atom (FMDirectoryView *view)
3762{
3763 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), GDK_NONE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_226
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_226
= 1; else _g_boolean_var_226 = 0; _g_boolean_var_226; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((GdkAtom)((gpointer) (gulong) (0)))); } } while (0)
;
3764
3765 return copied_files_atom;
3766}
3767
3768static void
3769prepend_uri_one (gpointer data, gpointer callback_data)
3770{
3771 CajaFile *file;
3772 GList **result;
3773
3774 g_assert (CAJA_IS_FILE (data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = (caja_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_227
= 1; else _g_boolean_var_227 = 0; _g_boolean_var_227; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 3774, ((const char*) (__func__)), "CAJA_IS_FILE (data)"); }
while (0)
;
3775 g_assert (callback_data != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if (callback_data != ((void*)0)) _g_boolean_var_228 = 1; else
_g_boolean_var_228 = 0; _g_boolean_var_228; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 3775, ((const char*) (
__func__)), "callback_data != NULL"); } while (0)
;
3776
3777 result = (GList **) callback_data;
3778 file = (CajaFile *) data;
3779 *result = g_list_prepend (*result, caja_file_get_uri (file));
3780}
3781
3782static void
3783offset_drop_points (GArray *relative_item_points,
3784 int x_offset, int y_offset)
3785{
3786 guint index;
3787
3788 if (relative_item_points == NULL((void*)0)) {
3789 return;
3790 }
3791
3792 for (index = 0; index < relative_item_points->len; index++) {
3793 g_array_index (relative_item_points, GdkPoint, index)(((GdkPoint*) (void *) (relative_item_points)->data) [(index
)])
.x += x_offset;
3794 g_array_index (relative_item_points, GdkPoint, index)(((GdkPoint*) (void *) (relative_item_points)->data) [(index
)])
.y += y_offset;
3795 }
3796}
3797
3798static void
3799fm_directory_view_create_links_for_files (FMDirectoryView *view, GList *files,
3800 GArray *relative_item_points)
3801{
3802 GList *uris;
3803 char *dir_uri;
3804 CopyMoveDoneData *copy_move_done_data;
3805 g_assert (relative_item_points->len == 0do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if (relative_item_points->len == 0 || g_list_length (files
) == relative_item_points->len) _g_boolean_var_229 = 1; else
_g_boolean_var_229 = 0; _g_boolean_var_229; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 3806, ((const char*) (
__func__)), "relative_item_points->len == 0 || g_list_length (files) == relative_item_points->len"
); } while (0)
3806 || g_list_length (files) == relative_item_points->len)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if (relative_item_points->len == 0 || g_list_length (files
) == relative_item_points->len) _g_boolean_var_229 = 1; else
_g_boolean_var_229 = 0; _g_boolean_var_229; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 3806, ((const char*) (
__func__)), "relative_item_points->len == 0 || g_list_length (files) == relative_item_points->len"
); } while (0)
;
3807
3808 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_230
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_230
= 1; else _g_boolean_var_230 = 0; _g_boolean_var_230; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 3808, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
3809 g_assert (files != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (files != ((void*)0)) _g_boolean_var_231 = 1; else _g_boolean_var_231
= 0; _g_boolean_var_231; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 3809, ((const char*) (
__func__)), "files != NULL"); } while (0)
;
3810
3811 /* create a list of URIs */
3812 uris = NULL((void*)0);
3813 g_list_foreach (files, prepend_uri_one, &uris);
3814 uris = g_list_reverse (uris);
3815
3816 g_assert (g_list_length (uris) == g_list_length (files))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_232
; if (g_list_length (uris) == g_list_length (files)) _g_boolean_var_232
= 1; else _g_boolean_var_232 = 0; _g_boolean_var_232; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 3816, ((const char*) (__func__)), "g_list_length (uris) == g_list_length (files)"
); } while (0)
;
3817
3818 /* offset the drop locations a bit so that we don't pile
3819 * up the icons on top of each other
3820 */
3821 offset_drop_points (relative_item_points,
3822 DUPLICATE_HORIZONTAL_ICON_OFFSET70,
3823 DUPLICATE_VERTICAL_ICON_OFFSET30);
3824
3825 copy_move_done_data = pre_copy_move (view);
3826 dir_uri = fm_directory_view_get_backing_uri (view);
3827 caja_file_operations_copy_move (uris, relative_item_points, dir_uri, GDK_ACTION_LINK,
3828 GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))), copy_move_done_callback, copy_move_done_data);
3829 g_free (dir_uri);
3830 g_list_free_full (uris, g_free);
3831}
3832
3833static void
3834fm_directory_view_duplicate_selection (FMDirectoryView *view, GList *files,
3835 GArray *relative_item_points)
3836{
3837 GList *uris;
3838 CopyMoveDoneData *copy_move_done_data;
3839
3840 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_233
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_233
= 1; else _g_boolean_var_233 = 0; _g_boolean_var_233; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 3840, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
3841 g_assert (files != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_234
; if (files != ((void*)0)) _g_boolean_var_234 = 1; else _g_boolean_var_234
= 0; _g_boolean_var_234; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 3841, ((const char*) (
__func__)), "files != NULL"); } while (0)
;
3842 g_assert (g_list_length (files) == relative_item_points->lendo { if (__builtin_expect (__extension__ ({ int _g_boolean_var_235
; if (g_list_length (files) == relative_item_points->len ||
relative_item_points->len == 0) _g_boolean_var_235 = 1; else
_g_boolean_var_235 = 0; _g_boolean_var_235; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 3843, ((const char*) (
__func__)), "g_list_length (files) == relative_item_points->len || relative_item_points->len == 0"
); } while (0)
3843 || relative_item_points->len == 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_235
; if (g_list_length (files) == relative_item_points->len ||
relative_item_points->len == 0) _g_boolean_var_235 = 1; else
_g_boolean_var_235 = 0; _g_boolean_var_235; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 3843, ((const char*) (
__func__)), "g_list_length (files) == relative_item_points->len || relative_item_points->len == 0"
); } while (0)
;
3844
3845 /* create a list of URIs */
3846 uris = NULL((void*)0);
3847 g_list_foreach (files, prepend_uri_one, &uris);
3848 uris = g_list_reverse (uris);
3849
3850 g_assert (g_list_length (uris) == g_list_length (files))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_236
; if (g_list_length (uris) == g_list_length (files)) _g_boolean_var_236
= 1; else _g_boolean_var_236 = 0; _g_boolean_var_236; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 3850, ((const char*) (__func__)), "g_list_length (uris) == g_list_length (files)"
); } while (0)
;
3851
3852 /* offset the drop locations a bit so that we don't pile
3853 * up the icons on top of each other
3854 */
3855 offset_drop_points (relative_item_points,
3856 DUPLICATE_HORIZONTAL_ICON_OFFSET70,
3857 DUPLICATE_VERTICAL_ICON_OFFSET30);
3858
3859 copy_move_done_data = pre_copy_move (view);
3860 caja_file_operations_copy_move (uris, relative_item_points, NULL((void*)0), GDK_ACTION_COPY,
3861 GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))), copy_move_done_callback, copy_move_done_data);
3862 g_list_free_full (uris, g_free);
3863}
3864
3865/* special_link_in_selection
3866 *
3867 * Return TRUE if one of our special links is in the selection.
3868 * Special links include the following:
3869 * CAJA_DESKTOP_LINK_TRASH, CAJA_DESKTOP_LINK_HOME, CAJA_DESKTOP_LINK_MOUNT
3870 */
3871
3872static gboolean
3873special_link_in_selection (FMDirectoryView *view)
3874{
3875 gboolean saw_link;
3876 GList *selection, *node;
3877 CajaFile *file = NULL((void*)0);
3878
3879 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_237
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_237
= 1; else _g_boolean_var_237 = 0; _g_boolean_var_237; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
3880
3881 saw_link = FALSE(0);
3882
3883 selection = fm_directory_view_get_selection (FM_DIRECTORY_VIEW (view)((((FMDirectoryView*) (void *) ((view))))));
3884
3885 for (node = selection; node != NULL((void*)0); node = node->next) {
3886 file = CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data)))));
3887
3888 saw_link = CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
;
3889
3890 if (saw_link) {
3891 break;
3892 }
3893 }
3894
3895 caja_file_list_free (selection);
3896
3897 return saw_link;
3898}
3899
3900/* desktop_or_home_dir_in_selection
3901 *
3902 * Return TRUE if either the desktop or the home directory is in the selection.
3903 */
3904
3905static gboolean
3906desktop_or_home_dir_in_selection (FMDirectoryView *view)
3907{
3908 gboolean saw_desktop_or_home_dir;
3909 GList *selection, *node;
3910 CajaFile *file = NULL((void*)0);
3911
3912 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_238
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_238
= 1; else _g_boolean_var_238 = 0; _g_boolean_var_238; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
3913
3914 saw_desktop_or_home_dir = FALSE(0);
3915
3916 selection = fm_directory_view_get_selection (FM_DIRECTORY_VIEW (view)((((FMDirectoryView*) (void *) ((view))))));
3917
3918 for (node = selection; node != NULL((void*)0); node = node->next) {
3919 file = CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data)))));
3920
3921 saw_desktop_or_home_dir =
3922 caja_file_is_home (file)
3923 || caja_file_is_desktop_directory (file);
3924
3925 if (saw_desktop_or_home_dir) {
3926 break;
3927 }
3928 }
3929
3930 caja_file_list_free (selection);
3931
3932 return saw_desktop_or_home_dir;
3933}
3934
3935static void
3936trash_or_delete_done_cb (GHashTable *debuting_uris,
3937 gboolean user_cancel,
3938 FMDirectoryView *view)
3939{
3940 if (user_cancel) {
3941 view->details->selection_was_removed = FALSE(0);
3942 }
3943}
3944
3945static void
3946trash_or_delete_files (GtkWindow *parent_window,
3947 const GList *files,
3948 gboolean delete_if_all_already_in_trash,
3949 FMDirectoryView *view)
3950{
3951 GList *locations;
3952 const GList *node;
3953
3954 locations = NULL((void*)0);
3955 for (node = files; node != NULL((void*)0); node = node->next) {
3956 locations = g_list_prepend (locations,
3957 caja_file_get_location ((CajaFile *) node->data));
3958 }
3959
3960 locations = g_list_reverse (locations);
3961
3962 caja_file_operations_trash_or_delete (locations,
3963 parent_window,
3964 (CajaDeleteCallback) trash_or_delete_done_cb,
3965 view);
3966 g_list_free_full (locations, g_object_unref);
3967}
3968
3969static gboolean
3970can_rename_file (FMDirectoryView *view, CajaFile *file)
3971{
3972 return caja_file_can_rename (file);
3973}
3974
3975static void
3976start_renaming_file (FMDirectoryView *view,
3977 CajaFile *file,
3978 gboolean select_all)
3979{
3980 if (file != NULL((void*)0)) {
3981 fm_directory_view_select_file (view, file);
3982 }
3983}
3984
3985typedef struct {
3986 FMDirectoryView *view;
3987 CajaFile *new_file;
3988} RenameData;
3989
3990static gboolean
3991delayed_rename_file_hack_callback (RenameData *data)
3992{
3993 FMDirectoryView *view;
3994 CajaFile *new_file;
3995
3996 view = data->view;
3997 new_file = data->new_file;
3998
3999 if (view->details->window != NULL((void*)0) &&
4000 view->details->active) {
4001 EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view, start_renaming_file, (view, new_file, FALSE))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->start_renaming_file
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->start_renaming_file) (view, new_file, (0)); } } while
(0)
;
4002 fm_directory_view_reveal_selection (view);
4003 }
4004
4005 return FALSE(0);
4006}
4007
4008static void
4009delayed_rename_file_hack_removed (RenameData *data)
4010{
4011 g_object_unref (data->view);
4012 caja_file_unref (data->new_file);
4013 g_free (data);
4014}
4015
4016
4017static void
4018rename_file (FMDirectoryView *view, CajaFile *new_file)
4019{
4020 /* HACK!!!!
4021 This is a work around bug in listview. After the rename is
4022 enabled we will get file changes due to info about the new
4023 file being read, which will cause the model to change. When
4024 the model changes GtkTreeView clears the editing. This hack just
4025 delays editing for some time to try to avoid this problem.
4026 A major problem is that the selection of the row causes us
4027 to load the slow mimetype for the file, which leads to a
4028 file_changed. So, before we delay we select the row.
4029 */
4030 if (FM_IS_LIST_VIEW (view)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view)); GType __t = (fm_list_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; }))))
) {
4031 RenameData *data;
4032
4033 fm_directory_view_select_file (view, new_file);
4034
4035 data = g_new (RenameData, 1)(RenameData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (RenameData); 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; }))
;
4036 data->view = g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view));
4037 data->new_file = caja_file_ref (new_file);
4038 if (view->details->delayed_rename_file_id != 0) {
4039 g_source_remove (view->details->delayed_rename_file_id);
4040 }
4041 view->details->delayed_rename_file_id =
4042 g_timeout_add_full (G_PRIORITY_DEFAULT0,
4043 100, (GSourceFunc)delayed_rename_file_hack_callback,
4044 data, (GDestroyNotify) delayed_rename_file_hack_removed);
4045
4046 return;
4047 }
4048
4049 /* no need to select because start_renaming_file selects
4050 * fm_directory_view_select_file (view, new_file);
4051 */
4052 EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view, start_renaming_file, (view, new_file, FALSE))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->start_renaming_file
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->start_renaming_file) (view, new_file, (0)); } } while
(0)
;
4053 fm_directory_view_reveal_selection (view);
4054}
4055
4056static void
4057reveal_newly_added_folder (FMDirectoryView *view, CajaFile *new_file,
4058 CajaDirectory *directory, GFile *target_location)
4059{
4060 GFile *location;
4061
4062 location = caja_file_get_location (new_file);
4063 if (g_file_equal (location, target_location)) {
4064 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) (reveal_newly_added_folder))), ((void *) target_location
))
4065 G_CALLBACK (reveal_newly_added_folder),g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (reveal_newly_added_folder))), ((void *) target_location
))
4066 (void *) target_location)g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (reveal_newly_added_folder))), ((void *) target_location
))
;
4067 rename_file (view, new_file);
4068 }
4069 g_object_unref (location);
4070}
4071
4072typedef struct {
4073 FMDirectoryView *directory_view;
4074 GHashTable *added_locations;
4075} NewFolderData;
4076
4077
4078static void
4079track_newly_added_locations (FMDirectoryView *view, CajaFile *new_file,
4080 CajaDirectory *directory, gpointer user_data)
4081{
4082 NewFolderData *data;
4083
4084 data = user_data;
4085
4086 g_hash_table_insert (data->added_locations, caja_file_get_location (new_file), NULL((void*)0));
4087}
4088
4089static void
4090new_folder_done (GFile *new_folder, gpointer user_data)
4091{
4092 FMDirectoryView *directory_view;
4093 CajaFile *file;
4094 char screen_string[32];
4095 GdkScreen *screen;
4096 NewFolderData *data;
4097
4098 data = (NewFolderData *)user_data;
4099
4100 directory_view = data->directory_view;
4101
4102 if (directory_view == NULL((void*)0)) {
4103 goto fail;
4104 }
4105
4106 g_signal_handlers_disconnect_by_func (directory_view,g_signal_handlers_disconnect_matched ((directory_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (track_newly_added_locations))), ((void *) data
))
4107 G_CALLBACK (track_newly_added_locations),g_signal_handlers_disconnect_matched ((directory_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (track_newly_added_locations))), ((void *) data
))
4108 (void *) data)g_signal_handlers_disconnect_matched ((directory_view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (track_newly_added_locations))), ((void *) data
))
;
4109
4110 if (new_folder == NULL((void*)0)) {
4111 goto fail;
4112 }
4113
4114 screen = gtk_widget_get_screen (GTK_WIDGET (directory_view)((((GtkWidget*) (void *) ((directory_view))))));
4115 g_snprintf (screen_string, sizeof (screen_string), "%d", gdk_x11_screen_get_screen_number (screen));
4116
4117
4118 file = caja_file_get (new_folder);
4119 caja_file_set_metadata
4120 (file, CAJA_METADATA_KEY_SCREEN"screen",
4121 NULL((void*)0),
4122 screen_string);
4123
4124 if (g_hash_table_lookup_extended (data->added_locations, new_folder, NULL((void*)0), NULL((void*)0))) {
4125 /* The file was already added */
4126 rename_file (directory_view, file);
4127 } else {
4128 /* We need to run after the default handler adds the folder we want to
4129 * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
4130 * must use connect_after.
4131 */
4132 g_signal_connect_data (directory_view,
4133 "add_file",
4134 G_CALLBACK (reveal_newly_added_folder)((GCallback) (reveal_newly_added_folder)),
4135 g_object_ref (new_folder)((__typeof__ (new_folder)) (g_object_ref) (new_folder)),
4136 (GClosureNotify)g_object_unref,
4137 G_CONNECT_AFTER);
4138 }
4139 caja_file_unref (file);
4140
4141 fail:
4142 g_hash_table_destroy (data->added_locations);
4143 eel_remove_weak_pointer (&data->directory_view);
4144 g_free (data);
4145}
4146
4147
4148static NewFolderData *
4149new_folder_data_new (FMDirectoryView *directory_view)
4150{
4151 NewFolderData *data;
4152
4153 data = g_new (NewFolderData, 1)(NewFolderData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (NewFolderData); 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; }))
;
4154 data->directory_view = directory_view;
4155 data->added_locations = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal,
4156 g_object_unref, NULL((void*)0));
4157 eel_add_weak_pointer (&data->directory_view);
4158
4159 return data;
4160}
4161
4162static GdkPoint *
4163context_menu_to_file_operation_position (FMDirectoryView *directory_view)
4164{
4165 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (directory_view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_239
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory_view)); GType __t = (fm_directory_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_239 = 1; else _g_boolean_var_239 =
0; _g_boolean_var_239; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (directory_view)"
); return (((void*)0)); } } while (0)
;
4166
4167 if (fm_directory_view_using_manual_layout (directory_view)
4168 && directory_view->details->context_menu_position.x >= 0
4169 && directory_view->details->context_menu_position.y >= 0) {
4170 EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, directory_view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((directory_view)))->g_class))))))))
)->widget_to_file_operation_position != ((void*)0)) { (* (
(((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((directory_view)))->g_class)))))))))->widget_to_file_operation_position
) (directory_view, &directory_view->details->context_menu_position
); } } while (0)
4171 widget_to_file_operation_position,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((directory_view)))->g_class))))))))
)->widget_to_file_operation_position != ((void*)0)) { (* (
(((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((directory_view)))->g_class)))))))))->widget_to_file_operation_position
) (directory_view, &directory_view->details->context_menu_position
); } } while (0)
4172 (directory_view, &directory_view->details->context_menu_position))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((directory_view)))->g_class))))))))
)->widget_to_file_operation_position != ((void*)0)) { (* (
(((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((directory_view)))->g_class)))))))))->widget_to_file_operation_position
) (directory_view, &directory_view->details->context_menu_position
); } } while (0)
;
4173 return &directory_view->details->context_menu_position;
4174 } else {
4175 return NULL((void*)0);
4176 }
4177}
4178
4179static void
4180update_context_menu_position_from_event (FMDirectoryView *view,
4181 GdkEventButton *event)
4182{
4183 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_240
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_240
= 1; else _g_boolean_var_240 = 0; _g_boolean_var_240; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
4184
4185 if (event != NULL((void*)0)) {
4186 view->details->context_menu_position.x = event->x;
4187 view->details->context_menu_position.y = event->y;
4188 } else {
4189 view->details->context_menu_position.x = -1;
4190 view->details->context_menu_position.y = -1;
4191 }
4192}
4193
4194void
4195fm_directory_view_new_folder (FMDirectoryView *directory_view)
4196{
4197 char *parent_uri;
4198 NewFolderData *data;
4199 GdkPoint *pos;
4200
4201 data = new_folder_data_new (directory_view);
4202
4203 g_signal_connect_data (directory_view,
4204 "add_file",
4205 G_CALLBACK (track_newly_added_locations)((GCallback) (track_newly_added_locations)),
4206 data,
4207 (GClosureNotify)NULL((void*)0),
4208 G_CONNECT_AFTER);
4209
4210 pos = context_menu_to_file_operation_position (directory_view);
4211
4212 parent_uri = fm_directory_view_get_backing_uri (directory_view);
4213 caja_file_operations_new_folder (GTK_WIDGET (directory_view)((((GtkWidget*) (void *) ((directory_view))))),
4214 pos, parent_uri,
4215 new_folder_done, data);
4216
4217 g_free (parent_uri);
4218}
4219
4220static NewFolderData *
4221setup_new_folder_data (FMDirectoryView *directory_view)
4222{
4223 NewFolderData *data;
4224
4225 data = new_folder_data_new (directory_view);
4226
4227 g_signal_connect_data (directory_view,
4228 "add_file",
4229 G_CALLBACK (track_newly_added_locations)((GCallback) (track_newly_added_locations)),
4230 data,
4231 (GClosureNotify)NULL((void*)0),
4232 G_CONNECT_AFTER);
4233
4234 return data;
4235}
4236
4237static void
4238fm_directory_view_new_file_with_initial_contents (FMDirectoryView *directory_view,
4239 const char *parent_uri,
4240 const char *filename,
4241 const char *initial_contents,
4242 int length,
4243 GdkPoint *pos)
4244{
4245 NewFolderData *data;
4246
4247 g_assert (parent_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_241
; if (parent_uri != ((void*)0)) _g_boolean_var_241 = 1; else _g_boolean_var_241
= 0; _g_boolean_var_241; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 4247, ((const char*) (
__func__)), "parent_uri != NULL"); } while (0)
;
4248
4249 data = setup_new_folder_data (directory_view);
4250
4251 if (pos == NULL((void*)0)) {
4252 pos = context_menu_to_file_operation_position (directory_view);
4253 }
4254
4255 caja_file_operations_new_file (GTK_WIDGET (directory_view)((((GtkWidget*) (void *) ((directory_view))))),
4256 pos, parent_uri, filename,
4257 initial_contents, length,
4258 new_folder_done, data);
4259}
4260
4261void
4262fm_directory_view_new_file (FMDirectoryView *directory_view,
4263 const char *parent_uri,
4264 CajaFile *source)
4265{
4266 GdkPoint *pos;
4267 NewFolderData *data;
4268 char *source_uri;
4269 char *container_uri;
4270
4271 container_uri = NULL((void*)0);
4272 if (parent_uri == NULL((void*)0)) {
4273 container_uri = fm_directory_view_get_backing_uri (directory_view);
4274 g_assert (container_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_242
; if (container_uri != ((void*)0)) _g_boolean_var_242 = 1; else
_g_boolean_var_242 = 0; _g_boolean_var_242; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 4274, ((const char*) (
__func__)), "container_uri != NULL"); } while (0)
;
4275 }
4276
4277 if (source == NULL((void*)0)) {
4278 fm_directory_view_new_file_with_initial_contents (directory_view,
4279 parent_uri != NULL((void*)0) ? parent_uri : container_uri,
4280 NULL((void*)0),
4281 NULL((void*)0),
4282 0,
4283 NULL((void*)0));
4284 g_free (container_uri);
4285 return;
4286 }
4287
4288 g_return_if_fail (caja_file_is_local (source))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_243
; if (caja_file_is_local (source)) _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__
)), "caja_file_is_local (source)"); return; } } while (0)
;
4289
4290 pos = context_menu_to_file_operation_position (directory_view);
4291
4292 data = setup_new_folder_data (directory_view);
4293
4294 source_uri = caja_file_get_uri (source);
4295
4296 caja_file_operations_new_file_from_template (GTK_WIDGET (directory_view)((((GtkWidget*) (void *) ((directory_view))))),
4297 pos,
4298 parent_uri != NULL((void*)0) ? parent_uri : container_uri,
4299 NULL((void*)0),
4300 source_uri,
4301 new_folder_done, data);
4302
4303 g_free (source_uri);
4304 g_free (container_uri);
4305}
4306
4307/* handle the open command */
4308
4309static void
4310open_one_in_new_window (gpointer data, gpointer callback_data)
4311{
4312 g_assert (CAJA_IS_FILE (data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = (caja_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_244
= 1; else _g_boolean_var_244 = 0; _g_boolean_var_244; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 4312, ((const char*) (__func__)), "CAJA_IS_FILE (data)"); }
while (0)
;
4313 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_245
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_245 = 1; else _g_boolean_var_245 =
0; _g_boolean_var_245; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 4313, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
4314
4315 fm_directory_view_activate_file (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))),
4316 CAJA_FILE (data)((((CajaFile*) (void *) ((data))))),
4317 CAJA_WINDOW_OPEN_IN_NAVIGATION,
4318 0);
4319}
4320
4321static void
4322open_one_in_folder_window (gpointer data, gpointer callback_data)
4323{
4324 g_assert (CAJA_IS_FILE (data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_246
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = (caja_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_246
= 1; else _g_boolean_var_246 = 0; _g_boolean_var_246; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 4324, ((const char*) (__func__)), "CAJA_IS_FILE (data)"); }
while (0)
;
4325 g_assert (FM_IS_DIRECTORY_VIEW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_247
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_directory_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_247 = 1; else _g_boolean_var_247 =
0; _g_boolean_var_247; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 4325, ((const char*) (
__func__)), "FM_IS_DIRECTORY_VIEW (callback_data)"); } while (
0)
;
4326
4327 fm_directory_view_activate_file (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))),
4328 CAJA_FILE (data)((((CajaFile*) (void *) ((data))))),
4329 CAJA_WINDOW_OPEN_IN_SPATIAL,
4330 0);
4331}
4332
4333CajaFile *
4334fm_directory_view_get_directory_as_file (FMDirectoryView *view)
4335{
4336 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_248
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_248
= 1; else _g_boolean_var_248 = 0; _g_boolean_var_248; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 4336, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
4337
4338 return view->details->directory_as_file;
4339}
4340
4341static void
4342open_with_launch_application_callback (GtkAction *action,
4343 gpointer callback_data)
4344{
4345 ApplicationLaunchParameters *launch_parameters;
4346
4347 launch_parameters = (ApplicationLaunchParameters *) callback_data;
4348 caja_launch_application
4349 (launch_parameters->application,
4350 launch_parameters->files,
4351 fm_directory_view_get_containing_window (launch_parameters->directory_view));
4352}
4353
4354static void
4355open_parent_folder_callback (GtkAction *action,
4356 gpointer callback_data)
4357{
4358 gchar *uri;
4359
4360 uri = (gchar *) callback_data;
4361 g_app_info_launch_default_for_uri (uri, NULL((void*)0), NULL((void*)0));
4362}
4363
4364static char *
4365escape_action_name (const char *action_name,
4366 const char *prefix)
4367{
4368 GString *s;
4369
4370 if (action_name == NULL((void*)0)) {
4371 return NULL((void*)0);
4372 }
4373
4374 s = g_string_new (prefix);
4375
4376 while (*action_name != 0) {
4377 switch (*action_name) {
4378 case '\\':
4379 g_string_append (s, "\\\\")(__builtin_constant_p ("\\\\") ? __extension__ ({ const char *
const __val = ("\\\\"); g_string_append_len_inline (s, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_249;
if (__val != ((void*)0)) _g_boolean_var_249 = 1; else _g_boolean_var_249
= 0; _g_boolean_var_249; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "\\\\", (gssize) -1))
;
4380 break;
4381 case '/':
4382 g_string_append (s, "\\s")(__builtin_constant_p ("\\s") ? __extension__ ({ const char *
const __val = ("\\s"); g_string_append_len_inline (s, __val,
(__builtin_expect (__extension__ ({ int _g_boolean_var_250; if
(__val != ((void*)0)) _g_boolean_var_250 = 1; else _g_boolean_var_250
= 0; _g_boolean_var_250; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "\\s", (gssize) -1))
;
4383 break;
4384 case '&':
4385 g_string_append (s, "\\a")(__builtin_constant_p ("\\a") ? __extension__ ({ const char *
const __val = ("\\a"); g_string_append_len_inline (s, __val,
(__builtin_expect (__extension__ ({ int _g_boolean_var_251; if
(__val != ((void*)0)) _g_boolean_var_251 = 1; else _g_boolean_var_251
= 0; _g_boolean_var_251; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "\\a", (gssize) -1))
;
4386 break;
4387 case '"':
4388 g_string_append (s, "\\q")(__builtin_constant_p ("\\q") ? __extension__ ({ const char *
const __val = ("\\q"); g_string_append_len_inline (s, __val,
(__builtin_expect (__extension__ ({ int _g_boolean_var_252; if
(__val != ((void*)0)) _g_boolean_var_252 = 1; else _g_boolean_var_252
= 0; _g_boolean_var_252; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "\\q", (gssize) -1))
;
4389 break;
4390 default:
4391 g_string_append_c (s, *action_name)g_string_append_c_inline (s, *action_name);
4392 }
4393
4394 action_name ++;
4395 }
4396 return g_string_free (s, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((s), (
(0))) : g_string_free_and_steal (s)) : (g_string_free) ((s), (
(0))))
;
4397}
4398
4399static char *
4400escape_action_path (const char *action_path)
4401{
4402 GString *s;
4403
4404 if (action_path == NULL((void*)0)) {
4405 return NULL((void*)0);
4406 }
4407
4408 s = g_string_sized_new (strlen (action_path) + 2);
4409
4410 while (*action_path != 0) {
4411 switch (*action_path) {
4412 case '\\':
4413 g_string_append (s, "\\\\")(__builtin_constant_p ("\\\\") ? __extension__ ({ const char *
const __val = ("\\\\"); g_string_append_len_inline (s, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_253;
if (__val != ((void*)0)) _g_boolean_var_253 = 1; else _g_boolean_var_253
= 0; _g_boolean_var_253; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "\\\\", (gssize) -1))
;
4414 break;
4415 case '&':
4416 g_string_append (s, "\\a")(__builtin_constant_p ("\\a") ? __extension__ ({ const char *
const __val = ("\\a"); g_string_append_len_inline (s, __val,
(__builtin_expect (__extension__ ({ int _g_boolean_var_254; if
(__val != ((void*)0)) _g_boolean_var_254 = 1; else _g_boolean_var_254
= 0; _g_boolean_var_254; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "\\a", (gssize) -1))
;
4417 break;
4418 case '"':
4419 g_string_append (s, "\\q")(__builtin_constant_p ("\\q") ? __extension__ ({ const char *
const __val = ("\\q"); g_string_append_len_inline (s, __val,
(__builtin_expect (__extension__ ({ int _g_boolean_var_255; if
(__val != ((void*)0)) _g_boolean_var_255 = 1; else _g_boolean_var_255
= 0; _g_boolean_var_255; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(s, "\\q", (gssize) -1))
;
4420 break;
4421 default:
4422 g_string_append_c (s, *action_path)g_string_append_c_inline (s, *action_path);
4423 }
4424
4425 action_path ++;
4426 }
4427 return g_string_free (s, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((s), (
(0))) : g_string_free_and_steal (s)) : (g_string_free) ((s), (
(0))))
;
4428}
4429
4430
4431static void
4432add_submenu (GtkUIManager *ui_manager,
4433 GtkActionGroup *action_group,
4434 guint merge_id,
4435 const char *parent_path,
4436 const char *uri,
4437 const char *label,
4438 cairo_surface_t *surface,
4439 gboolean add_action)
4440{
4441 if (parent_path != NULL((void*)0)) {
4442 char *escaped_label;
4443 char *action_name;
4444 char *submenu_name;
4445 char *escaped_submenu_name;
4446
4447 action_name = escape_action_name (uri, "submenu_");
4448 submenu_name = g_path_get_basename (uri);
4449 escaped_submenu_name = escape_action_path (submenu_name);
4450 escaped_label = eel_str_double_underscores (label);
4451
4452 if (add_action) {
4453 GtkAction *action;
4454
4455 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4456 action = gtk_action_new (action_name,
4457 escaped_label,
4458 NULL((void*)0),
4459 NULL((void*)0));
4460 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4461 if (surface != NULL((void*)0)) {
4462 g_object_set_data_full (G_OBJECT (action)((((GObject*) (void *) ((action))))), "menu-icon",
4463 cairo_surface_reference (surface),
4464 (GDestroyNotify)cairo_surface_destroy);
4465 }
4466
4467 g_object_set (action, "hide-if-empty", FALSE(0), NULL((void*)0));
4468
4469 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4470 gtk_action_group_add_action (action_group,
4471 action);
4472 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4473 g_object_unref (action);
4474 }
4475
4476 gtk_ui_manager_add_ui (ui_manager,
4477 merge_id,
4478 parent_path,
4479 escaped_submenu_name,
4480 action_name,
4481 GTK_UI_MANAGER_MENU,
4482 FALSE(0));
4483 g_free (action_name);
4484 g_free (escaped_label);
4485 g_free (submenu_name);
4486 g_free (escaped_submenu_name);
4487 }
4488}
4489
4490static void
4491add_application_to_open_with_menu (FMDirectoryView *view,
4492 GAppInfo *application,
4493 GList *files,
4494 int index,
4495 const char *menu_placeholder,
4496 const char *popup_placeholder,
4497 const gboolean submenu)
4498{
4499 ApplicationLaunchParameters *launch_parameters;
4500 char *tip;
4501 char *label;
4502 char *action_name;
4503 char *escaped_app;
4504 char *path;
4505 GtkAction *action;
4506 GIcon *app_icon;
4507 GtkWidget *menuitem;
4508
4509 launch_parameters = application_launch_parameters_new
4510 (application, files, view);
4511 escaped_app = eel_str_double_underscores (g_app_info_get_display_name (application));
4512 if (submenu)
4513 label = g_strdup_printf ("%s", escaped_app);
4514 else
4515 label = g_strdup_printf (_("Open With %s")dcgettext (((void*)0), "Open With %s", 5), escaped_app);
4516
4517 tip = g_strdup_printf (ngettext ("Use \"%s\" to open the selected item",dcngettext (((void*)0), "Use \"%s\" to open the selected item"
, "Use \"%s\" to open the selected items", g_list_length (files
), 5)
4518 "Use \"%s\" to open the selected items",dcngettext (((void*)0), "Use \"%s\" to open the selected item"
, "Use \"%s\" to open the selected items", g_list_length (files
), 5)
4519 g_list_length (files))dcngettext (((void*)0), "Use \"%s\" to open the selected item"
, "Use \"%s\" to open the selected items", g_list_length (files
), 5)
,
4520 escaped_app);
4521 g_free (escaped_app);
4522
4523 action_name = g_strdup_printf ("open_with_%d", index);
4524
4525 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4526 action = gtk_action_new (action_name,
4527 label,
4528 tip,
4529 NULL((void*)0));
4530 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4531
4532 app_icon = g_app_info_get_icon (application);
4533 if (app_icon != NULL((void*)0)) {
4534 g_object_ref (app_icon)((__typeof__ (app_icon)) (g_object_ref) (app_icon));
4535 } else {
4536 app_icon = g_themed_icon_new ("application-x-executable");
4537 }
4538
4539 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4540 gtk_action_set_gicon (action, app_icon);
4541 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4542 g_object_unref (app_icon);
4543
4544 g_signal_connect_data (action, "activate",
4545 G_CALLBACK (open_with_launch_application_callback)((GCallback) (open_with_launch_application_callback)),
4546 launch_parameters,
4547 (GClosureNotify)application_launch_parameters_free, 0);
4548
4549 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4550 gtk_action_group_add_action (view->details->open_with_action_group,
4551 action);
4552 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4553 g_object_unref (action);
4554
4555 gtk_ui_manager_add_ui (caja_window_info_get_ui_manager (view->details->window),
4556 view->details->open_with_merge_id,
4557 menu_placeholder,
4558 action_name,
4559 action_name,
4560 GTK_UI_MANAGER_MENUITEM,
4561 FALSE(0));
4562
4563 path = g_strdup_printf ("%s/%s", menu_placeholder, action_name);
4564 menuitem = gtk_ui_manager_get_widget (
4565 caja_window_info_get_ui_manager (view->details->window),
4566 path);
4567 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem)((((GtkImageMenuItem*) (void *) ((menuitem))))), TRUE(!(0)));
4568 g_free (path);
4569
4570 gtk_ui_manager_add_ui (caja_window_info_get_ui_manager (view->details->window),
4571 view->details->open_with_merge_id,
4572 popup_placeholder,
4573 action_name,
4574 action_name,
4575 GTK_UI_MANAGER_MENUITEM,
4576 FALSE(0));
4577
4578 path = g_strdup_printf ("%s/%s", popup_placeholder, action_name);
4579 menuitem = gtk_ui_manager_get_widget (
4580 caja_window_info_get_ui_manager (view->details->window),
4581 path);
4582 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem)((((GtkImageMenuItem*) (void *) ((menuitem))))), TRUE(!(0)));
4583
4584 g_free (path);
4585 g_free (action_name);
4586 g_free (label);
4587 g_free (tip);
4588}
4589
4590static void
4591add_parent_folder_to_open_menu (FMDirectoryView *view,
4592 GList *files,
4593 const char *menu_placeholder,
4594 const char *popup_placeholder)
4595{
4596 CajaFile *file;
4597 gchar *uri;
4598 char *tip;
4599 char *label;
4600 char *action_name;
4601 char *path;
4602 GtkAction *action;
4603 GtkWidget *menuitem;
4604
4605 file = g_list_first(files)->data;
4606
4607 if (caja_file_is_directory (file))
4608 return;
4609
4610 uri = caja_file_get_parent_uri (file);
4611
4612 label = g_strdup (_("Open parent location"))g_strdup_inline (dcgettext (((void*)0), "Open parent location"
, 5))
;
4613 tip = g_strdup (_("Open parent location for the selected item"))g_strdup_inline (dcgettext (((void*)0), "Open parent location for the selected item"
, 5))
;
4614 action_name = g_strdup ("open_location")g_strdup_inline ("open_location");
4615
4616 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4617 action = gtk_action_new (action_name,
4618 label,
4619 tip,
4620 NULL((void*)0));
4621
4622 gtk_action_set_icon_name (action, "folder");
4623 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4624
4625 g_signal_connect_data (action, "activate",
4626 G_CALLBACK (open_parent_folder_callback)((GCallback) (open_parent_folder_callback)),
4627 uri, (GClosureNotify)g_free, 0);
4628
4629 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4630 gtk_action_group_add_action (view->details->open_with_action_group,
4631 action);
4632 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4633 g_object_unref (action);
4634
4635 gtk_ui_manager_add_ui (caja_window_info_get_ui_manager (view->details->window),
4636 view->details->open_with_merge_id,
4637 menu_placeholder,
4638 action_name,
4639 action_name,
4640 GTK_UI_MANAGER_MENUITEM,
4641 FALSE(0));
4642
4643 path = g_strdup_printf ("%s/%s", menu_placeholder, action_name);
4644 menuitem = gtk_ui_manager_get_widget (
4645 caja_window_info_get_ui_manager (view->details->window),
4646 path);
4647 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem)((((GtkImageMenuItem*) (void *) ((menuitem))))), TRUE(!(0)));
4648 g_free (path);
4649
4650 gtk_ui_manager_add_ui (caja_window_info_get_ui_manager (view->details->window),
4651 view->details->open_with_merge_id,
4652 popup_placeholder,
4653 action_name,
4654 action_name,
4655 GTK_UI_MANAGER_MENUITEM,
4656 FALSE(0));
4657
4658 path = g_strdup_printf ("%s/%s", popup_placeholder, action_name);
4659 menuitem = gtk_ui_manager_get_widget (
4660 caja_window_info_get_ui_manager (view->details->window),
4661 path);
4662 gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem)((((GtkImageMenuItem*) (void *) ((menuitem))))), TRUE(!(0)));
4663
4664 g_free (path);
4665 g_free (action_name);
4666 g_free (label);
4667 g_free (tip);
4668}
4669
4670static void
4671get_x_content_async_callback (char **content,
4672 gpointer user_data)
4673{
4674 FMDirectoryView *view;
4675
4676 view = FM_DIRECTORY_VIEW (user_data)((((FMDirectoryView*) (void *) ((user_data)))));
4677
4678 if (view->details->window != NULL((void*)0)) {
4679 schedule_update_menus (view);
4680 }
4681 g_object_unref (view);
4682}
4683
4684static void
4685add_x_content_apps (FMDirectoryView *view, CajaFile *file, GList **applications)
4686{
4687 GMount *mount;
4688 char **x_content_types;
4689
4690 g_return_if_fail (applications != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_256
; if (applications != ((void*)0)) _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__
)), "applications != NULL"); return; } } while (0)
;
4691
4692 mount = caja_file_get_mount (file);
4693
4694 if (mount == NULL((void*)0)) {
4695 return;
4696 }
4697
4698 x_content_types = caja_autorun_get_cached_x_content_types_for_mount (mount);
4699 if (x_content_types != NULL((void*)0)) {
4700 unsigned int n;
4701
4702 for (n = 0; x_content_types[n] != NULL((void*)0); n++) {
4703 char *x_content_type = x_content_types[n];
4704 GList *app_info_for_x_content_type;
4705
4706 app_info_for_x_content_type = g_app_info_get_all_for_type (x_content_type);
4707 *applications = g_list_concat (*applications, app_info_for_x_content_type);
4708 }
4709 g_strfreev (x_content_types);
4710 } else {
4711 caja_autorun_get_x_content_types_for_mount_async (mount,
4712 get_x_content_async_callback,
4713 NULL((void*)0),
4714 g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)));
4715
4716 }
4717
4718 g_object_unref (mount);
4719}
4720
4721static void
4722reset_open_with_menu (FMDirectoryView *view, GList *selection)
4723{
4724 GList *applications, *node;
4725 gboolean submenu_visible, filter_default;
4726 int num_applications;
4727 int index;
4728 gboolean other_applications_visible;
4729 gboolean open_with_chooser_visible;
4730 GtkUIManager *ui_manager;
4731 GtkAction *action;
4732 GAppInfo *default_app;
4733 char *uri;
4734
4735 /* Clear any previous inserted items in the applications and viewers placeholders */
4736
4737 ui_manager = caja_window_info_get_ui_manager (view->details->window);
4738 caja_ui_unmerge_ui (ui_manager,
4739 &view->details->open_with_merge_id,
4740 &view->details->open_with_action_group);
4741
4742 caja_ui_prepare_merge_ui (ui_manager,
4743 "OpenWithGroup",
4744 &view->details->open_with_merge_id,
4745 &view->details->open_with_action_group);
4746
4747 num_applications = 0;
Value stored to 'num_applications' is never read
4748
4749 other_applications_visible = (selection != NULL((void*)0));
4750 filter_default = (selection != NULL((void*)0));
4751
4752 default_app = NULL((void*)0);
4753 if (filter_default) {
4754 default_app = caja_mime_get_default_application_for_files (selection);
4755 }
4756
4757 applications = NULL((void*)0);
4758 if (other_applications_visible) {
4759 applications = caja_mime_get_applications_for_files (selection);
4760 }
4761
4762 if (g_list_length (selection) == 1) {
4763 add_x_content_apps (view, CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data))))), &applications);
4764 }
4765
4766
4767 num_applications = g_list_length (applications);
4768
4769 if (file_list_all_are_folders (selection)) {
4770 submenu_visible = (num_applications > 2);
4771 } else {
4772 submenu_visible = (num_applications > 3);
4773 }
4774
4775 for (node = applications, index = 0; node != NULL((void*)0); node = node->next, index++) {
4776 GAppInfo *application;
4777 char *menu_path;
4778 char *popup_path;
4779
4780 application = node->data;
4781
4782 if (default_app != NULL((void*)0) && g_app_info_equal (default_app, application)) {
4783 continue;
4784 }
4785
4786 if (submenu_visible) {
4787 menu_path = FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER"/MenuBar/File/Open Placeholder/Open With/Applications Placeholder";
4788 popup_path = FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER"/selection/Open Placeholder/Open With/Applications Placeholder";
4789 } else {
4790 menu_path = FM_DIRECTORY_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER"/MenuBar/File/Open Placeholder/Applications Placeholder";
4791 popup_path = FM_DIRECTORY_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER"/selection/Open Placeholder/Applications Placeholder";
4792 }
4793
4794 gtk_ui_manager_add_ui (caja_window_info_get_ui_manager (view->details->window),
4795 view->details->open_with_merge_id,
4796 menu_path,
4797 "separator",
4798 NULL((void*)0),
4799 GTK_UI_MANAGER_SEPARATOR,
4800 FALSE(0));
4801
4802 add_application_to_open_with_menu (view,
4803 node->data,
4804 selection,
4805 index,
4806 menu_path, popup_path, submenu_visible);
4807
4808 }
4809 g_list_free_full (applications, g_object_unref);
4810 if (default_app != NULL((void*)0)) {
4811 g_object_unref (default_app);
4812 }
4813
4814 /* Show open parent folder action if we are in search mode */
4815 uri = fm_directory_view_get_uri (view);
4816 if (eel_uri_is_search (uri) && g_list_length (selection) == 1)
4817 add_parent_folder_to_open_menu (view,
4818 selection,
4819 FM_DIRECTORY_VIEW_MENU_PATH_OPEN"/MenuBar/File/Open Placeholder/Open",
4820 FM_DIRECTORY_VIEW_POPUP_PATH_OPEN"/selection/Open Placeholder/Open");
4821
4822 g_free (uri);
4823
4824 open_with_chooser_visible = other_applications_visible &&
4825 g_list_length (selection) == 1;
4826
4827 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
4828 if (submenu_visible) {
4829 action = gtk_action_group_get_action (view->details->dir_action_group,
4830 FM_ACTION_OTHER_APPLICATION1"OtherApplication1");
4831 gtk_action_set_visible (action, open_with_chooser_visible);
4832 action = gtk_action_group_get_action (view->details->dir_action_group,
4833 FM_ACTION_OTHER_APPLICATION2"OtherApplication2");
4834 gtk_action_set_visible (action, FALSE(0));
4835 } else {
4836 action = gtk_action_group_get_action (view->details->dir_action_group,
4837 FM_ACTION_OTHER_APPLICATION1"OtherApplication1");
4838 gtk_action_set_visible (action, FALSE(0));
4839 action = gtk_action_group_get_action (view->details->dir_action_group,
4840 FM_ACTION_OTHER_APPLICATION2"OtherApplication2");
4841 gtk_action_set_visible (action, open_with_chooser_visible);
4842 }
4843 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
4844}
4845
4846static GList *
4847get_all_extension_menu_items (GtkWidget *window,
4848 GList *selection)
4849{
4850 GList *items;
4851 GList *providers;
4852 GList *l;
4853
4854 providers = caja_extensions_get_for_type (CAJA_TYPE_MENU_PROVIDER(caja_menu_provider_get_type ()));
4855 items = NULL((void*)0);
4856
4857 for (l = providers; l != NULL((void*)0); l = l->next) {
4858 CajaMenuProvider *provider;
4859 GList *file_items;
4860
4861 provider = CAJA_MENU_PROVIDER (l->data)((((CajaMenuProvider*) (void *) ((l->data)))));
4862 file_items = caja_menu_provider_get_file_items (provider,
4863 window,
4864 selection);
4865 items = g_list_concat (items, file_items);
4866 }
4867
4868 caja_module_extension_list_free (providers);
4869
4870 return items;
4871}
4872
4873typedef struct
4874{
4875 CajaMenuItem *item;
4876 FMDirectoryView *view;
4877 GList *selection;
4878 GtkAction *action;
4879} ExtensionActionCallbackData;
4880
4881
4882static void
4883extension_action_callback_data_free (ExtensionActionCallbackData *data)
4884{
4885 g_object_unref (data->item);
4886 caja_file_list_free (data->selection);
4887
4888 g_free (data);
4889}
4890
4891static gboolean
4892search_in_menu_items (GList* items, const char *item_name)
4893{
4894 GList* list;
4895
4896 for (list = items; list != NULL((void*)0); list = list->next) {
4897 CajaMenu* menu;
4898 char *name;
4899
4900 g_object_get (list->data, "name", &name, NULL((void*)0));
4901 if (strcmp (name, item_name) == 0) {
4902 g_free (name);
4903 return TRUE(!(0));
4904 }
4905 g_free (name);
4906
4907 menu = NULL((void*)0);
4908 g_object_get (list->data, "menu", &menu, NULL((void*)0));
4909 if (menu != NULL((void*)0)) {
4910 gboolean ret;
4911 GList* submenus;
4912
4913 submenus = caja_menu_get_items (menu);
4914 ret = search_in_menu_items (submenus, item_name);
4915 caja_menu_item_list_free (submenus);
4916 g_object_unref (menu);
4917 if (ret) {
4918 return TRUE(!(0));
4919 }
4920 }
4921 }
4922 return FALSE(0);
4923}
4924
4925static void
4926extension_action_callback (GtkAction *action,
4927 gpointer callback_data)
4928{
4929 ExtensionActionCallbackData *data;
4930 char *item_name;
4931 gboolean is_valid;
4932 GList *l;
4933 GList *items;
4934
4935 data = callback_data;
4936
4937 /* Make sure the selected menu item is valid for the final sniffed
4938 * mime type */
4939 g_object_get (data->item, "name", &item_name, NULL((void*)0));
4940 items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (data->view)((((GtkWidget*) (void *) ((data->view)))))),
4941 data->selection);
4942
4943 is_valid = search_in_menu_items (items, item_name);
4944
4945 for (l = items; l != NULL((void*)0); l = l->next) {
4946 g_object_unref (l->data);
4947 }
4948 g_list_free (items);
4949
4950 g_free (item_name);
4951
4952 if (is_valid) {
4953 caja_menu_item_activate (data->item);
4954 }
4955}
4956
4957static cairo_surface_t *
4958get_menu_icon (const char *icon_name,
4959 GtkWidget *widget)
4960{
4961 CajaIconInfo *info;
4962 cairo_surface_t *surface;
4963 int size, scale;
4964
4965 size = caja_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU);
4966 scale = gtk_widget_get_scale_factor (widget);
4967
4968 if (g_path_is_absolute (icon_name)) {
4969 info = caja_icon_info_lookup_from_path (icon_name, size, scale);
4970 } else {
4971 info = caja_icon_info_lookup_from_name (icon_name, size, scale);
4972 }
4973 surface = caja_icon_info_get_surface_nodefault_at_size (info, size);
4974 g_object_unref (info);
4975
4976 return surface;
4977}
4978
4979static cairo_surface_t *
4980get_menu_icon_for_file (CajaFile *file,
4981 GtkWidget *widget)
4982{
4983 CajaIconInfo *info;
4984 cairo_surface_t *surface;
4985 int size, scale;
4986
4987 size = caja_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU);
4988 scale = gtk_widget_get_scale_factor (widget);
4989
4990 info = caja_file_get_icon (file, size, scale, 0);
4991 surface = caja_icon_info_get_surface_nodefault_at_size (info, size);
4992 g_object_unref (info);
4993
4994 return surface;
4995}
4996
4997static GtkAction *
4998add_extension_action_for_files (FMDirectoryView *view,
4999 CajaMenuItem *item,
5000 GList *files)
5001{
5002 char *name, *label, *tip, *icon;
5003 gboolean sensitive, priority;
5004 GtkAction *action;
5005 ExtensionActionCallbackData *data;
5006
5007 g_object_get (G_OBJECT (item)((((GObject*) (void *) ((item))))),
5008 "name", &name, "label", &label,
5009 "tip", &tip, "icon", &icon,
5010 "sensitive", &sensitive,
5011 "priority", &priority,
5012 NULL((void*)0));
5013
5014 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5015 action = gtk_action_new (name,
5016 label,
5017 tip,
5018 icon);
5019 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5020
5021 if (icon != NULL((void*)0)) {
5022 cairo_surface_t *surface;
5023
5024 surface = get_menu_icon (icon, GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
5025
5026 if (surface != NULL((void*)0)) {
5027 g_object_set_data_full (G_OBJECT (action)((((GObject*) (void *) ((action))))), "menu-icon",
5028 surface,
5029 (GDestroyNotify)cairo_surface_destroy);
5030 }
5031 }
5032
5033 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5034 gtk_action_set_sensitive (action, sensitive);
5035 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5036 g_object_set (action, "is-important", priority, NULL((void*)0));
5037
5038 data = g_new0 (ExtensionActionCallbackData, 1)(ExtensionActionCallbackData *) (__extension__ ({ gsize __n =
(gsize) (1); gsize __s = sizeof (ExtensionActionCallbackData
); 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; }))
;
5039 data->item = g_object_ref (item)((__typeof__ (item)) (g_object_ref) (item));
5040 data->view = view;
5041 data->selection = caja_file_list_copy (files);
5042 data->action = action;
5043
5044 g_signal_connect_data (action, "activate",
5045 G_CALLBACK (extension_action_callback)((GCallback) (extension_action_callback)),
5046 data,
5047 (GClosureNotify)extension_action_callback_data_free, 0);
5048
5049 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5050 gtk_action_group_add_action (view->details->extensions_menu_action_group,
5051 GTK_ACTION (action)((((GtkAction*) (void *) ((action))))));
5052 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5053 g_object_unref (action);
5054
5055 g_free (name);
5056 g_free (label);
5057 g_free (tip);
5058 g_free (icon);
5059
5060 return action;
5061}
5062
5063static void
5064add_extension_menu_items (FMDirectoryView *view,
5065 GList *files,
5066 GList *menu_items,
5067 const char *subdirectory)
5068{
5069 GtkUIManager *ui_manager;
5070 GList *l;
5071
5072 ui_manager = caja_window_info_get_ui_manager (view->details->window);
5073
5074 for (l = menu_items; l; l = l->next) {
5075 CajaMenuItem *item;
5076 CajaMenu *menu;
5077 GtkAction *action;
5078 const gchar *action_name;
5079 char *path;
5080
5081 item = CAJA_MENU_ITEM (l->data)((((CajaMenuItem*) (void *) ((l->data)))));
5082
5083 g_object_get (item, "menu", &menu, NULL((void*)0));
5084
5085 action = add_extension_action_for_files (view, item, files);
5086
5087 path = g_build_path ("/", FM_DIRECTORY_VIEW_POPUP_PATH_EXTENSION_ACTIONS"/selection/Extension Actions", subdirectory, NULL((void*)0));
5088 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5089 action_name = gtk_action_get_name (action);
5090 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5091
5092 gtk_ui_manager_add_ui (ui_manager,
5093 view->details->extensions_menu_merge_id,
5094 path,
5095 action_name,
5096 action_name,
5097 (menu != NULL((void*)0)) ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM,
5098 FALSE(0));
5099 g_free (path);
5100
5101 path = g_build_path ("/", FM_DIRECTORY_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER"/MenuBar/Edit/Extension Actions", subdirectory, NULL((void*)0));
5102 gtk_ui_manager_add_ui (ui_manager,
5103 view->details->extensions_menu_merge_id,
5104 path,
5105 action_name,
5106 action_name,
5107 (menu != NULL((void*)0)) ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM,
5108 FALSE(0));
5109 g_free (path);
5110
5111 /* recursively fill the menu */
5112 if (menu != NULL((void*)0)) {
5113 char *subdir;
5114 GList *children;
5115
5116 children = caja_menu_get_items (menu);
5117
5118 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5119 subdir = g_build_path ("/", subdirectory, gtk_action_get_name (action), NULL((void*)0));
5120 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5121 add_extension_menu_items (view,
5122 files,
5123 children,
5124 subdir);
5125
5126 caja_menu_item_list_free (children);
5127 g_free (subdir);
5128 }
5129 }
5130}
5131
5132static void
5133reset_extension_actions_menu (FMDirectoryView *view, GList *selection)
5134{
5135 GList *items;
5136 GtkUIManager *ui_manager;
5137
5138 /* Clear any previous inserted items in the extension actions placeholder */
5139 ui_manager = caja_window_info_get_ui_manager (view->details->window);
5140
5141 caja_ui_unmerge_ui (ui_manager,
5142 &view->details->extensions_menu_merge_id,
5143 &view->details->extensions_menu_action_group);
5144
5145 caja_ui_prepare_merge_ui (ui_manager,
5146 "DirExtensionsMenuGroup",
5147 &view->details->extensions_menu_merge_id,
5148 &view->details->extensions_menu_action_group);
5149
5150 items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))),
5151 selection);
5152 if (items != NULL((void*)0)) {
5153 add_extension_menu_items (view, selection, items, "");
5154
5155 g_list_free_full (items, g_object_unref);
5156 }
5157}
5158
5159static char *
5160change_to_view_directory (FMDirectoryView *view)
5161{
5162 char *path;
5163 char *old_path;
5164
5165 old_path = g_get_current_dir ();
5166
5167 path = get_view_directory (view);
5168
5169 /* FIXME: What to do about non-local directories? */
5170 if (path != NULL((void*)0)) {
5171 g_chdir (path);
5172 }
5173
5174 g_free (path);
5175
5176 return old_path;
5177}
5178
5179static char **
5180get_file_names_as_parameter_array (GList *selection,
5181 CajaDirectory *model)
5182{
5183 char **parameters;
5184 GList *node;
5185 GFile *model_location;
5186 int i;
5187 CajaFile *file = NULL((void*)0);
5188 GFile *file_location = NULL((void*)0);
5189
5190 if (model == NULL((void*)0)) {
5191 return NULL((void*)0);
5192 }
5193
5194 parameters = g_new (char *, g_list_length (selection) + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (g_list_length
(selection) + 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; }))
;
5195
5196 model_location = caja_directory_get_location (model);
5197
5198 for (node = selection, i = 0; node != NULL((void*)0); node = node->next, i++) {
5199 file = CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data)))));
5200
5201 if (!caja_file_is_local (file)) {
5202 parameters[i] = NULL((void*)0);
5203 g_strfreev (parameters);
5204 return NULL((void*)0);
5205 }
5206
5207 file_location = caja_file_get_location (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))));
5208 parameters[i] = g_file_get_relative_path (model_location, file_location);
5209 if (parameters[i] == NULL((void*)0)) {
5210 parameters[i] = g_file_get_path (file_location);
5211 }
5212 g_object_unref (file_location);
5213 }
5214
5215 g_object_unref (model_location);
5216
5217 parameters[i] = NULL((void*)0);
5218 return parameters;
5219}
5220
5221static char *
5222get_file_paths_or_uris_as_newline_delimited_string (GList *selection, gboolean get_paths)
5223{
5224 char *path;
5225 char *result;
5226 CajaDesktopLink *link;
5227 GString *expanding_string;
5228 GList *node;
5229 GFile *location;
5230
5231 expanding_string = g_string_new ("");
5232 for (node = selection; node != NULL((void*)0); node = node->next) {
5233 char *uri;
5234
5235 uri = NULL((void*)0);
5236
5237 if (CAJA_IS_DESKTOP_ICON_FILE (node->data)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(node->data)); GType __t = (caja_desktop_icon_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; }))))
) {
5238 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (node->data)((((CajaDesktopIconFile*) (void *) ((node->data))))));
5239 if (link != NULL((void*)0)) {
5240 location = caja_desktop_link_get_activation_location (link);
5241 uri = g_file_get_uri (location);
5242 g_object_unref (location);
5243 g_object_unref (G_OBJECT (link)((((GObject*) (void *) ((link))))));
5244 }
5245 } else {
5246 uri = caja_file_get_uri (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))));
5247 }
5248 if (uri == NULL((void*)0)) {
5249 continue;
5250 }
5251
5252 if (get_paths) {
5253 path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
5254 if (path != NULL((void*)0)) {
5255 g_string_append (expanding_string, path)(__builtin_constant_p (path) ? __extension__ ({ const char * const
__val = (path); g_string_append_len_inline (expanding_string
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_257
; if (__val != ((void*)0)) _g_boolean_var_257 = 1; else _g_boolean_var_257
= 0; _g_boolean_var_257; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(expanding_string, path, (gssize) -1))
;
5256 g_free (path);
5257 g_string_append (expanding_string, "\n")(__builtin_constant_p ("\n") ? __extension__ ({ const char * const
__val = ("\n"); g_string_append_len_inline (expanding_string
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_258
; if (__val != ((void*)0)) _g_boolean_var_258 = 1; else _g_boolean_var_258
= 0; _g_boolean_var_258; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(expanding_string, "\n", (gssize) -1))
;
5258 }
5259 } else {
5260 g_string_append (expanding_string, uri)(__builtin_constant_p (uri) ? __extension__ ({ const char * const
__val = (uri); g_string_append_len_inline (expanding_string,
__val, (__builtin_expect (__extension__ ({ int _g_boolean_var_259
; if (__val != ((void*)0)) _g_boolean_var_259 = 1; else _g_boolean_var_259
= 0; _g_boolean_var_259; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(expanding_string, uri, (gssize) -1))
;
5261 g_string_append (expanding_string, "\n")(__builtin_constant_p ("\n") ? __extension__ ({ const char * const
__val = ("\n"); g_string_append_len_inline (expanding_string
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_260
; if (__val != ((void*)0)) _g_boolean_var_260 = 1; else _g_boolean_var_260
= 0; _g_boolean_var_260; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(expanding_string, "\n", (gssize) -1))
;
5262 }
5263 g_free (uri);
5264 }
5265
5266 result = expanding_string->str;
5267 g_string_free (expanding_string, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((expanding_string
), ((0))) : g_string_free_and_steal (expanding_string)) : (g_string_free
) ((expanding_string), ((0))))
;
5268
5269 return result;
5270}
5271
5272static char *
5273get_file_paths_as_newline_delimited_string (GList *selection)
5274{
5275 return get_file_paths_or_uris_as_newline_delimited_string (selection, TRUE(!(0)));
5276}
5277
5278static char *
5279get_file_uris_as_newline_delimited_string (GList *selection)
5280{
5281 return get_file_paths_or_uris_as_newline_delimited_string (selection, FALSE(0));
5282}
5283
5284/* returns newly allocated strings for setting the environment variables */
5285static void
5286get_strings_for_environment_variables (FMDirectoryView *view, GList *selected_files,
5287 char **file_paths, char **uris, char **uri)
5288{
5289 char *directory_uri;
5290
5291 /* We need to check that the directory uri starts with "file:" since
5292 * caja_directory_is_local returns FALSE for nfs.
5293 */
5294 directory_uri = caja_directory_get_uri (view->details->model);
5295 if (eel_str_has_prefix (directory_uri, "file:") ||
5296 eel_uri_is_desktop (directory_uri) ||
5297 eel_uri_is_trash (directory_uri)) {
5298 *file_paths = get_file_paths_as_newline_delimited_string (selected_files);
5299 } else {
5300 *file_paths = g_strdup ("")g_strdup_inline ("");
5301 }
5302 g_free (directory_uri);
5303
5304 *uris = get_file_uris_as_newline_delimited_string (selected_files);
5305
5306 *uri = caja_directory_get_uri (view->details->model);
5307 if (eel_uri_is_desktop (*uri)) {
5308 g_free (*uri);
5309 *uri = caja_get_desktop_directory_uri ();
5310 }
5311}
5312
5313static FMDirectoryView *
5314get_directory_view_of_extra_pane (FMDirectoryView *view)
5315{
5316 CajaWindowSlotInfo *slot;
5317
5318 slot = caja_window_info_get_extra_slot (fm_directory_view_get_caja_window (view));
5319 if (slot != NULL((void*)0)) {
5320 CajaView *next_view;
5321
5322 next_view = caja_window_slot_info_get_current_view (slot);
5323
5324 if (FM_IS_DIRECTORY_VIEW (next_view)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(next_view)); GType __t = (fm_directory_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; }))))
) {
5325 return FM_DIRECTORY_VIEW (next_view)((((FMDirectoryView*) (void *) ((next_view)))));
5326 }
5327 }
5328 return NULL((void*)0);
5329}
5330
5331/*
5332 * Set up some environment variables that scripts can use
5333 * to take advantage of the current Caja state.
5334 */
5335static void set_script_environment_variables(FMDirectoryView* view, GList* selected_files)
5336{
5337 char* file_paths;
5338 char* uris;
5339 char* uri;
5340 char* geometry_string;
5341 FMDirectoryView* next_view;
5342
5343 get_strings_for_environment_variables(view, selected_files, &file_paths, &uris, &uri);
5344
5345 g_setenv("CAJA_SCRIPT_SELECTED_FILE_PATHS", file_paths, TRUE(!(0)));
5346 g_setenv("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS", file_paths, TRUE(!(0))); // compatibilidad GNOME
5347
5348 g_free(file_paths);
5349
5350 g_setenv("CAJA_SCRIPT_SELECTED_URIS", uris, TRUE(!(0)));
5351 g_setenv("NAUTILUS_SCRIPT_SELECTED_URIS", uris, TRUE(!(0))); // compatibilidad GNOME
5352
5353 g_free(uris);
5354
5355 g_setenv("CAJA_SCRIPT_CURRENT_URI", uri, TRUE(!(0)));
5356 g_setenv("NAUTILUS_SCRIPT_CURRENT_URI", uri, TRUE(!(0))); // compatibilidad GNOME
5357
5358
5359 g_free(uri);
5360
5361 geometry_string = eel_gtk_window_get_geometry_string(GTK_WINDOW (fm_directory_view_get_containing_window (view))((((GtkWindow*) (void *) ((fm_directory_view_get_containing_window
(view))))))
);
5362
5363 g_setenv("CAJA_SCRIPT_WINDOW_GEOMETRY", geometry_string, TRUE(!(0)));
5364 g_setenv("NAUTILUS_SCRIPT_WINDOW_GEOMETRY", geometry_string, TRUE(!(0))); // compatibilidad GNOME
5365
5366 g_free(geometry_string);
5367
5368 /* next pane */
5369 next_view = get_directory_view_of_extra_pane(view);
5370
5371 if (next_view)
5372 {
5373 GList* next_pane_selected_files = fm_directory_view_get_selection (next_view);
5374
5375 get_strings_for_environment_variables(next_view, next_pane_selected_files, &file_paths, &uris, &uri);
5376
5377 caja_file_list_free(next_pane_selected_files);
5378 }
5379 else
5380 {
5381 file_paths = g_strdup("")g_strdup_inline ("");
5382 uris = g_strdup("")g_strdup_inline ("");
5383 uri = g_strdup("")g_strdup_inline ("");
5384 }
5385
5386 g_setenv("CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS", file_paths, TRUE(!(0)));
5387 g_setenv("NAUTILUS_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS", file_paths, TRUE(!(0))); // compatibilidad GNOME
5388 g_free(file_paths);
5389
5390 g_setenv("CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS", uris, TRUE(!(0)));
5391 g_setenv("NAUTILUS_SCRIPT_NEXT_PANE_SELECTED_URIS", uris, TRUE(!(0))); // compatibilidad GNOME
5392 g_free(uris);
5393
5394 g_setenv("CAJA_SCRIPT_NEXT_PANE_CURRENT_URI", uri, TRUE(!(0)));
5395 g_setenv("NAUTILUS_SCRIPT_NEXT_PANE_CURRENT_URI", uri, TRUE(!(0))); // compatibilidad GNOME
5396 g_free(uri);
5397}
5398
5399/* Unset all the special script environment variables. */
5400static void unset_script_environment_variables(void)
5401{
5402 g_unsetenv("CAJA_SCRIPT_SELECTED_FILE_PATHS");
5403 g_unsetenv("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS");
5404
5405 g_unsetenv("CAJA_SCRIPT_SELECTED_URIS");
5406 g_unsetenv("NAUTILUS_SCRIPT_SELECTED_URIS");
5407
5408 g_unsetenv("CAJA_SCRIPT_CURRENT_URI");
5409 g_unsetenv("NAUTILUS_SCRIPT_CURRENT_URI");
5410
5411 g_unsetenv("CAJA_SCRIPT_WINDOW_GEOMETRY");
5412 g_unsetenv("NAUTILUS_SCRIPT_WINDOW_GEOMETRY");
5413
5414 g_unsetenv("CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS");
5415 g_unsetenv("NAUTILUS_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS");
5416
5417 g_unsetenv("CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS");
5418 g_unsetenv("NAUTILUS_SCRIPT_NEXT_PANE_SELECTED_URIS");
5419
5420 g_unsetenv("CAJA_SCRIPT_NEXT_PANE_CURRENT_URI");
5421 g_unsetenv("NAUTILUS_SCRIPT_NEXT_PANE_CURRENT_URI");
5422}
5423
5424static void
5425run_script_callback (GtkAction *action, gpointer callback_data)
5426{
5427 ScriptLaunchParameters *launch_parameters;
5428 GdkScreen *screen;
5429 GList *selected_files;
5430 char *file_uri;
5431 char *local_file_path;
5432 char *quoted_path;
5433 char *old_working_dir;
5434 char **parameters, *name;
5435 GtkWindow *window;
5436
5437 launch_parameters = (ScriptLaunchParameters *) callback_data;
5438
5439 file_uri = caja_file_get_uri (launch_parameters->file);
5440 local_file_path = g_filename_from_uri (file_uri, NULL((void*)0), NULL((void*)0));
5441 g_assert (local_file_path != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_261
; if (local_file_path != ((void*)0)) _g_boolean_var_261 = 1; else
_g_boolean_var_261 = 0; _g_boolean_var_261; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 5441, ((const char*) (
__func__)), "local_file_path != NULL"); } while (0)
;
5442 g_free (file_uri);
5443
5444 quoted_path = g_shell_quote (local_file_path);
5445
5446 old_working_dir = change_to_view_directory (launch_parameters->directory_view);
5447
5448 selected_files = fm_directory_view_get_selection (launch_parameters->directory_view);
5449 set_script_environment_variables (launch_parameters->directory_view, selected_files);
5450
5451 parameters = get_file_names_as_parameter_array (selected_files,
5452 launch_parameters->directory_view->details->model);
5453
5454 screen = gtk_widget_get_screen (GTK_WIDGET (launch_parameters->directory_view)((((GtkWidget*) (void *) ((launch_parameters->directory_view
)))))
);
5455
5456 name = caja_file_get_name (launch_parameters->file);
5457 /* FIXME: handle errors with dialog? Or leave up to each script? */
5458 window = fm_directory_view_get_containing_window (launch_parameters->directory_view);
5459 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
5460 "directory view run_script_callback, window=%p, name=\"%s\", script_path=\"%s\" (omitting script parameters)",
5461 window, name, local_file_path);
5462 caja_launch_application_from_command_array (screen, name, quoted_path, FALSE(0),
5463 (const char * const *) parameters);
5464 g_free (local_file_path);
5465 g_free (name);
5466 g_strfreev (parameters);
5467
5468 caja_file_list_free (selected_files);
5469 unset_script_environment_variables ();
5470 g_chdir (old_working_dir);
5471 g_free (old_working_dir);
5472 g_free (quoted_path);
5473}
5474
5475static void
5476add_script_to_scripts_menus (FMDirectoryView *directory_view,
5477 CajaFile *file,
5478 const char *menu_path,
5479 const char *popup_path,
5480 const char *popup_bg_path)
5481{
5482 ScriptLaunchParameters *launch_parameters;
5483 char *tip;
5484 char *name;
5485 char *uri;
5486 char *action_name;
5487 char *escaped_label;
5488 cairo_surface_t *surface;
5489 GtkUIManager *ui_manager;
5490 GtkAction *action;
5491
5492 name = caja_file_get_display_name (file);
5493 uri = caja_file_get_uri (file);
5494 tip = g_strdup_printf (_("Run \"%s\" on any selected items")dcgettext (((void*)0), "Run \"%s\" on any selected items", 5), name);
5495
5496 launch_parameters = script_launch_parameters_new (file, directory_view);
5497
5498 action_name = escape_action_name (uri, "script_");
5499 escaped_label = eel_str_double_underscores (name);
5500
5501 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5502 action = gtk_action_new (action_name,
5503 escaped_label,
5504 tip,
5505 NULL((void*)0));
5506 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5507
5508 surface = get_menu_icon_for_file (file, GTK_WIDGET (directory_view)((((GtkWidget*) (void *) ((directory_view))))));
5509 if (surface != NULL((void*)0)) {
5510 g_object_set_data_full (G_OBJECT (action)((((GObject*) (void *) ((action))))), "menu-icon",
5511 surface,
5512 (GDestroyNotify)cairo_surface_destroy);
5513 }
5514
5515 g_signal_connect_data (action, "activate",
5516 G_CALLBACK (run_script_callback)((GCallback) (run_script_callback)),
5517 launch_parameters,
5518 (GClosureNotify)script_launch_parameters_free, 0);
5519
5520 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5521 gtk_action_group_add_action_with_accel (directory_view->details->scripts_action_group,
5522 action, NULL((void*)0));
5523 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5524 g_object_unref (action);
5525
5526 ui_manager = caja_window_info_get_ui_manager (directory_view->details->window);
5527
5528 gtk_ui_manager_add_ui (ui_manager,
5529 directory_view->details->scripts_merge_id,
5530 menu_path,
5531 action_name,
5532 action_name,
5533 GTK_UI_MANAGER_MENUITEM,
5534 FALSE(0));
5535 gtk_ui_manager_add_ui (ui_manager,
5536 directory_view->details->scripts_merge_id,
5537 popup_path,
5538 action_name,
5539 action_name,
5540 GTK_UI_MANAGER_MENUITEM,
5541 FALSE(0));
5542 gtk_ui_manager_add_ui (ui_manager,
5543 directory_view->details->scripts_merge_id,
5544 popup_bg_path,
5545 action_name,
5546 action_name,
5547 GTK_UI_MANAGER_MENUITEM,
5548 FALSE(0));
5549
5550 g_free (name);
5551 g_free (uri);
5552 g_free (tip);
5553 g_free (action_name);
5554 g_free (escaped_label);
5555}
5556
5557static void
5558add_submenu_to_directory_menus (FMDirectoryView *directory_view,
5559 GtkActionGroup *action_group,
5560 guint merge_id,
5561 CajaFile *file,
5562 const char *menu_path,
5563 const char *popup_path,
5564 const char *popup_bg_path)
5565{
5566 char *name;
5567 cairo_surface_t *surface;
5568 char *uri;
5569 GtkUIManager *ui_manager;
5570
5571 ui_manager = caja_window_info_get_ui_manager (directory_view->details->window);
5572 uri = caja_file_get_uri (file);
5573 name = caja_file_get_display_name (file);
5574 surface = get_menu_icon_for_file (file, GTK_WIDGET (directory_view)((((GtkWidget*) (void *) ((directory_view))))));
5575 add_submenu (ui_manager, action_group, merge_id, menu_path, uri, name, surface, TRUE(!(0)));
5576 add_submenu (ui_manager, action_group, merge_id, popup_path, uri, name, surface, FALSE(0));
5577 add_submenu (ui_manager, action_group, merge_id, popup_bg_path, uri, name, surface, FALSE(0));
5578 if (surface) {
5579 cairo_surface_destroy (surface);
5580 }
5581 g_free (name);
5582 g_free (uri);
5583}
5584
5585static gboolean
5586directory_belongs_in_scripts_menu (const char *uri)
5587{
5588 int num_levels;
5589 int i;
5590
5591 if (!eel_str_has_prefix (uri, scripts_directory_uri)) {
5592 return FALSE(0);
5593 }
5594
5595 num_levels = 0;
5596 for (i = scripts_directory_uri_length; uri[i] != '\0'; i++) {
5597 if (uri[i] == '/') {
5598 num_levels++;
5599 }
5600 }
5601
5602 if (num_levels > MAX_MENU_LEVELS5) {
5603 return FALSE(0);
5604 }
5605
5606 return TRUE(!(0));
5607}
5608
5609static gboolean
5610update_directory_in_scripts_menu (FMDirectoryView *view, CajaDirectory *directory)
5611{
5612 char *menu_path, *popup_path, *popup_bg_path;
5613 GList *file_list, *filtered, *node;
5614 gboolean any_scripts;
5615 CajaDirectory *dir;
5616 char *uri;
5617 char *escaped_path;
5618 CajaFile *file = NULL((void*)0);
5619
5620 uri = caja_directory_get_uri (directory);
5621 escaped_path = escape_action_path (uri + scripts_directory_uri_length);
5622 g_free (uri);
5623 menu_path = g_strconcat (FM_DIRECTORY_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER"/MenuBar/File/Open Placeholder/Scripts/Scripts Placeholder",
5624 escaped_path,
5625 NULL((void*)0));
5626 popup_path = g_strconcat (FM_DIRECTORY_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER"/selection/Open Placeholder/Scripts/Scripts Placeholder",
5627 escaped_path,
5628 NULL((void*)0));
5629 popup_bg_path = g_strconcat (FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER"/background/Before Zoom Items/New Object Items/Scripts/Scripts Placeholder",
5630 escaped_path,
5631 NULL((void*)0));
5632 g_free (escaped_path);
5633
5634 file_list = caja_directory_get_file_list (directory);
5635 filtered = caja_file_list_filter_hidden (file_list, FALSE(0));
5636 caja_file_list_free (file_list);
5637
5638 file_list = caja_file_list_sort_by_display_name (filtered);
5639
5640 any_scripts = FALSE(0);
5641 for (node = file_list; node != NULL((void*)0); node = node->next) {
5642 file = node->data;
5643
5644 if (caja_file_is_launchable (file)) {
5645 add_script_to_scripts_menus (view, file, menu_path, popup_path, popup_bg_path);
5646 any_scripts = TRUE(!(0));
5647 } else if (caja_file_is_directory (file)) {
5648 uri = caja_file_get_uri (file);
5649 if (directory_belongs_in_scripts_menu (uri)) {
5650 dir = caja_directory_get_by_uri (uri);
5651 add_directory_to_scripts_directory_list (view, dir);
5652 caja_directory_unref (dir);
5653
5654 add_submenu_to_directory_menus (view,
5655 view->details->scripts_action_group,
5656 view->details->scripts_merge_id,
5657 file, menu_path, popup_path, popup_bg_path);
5658
5659 any_scripts = TRUE(!(0));
5660 }
5661 g_free (uri);
5662 }
5663 }
5664
5665 caja_file_list_free (file_list);
5666
5667 g_free (popup_path);
5668 g_free (popup_bg_path);
5669 g_free (menu_path);
5670
5671 return any_scripts;
5672}
5673
5674static void
5675update_scripts_menu (FMDirectoryView *view)
5676{
5677 gboolean any_scripts;
5678 GList *sorted_copy, *node;
5679 GtkUIManager *ui_manager;
5680 GtkAction *action;
5681 CajaDirectory *directory = NULL((void*)0);
5682
5683 /* There is a race condition here. If we don't mark the scripts menu as
5684 valid before we begin our task then we can lose script menu updates that
5685 occur before we finish. */
5686 view->details->scripts_invalid = FALSE(0);
5687
5688 ui_manager = caja_window_info_get_ui_manager (view->details->window);
5689 caja_ui_unmerge_ui (ui_manager,
5690 &view->details->scripts_merge_id,
5691 &view->details->scripts_action_group);
5692
5693 caja_ui_prepare_merge_ui (ui_manager,
5694 "ScriptsGroup",
5695 &view->details->scripts_merge_id,
5696 &view->details->scripts_action_group);
5697
5698 /* As we walk through the directories, remove any that no longer belong. */
5699 any_scripts = FALSE(0);
5700 sorted_copy = caja_directory_list_sort_by_uri
5701 (caja_directory_list_copy (view->details->scripts_directory_list));
5702 for (node = sorted_copy; node != NULL((void*)0); node = node->next) {
5703 char *uri;
5704
5705 directory = node->data;
5706
5707 uri = caja_directory_get_uri (directory);
5708 if (!directory_belongs_in_scripts_menu (uri)) {
5709 remove_directory_from_scripts_directory_list (view, directory);
5710 } else if (update_directory_in_scripts_menu (view, directory)) {
5711 any_scripts = TRUE(!(0));
5712 }
5713 g_free (uri);
5714 }
5715 caja_directory_list_free (sorted_copy);
5716
5717 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5718 action = gtk_action_group_get_action (view->details->dir_action_group, FM_ACTION_SCRIPTS"Scripts");
5719 gtk_action_set_visible (action, any_scripts);
5720 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5721}
5722
5723static void
5724create_template_callback (GtkAction *action, gpointer callback_data)
5725{
5726 CreateTemplateParameters *parameters;
5727
5728 parameters = callback_data;
5729
5730 fm_directory_view_new_file (parameters->directory_view, NULL((void*)0), parameters->file);
5731}
5732
5733static void
5734add_template_to_templates_menus (FMDirectoryView *directory_view,
5735 CajaFile *file,
5736 const char *menu_path,
5737 const char *popup_bg_path)
5738{
5739 char *tmp, *tip, *uri, *name;
5740 char *escaped_label;
5741 cairo_surface_t *surface;
5742 char *action_name;
5743 CreateTemplateParameters *parameters;
5744 GtkUIManager *ui_manager;
5745 GtkAction *action;
5746
5747 tmp = caja_file_get_display_name (file);
5748 name = eel_filename_strip_extension (tmp);
5749 g_free (tmp);
5750
5751 uri = caja_file_get_uri (file);
5752 tip = g_strdup_printf (_("Create Document from template \"%s\"")dcgettext (((void*)0), "Create Document from template \"%s\""
, 5)
, name);
5753
5754 action_name = escape_action_name (uri, "template_");
5755 escaped_label = eel_str_double_underscores (name);
5756
5757 parameters = create_template_parameters_new (file, directory_view);
5758
5759 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5760 action = gtk_action_new (action_name,
5761 escaped_label,
5762 tip,
5763 NULL((void*)0));
5764 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5765
5766 surface = get_menu_icon_for_file (file, GTK_WIDGET (directory_view)((((GtkWidget*) (void *) ((directory_view))))));
5767 if (surface != NULL((void*)0)) {
5768 g_object_set_data_full (G_OBJECT (action)((((GObject*) (void *) ((action))))), "menu-icon",
5769 surface,
5770 (GDestroyNotify)cairo_surface_destroy);
5771 }
5772
5773 g_signal_connect_data (action, "activate",
5774 G_CALLBACK (create_template_callback)((GCallback) (create_template_callback)),
5775 parameters,
5776 (GClosureNotify)create_templates_parameters_free, 0);
5777
5778 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5779 gtk_action_group_add_action (directory_view->details->templates_action_group,
5780 action);
5781 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5782 g_object_unref (action);
5783
5784 ui_manager = caja_window_info_get_ui_manager (directory_view->details->window);
5785
5786 gtk_ui_manager_add_ui (ui_manager,
5787 directory_view->details->templates_merge_id,
5788 menu_path,
5789 action_name,
5790 action_name,
5791 GTK_UI_MANAGER_MENUITEM,
5792 FALSE(0));
5793
5794 gtk_ui_manager_add_ui (ui_manager,
5795 directory_view->details->templates_merge_id,
5796 popup_bg_path,
5797 action_name,
5798 action_name,
5799 GTK_UI_MANAGER_MENUITEM,
5800 FALSE(0));
5801
5802 g_free (escaped_label);
5803 g_free (name);
5804 g_free (tip);
5805 g_free (uri);
5806 g_free (action_name);
5807}
5808
5809static void
5810update_templates_directory (FMDirectoryView *view)
5811{
5812 GList *node, *next;
5813
5814 for (node = view->details->templates_directory_list; node != NULL((void*)0); node = next) {
5815 next = node->next;
5816 remove_directory_from_templates_directory_list (view, node->data);
5817 }
5818
5819 if (caja_should_use_templates_directory ()) {
5820 CajaDirectory *templates_directory;
5821 char *templates_uri;
5822
5823 templates_uri = caja_get_templates_directory_uri ();
5824 templates_directory = caja_directory_get_by_uri (templates_uri);
5825 g_free (templates_uri);
5826 add_directory_to_templates_directory_list (view, templates_directory);
5827 caja_directory_unref (templates_directory);
5828 }
5829}
5830
5831static void
5832user_dirs_changed (FMDirectoryView *view)
5833{
5834 update_templates_directory (view);
5835 view->details->templates_invalid = TRUE(!(0));
5836 schedule_update_menus (view);
5837}
5838
5839static gboolean
5840directory_belongs_in_templates_menu (const char *templates_directory_uri,
5841 const char *uri)
5842{
5843 int num_levels;
5844 int i;
5845
5846 if (templates_directory_uri == NULL((void*)0)) {
5847 return FALSE(0);
5848 }
5849
5850 if (!g_str_has_prefix (uri, templates_directory_uri)(__builtin_constant_p (templates_directory_uri)? __extension__
({ const char * const __str = (uri); const char * const __prefix
= (templates_directory_uri); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_262; if (__str == ((void
*)0) || __prefix == ((void*)0)) _g_boolean_var_262 = 1; else _g_boolean_var_262
= 0; _g_boolean_var_262; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (uri, templates_directory_uri
) )
) {
5851 return FALSE(0);
5852 }
5853
5854 num_levels = 0;
5855 for (i = strlen (templates_directory_uri); uri[i] != '\0'; i++) {
5856 if (uri[i] == '/') {
5857 num_levels++;
5858 }
5859 }
5860
5861 if (num_levels > MAX_MENU_LEVELS5) {
5862 return FALSE(0);
5863 }
5864
5865 return TRUE(!(0));
5866}
5867
5868static gboolean
5869update_directory_in_templates_menu (FMDirectoryView *view,
5870 const char *templates_directory_uri,
5871 CajaDirectory *directory)
5872{
5873 char *menu_path, *popup_bg_path;
5874 GList *file_list, *filtered, *node;
5875 gboolean any_templates;
5876 CajaDirectory *dir;
5877 char *escaped_path;
5878 char *uri;
5879 int num;
5880 CajaFile *file = NULL((void*)0);
5881
5882 /* We know this directory belongs to the template dir, so it must exist */
5883 g_assert (templates_directory_uri)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_263
; if (templates_directory_uri) _g_boolean_var_263 = 1; else _g_boolean_var_263
= 0; _g_boolean_var_263; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 5883, ((const char*) (
__func__)), "templates_directory_uri"); } while (0)
;
5884
5885 uri = caja_directory_get_uri (directory);
5886 escaped_path = escape_action_path (uri + strlen (templates_directory_uri));
5887 g_free (uri);
5888 menu_path = g_strconcat (FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER"/MenuBar/File/New Items Placeholder/New Documents/New Documents Placeholder",
5889 escaped_path,
5890 NULL((void*)0));
5891 popup_bg_path = g_strconcat (FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER"/background/Before Zoom Items/New Object Items/New Documents/New Documents Placeholder",
5892 escaped_path,
5893 NULL((void*)0));
5894 g_free (escaped_path);
5895
5896 file_list = caja_directory_get_file_list (directory);
5897 filtered = caja_file_list_filter_hidden (file_list, FALSE(0));
5898 caja_file_list_free (file_list);
5899
5900 file_list = caja_file_list_sort_by_display_name (filtered);
5901
5902 num = 0;
5903 any_templates = FALSE(0);
5904 for (node = file_list; num < TEMPLATE_LIMIT30 && node != NULL((void*)0); node = node->next, num++) {
5905 file = node->data;
5906
5907 if (caja_file_is_directory (file)) {
5908 uri = caja_file_get_uri (file);
5909 if (directory_belongs_in_templates_menu (templates_directory_uri, uri)) {
5910 dir = caja_directory_get_by_uri (uri);
5911 add_directory_to_templates_directory_list (view, dir);
5912 caja_directory_unref (dir);
5913
5914 add_submenu_to_directory_menus (view,
5915 view->details->templates_action_group,
5916 view->details->templates_merge_id,
5917 file, menu_path, NULL((void*)0), popup_bg_path);
5918
5919 any_templates = TRUE(!(0));
5920 }
5921 g_free (uri);
5922 } else if (caja_file_can_read (file)) {
5923 add_template_to_templates_menus (view, file, menu_path, popup_bg_path);
5924 any_templates = TRUE(!(0));
5925 }
5926 }
5927
5928 caja_file_list_free (file_list);
5929
5930 g_free (popup_bg_path);
5931 g_free (menu_path);
5932
5933 return any_templates;
5934}
5935
5936
5937
5938static void
5939update_templates_menu (FMDirectoryView *view)
5940{
5941 gboolean any_templates;
5942 GList *sorted_copy, *node;
5943 GtkUIManager *ui_manager;
5944 GtkAction *action;
5945 char *templates_directory_uri;
5946 CajaDirectory *directory = NULL((void*)0);
5947
5948 if (caja_should_use_templates_directory ()) {
5949 templates_directory_uri = caja_get_templates_directory_uri ();
5950 } else {
5951 templates_directory_uri = NULL((void*)0);
5952 }
5953
5954 /* There is a race condition here. If we don't mark the scripts menu as
5955 valid before we begin our task then we can lose template menu updates that
5956 occur before we finish. */
5957 view->details->templates_invalid = FALSE(0);
5958
5959 ui_manager = caja_window_info_get_ui_manager (view->details->window);
5960 caja_ui_unmerge_ui (ui_manager,
5961 &view->details->templates_merge_id,
5962 &view->details->templates_action_group);
5963
5964 caja_ui_prepare_merge_ui (ui_manager,
5965 "TemplatesGroup",
5966 &view->details->templates_merge_id,
5967 &view->details->templates_action_group);
5968
5969 /* As we walk through the directories, remove any that no longer belong. */
5970 any_templates = FALSE(0);
5971 sorted_copy = caja_directory_list_sort_by_uri
5972 (caja_directory_list_copy (view->details->templates_directory_list));
5973 for (node = sorted_copy; node != NULL((void*)0); node = node->next) {
5974 char *uri;
5975
5976 directory = node->data;
5977
5978 uri = caja_directory_get_uri (directory);
5979 if (!directory_belongs_in_templates_menu (templates_directory_uri, uri)) {
5980 remove_directory_from_templates_directory_list (view, directory);
5981 } else if (update_directory_in_templates_menu (view,
5982 templates_directory_uri,
5983 directory)) {
5984 any_templates = TRUE(!(0));
5985 }
5986 g_free (uri);
5987 }
5988 caja_directory_list_free (sorted_copy);
5989
5990 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
5991 action = gtk_action_group_get_action (view->details->dir_action_group, FM_ACTION_NO_TEMPLATES"No Templates");
5992 gtk_action_set_visible (action, !any_templates);
5993 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
5994
5995 g_free (templates_directory_uri);
5996}
5997
5998
5999static void
6000action_open_scripts_folder_callback (GtkAction *action,
6001 gpointer callback_data)
6002{
6003 FMDirectoryView *view;
6004
6005 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6006
6007 open_location (view, scripts_directory_uri, CAJA_WINDOW_OPEN_ACCORDING_TO_MODE, 0);
6008
6009 eel_show_info_dialog_with_details
6010 (_("All executable files in this folder will appear in the "dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu.", 5)
6011 "Scripts menu.")dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu.", 5)
,
6012 _("Choosing a script from the menu will run "dcgettext (((void*)0), "Choosing a script from the menu will run "
"that script with any selected items as input.", 5)
6013 "that script with any selected items as input.")dcgettext (((void*)0), "Choosing a script from the menu will run "
"that script with any selected items as input.", 5)
,
6014 _("All executable files in this folder will appear in the "dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6015 "Scripts menu. Choosing a script from the menu will run "dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6016 "that script.\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6017 "When executed from a local folder, scripts will be passed "dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6018 "the selected file names. When executed from a remote folder "dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6019 "(e.g. a folder showing web or ftp content), scripts will "dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6020 "be passed no parameters.\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6021 "In all cases, the following environment variables will be "dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6022 "set by Caja, which the scripts may use:\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6023 "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6024 "CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6025 "CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6026 "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6027 "CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6028 "CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
6029 "CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window")dcgettext (((void*)0), "All executable files in this folder will appear in the "
"Scripts menu. Choosing a script from the menu will run " "that script.\n\n"
"When executed from a local folder, scripts will be passed "
"the selected file names. When executed from a remote folder "
"(e.g. a folder showing web or ftp content), scripts will " "be passed no parameters.\n\n"
"In all cases, the following environment variables will be "
"set by Caja, which the scripts may use:\n\n" "CAJA_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local)\n\n"
"CAJA_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files\n\n"
"CAJA_SCRIPT_CURRENT_URI: URI for current location\n\n" "CAJA_SCRIPT_WINDOW_GEOMETRY: position and size of current window\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local)\n\n"
"CAJA_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window\n\n"
"CAJA_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window"
, 5)
,
6030 fm_directory_view_get_containing_window (view));
6031}
6032
6033static GtkMenu *
6034create_popup_menu (FMDirectoryView *view, const char *popup_path)
6035{
6036 GtkWidget *menu;
6037
6038 menu = gtk_ui_manager_get_widget (caja_window_info_get_ui_manager (view->details->window),
6039 popup_path);
6040 gtk_menu_set_screen (GTK_MENU (menu)((((GtkMenu*) (void *) ((menu))))),
6041 gtk_widget_get_screen (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))));
6042 gtk_widget_show (GTK_WIDGET (menu)((((GtkWidget*) (void *) ((menu))))));
6043
6044 return GTK_MENU (menu)((((GtkMenu*) (void *) ((menu)))));
6045}
6046
6047static void
6048copy_or_cut_files (FMDirectoryView *view,
6049 GList *clipboard_contents,
6050 gboolean cut)
6051{
6052 int count;
6053 char *status_string;
6054 CajaClipboardInfo info;
6055 GtkTargetList *target_list;
6056 GtkTargetEntry *targets;
6057 int n_targets;
6058
6059 info.files = clipboard_contents;
6060 info.cut = cut;
6061
6062 target_list = gtk_target_list_new (NULL((void*)0), 0);
6063 gtk_target_list_add (target_list, copied_files_atom, 0, 0);
6064 gtk_target_list_add_uri_targets (target_list, 0);
6065 gtk_target_list_add_text_targets (target_list, 0);
6066
6067 targets = gtk_target_table_new_from_list (target_list, &n_targets);
6068 gtk_target_list_unref (target_list);
6069
6070 gtk_clipboard_set_with_data (caja_clipboard_get (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))),
6071 targets, n_targets,
6072 caja_get_clipboard_callback, caja_clear_clipboard_callback,
6073 NULL((void*)0));
6074 gtk_target_table_free (targets, n_targets);
6075
6076 caja_clipboard_monitor_set_clipboard_info (caja_clipboard_monitor_get (), &info);
6077
6078 count = g_list_length (clipboard_contents);
6079 if (count == 1) {
6080 char *name;
6081
6082 name = caja_file_get_display_name (clipboard_contents->data);
6083 if (cut) {
6084 status_string = g_strdup_printf (_("\"%s\" will be moved "dcgettext (((void*)0), "\"%s\" will be moved " "if you select the Paste command"
, 5)
6085 "if you select the Paste command")dcgettext (((void*)0), "\"%s\" will be moved " "if you select the Paste command"
, 5)
,
6086 name);
6087 } else {
6088 status_string = g_strdup_printf (_("\"%s\" will be copied "dcgettext (((void*)0), "\"%s\" will be copied " "if you select the Paste command"
, 5)
6089 "if you select the Paste command")dcgettext (((void*)0), "\"%s\" will be copied " "if you select the Paste command"
, 5)
,
6090 name);
6091 }
6092 g_free (name);
6093 } else {
6094 if (cut) {
6095 status_string = g_strdup_printf (ngettext("The %'d selected item will be moved "dcngettext (((void*)0), "The %'d selected item will be moved "
"if you select the Paste command", "The %'d selected items will be moved "
"if you select the Paste command", count, 5)
6096 "if you select the Paste command",dcngettext (((void*)0), "The %'d selected item will be moved "
"if you select the Paste command", "The %'d selected items will be moved "
"if you select the Paste command", count, 5)
6097 "The %'d selected items will be moved "dcngettext (((void*)0), "The %'d selected item will be moved "
"if you select the Paste command", "The %'d selected items will be moved "
"if you select the Paste command", count, 5)
6098 "if you select the Paste command",dcngettext (((void*)0), "The %'d selected item will be moved "
"if you select the Paste command", "The %'d selected items will be moved "
"if you select the Paste command", count, 5)
6099 count)dcngettext (((void*)0), "The %'d selected item will be moved "
"if you select the Paste command", "The %'d selected items will be moved "
"if you select the Paste command", count, 5)
,
6100 count);
6101 } else {
6102 status_string = g_strdup_printf (ngettext("The %'d selected item will be copied "dcngettext (((void*)0), "The %'d selected item will be copied "
"if you select the Paste command", "The %'d selected items will be copied "
"if you select the Paste command", count, 5)
6103 "if you select the Paste command",dcngettext (((void*)0), "The %'d selected item will be copied "
"if you select the Paste command", "The %'d selected items will be copied "
"if you select the Paste command", count, 5)
6104 "The %'d selected items will be copied "dcngettext (((void*)0), "The %'d selected item will be copied "
"if you select the Paste command", "The %'d selected items will be copied "
"if you select the Paste command", count, 5)
6105 "if you select the Paste command",dcngettext (((void*)0), "The %'d selected item will be copied "
"if you select the Paste command", "The %'d selected items will be copied "
"if you select the Paste command", count, 5)
6106 count)dcngettext (((void*)0), "The %'d selected item will be copied "
"if you select the Paste command", "The %'d selected items will be copied "
"if you select the Paste command", count, 5)
,
6107 count);
6108 }
6109 }
6110
6111 caja_window_slot_info_set_status (view->details->slot,
6112 status_string);
6113 g_free (status_string);
6114}
6115
6116static void
6117action_copy_files_callback (GtkAction *action,
6118 gpointer callback_data)
6119{
6120 FMDirectoryView *view;
6121 GList *selection;
6122
6123 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6124
6125 selection = fm_directory_view_get_selection_for_file_transfer (view);
6126 copy_or_cut_files (view, selection, FALSE(0));
6127 caja_file_list_free (selection);
6128}
6129
6130static void
6131move_copy_selection_to_location (FMDirectoryView *view,
6132 int copy_action,
6133 char *target_uri)
6134{
6135 GList *selection, *uris, *l;
6136
6137 selection = fm_directory_view_get_selection_for_file_transfer (view);
6138 if (selection == NULL((void*)0)) {
6139 return;
6140 }
6141
6142 uris = NULL((void*)0);
6143 for (l = selection; l != NULL((void*)0); l = l->next) {
6144 uris = g_list_prepend (uris,
6145 caja_file_get_uri ((CajaFile *) l->data));
6146 }
6147 uris = g_list_reverse (uris);
6148
6149 fm_directory_view_move_copy_items (uris, NULL((void*)0), target_uri,
6150 copy_action,
6151 0, 0,
6152 view);
6153
6154 g_list_free_full (uris, g_free);
6155 caja_file_list_free (selection);
6156}
6157
6158static void
6159move_copy_selection_to_next_pane (FMDirectoryView *view,
6160 int copy_action)
6161{
6162 CajaWindowSlotInfo *slot;
6163 char *dest_location;
6164
6165 slot = caja_window_info_get_extra_slot (fm_directory_view_get_caja_window (view));
6166 g_return_if_fail (slot != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_264
; if (slot != ((void*)0)) _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__)), "slot != NULL"); return
; } } while (0)
;
6167
6168 dest_location = caja_window_slot_info_get_current_location (slot);
6169 g_return_if_fail (dest_location != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_265
; if (dest_location != ((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__
)), "dest_location != NULL"); return; } } while (0)
;
6170
6171 move_copy_selection_to_location (view, copy_action, dest_location);
6172}
6173
6174static void
6175action_copy_to_next_pane_callback (GtkAction *action, gpointer callback_data)
6176{
6177 FMDirectoryView *view;
6178
6179 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6180 move_copy_selection_to_next_pane (view,
6181 GDK_ACTION_COPY);
6182}
6183
6184static void
6185action_move_to_next_pane_callback (GtkAction *action, gpointer callback_data)
6186{
6187 CajaWindowSlotInfo *slot;
6188 char *dest_location;
6189 FMDirectoryView *view;
6190
6191 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6192
6193 slot = caja_window_info_get_extra_slot (fm_directory_view_get_caja_window (view));
6194 g_return_if_fail (slot != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_266
; if (slot != ((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__)), "slot != NULL"); return
; } } while (0)
;
6195
6196 dest_location = caja_window_slot_info_get_current_location (slot);
6197 g_return_if_fail (dest_location != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (dest_location != ((void*)0)) _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__
)), "dest_location != NULL"); return; } } while (0)
;
6198
6199 move_copy_selection_to_location (view, GDK_ACTION_MOVE, dest_location);
6200}
6201
6202static void
6203action_copy_to_home_callback (GtkAction *action, gpointer callback_data)
6204{
6205 FMDirectoryView *view;
6206 char *dest_location;
6207
6208 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6209
6210 dest_location = caja_get_home_directory_uri ();
6211 move_copy_selection_to_location (view, GDK_ACTION_COPY, dest_location);
6212 g_free (dest_location);
6213}
6214
6215static void
6216action_move_to_home_callback (GtkAction *action, gpointer callback_data)
6217{
6218 FMDirectoryView *view;
6219 char *dest_location;
6220
6221 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6222
6223 dest_location = caja_get_home_directory_uri ();
6224 move_copy_selection_to_location (view, GDK_ACTION_MOVE, dest_location);
6225 g_free (dest_location);
6226}
6227
6228static void
6229action_copy_to_desktop_callback (GtkAction *action, gpointer callback_data)
6230{
6231 FMDirectoryView *view;
6232 char *dest_location;
6233
6234 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6235
6236 dest_location = caja_get_desktop_directory_uri ();
6237 move_copy_selection_to_location (view, GDK_ACTION_COPY, dest_location);
6238 g_free (dest_location);
6239}
6240
6241static void
6242action_move_to_desktop_callback (GtkAction *action, gpointer callback_data)
6243{
6244 FMDirectoryView *view;
6245 char *dest_location;
6246
6247 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6248
6249 dest_location = caja_get_desktop_directory_uri ();
6250 move_copy_selection_to_location (view, GDK_ACTION_MOVE, dest_location);
6251 g_free (dest_location);
6252}
6253
6254static void
6255action_cut_files_callback (GtkAction *action,
6256 gpointer callback_data)
6257{
6258 FMDirectoryView *view;
6259 GList *selection;
6260
6261 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6262
6263 selection = fm_directory_view_get_selection_for_file_transfer (view);
6264 copy_or_cut_files (view, selection, TRUE(!(0)));
6265 caja_file_list_free (selection);
6266}
6267
6268static void
6269paste_clipboard_data (FMDirectoryView *view,
6270 GtkSelectionData *selection_data,
6271 char *destination_uri)
6272{
6273 gboolean cut;
6274 GList *item_uris;
6275
6276 cut = FALSE(0);
6277 item_uris = caja_clipboard_get_uri_list_from_selection_data (selection_data, &cut,
6278 copied_files_atom);
6279
6280 if (item_uris == NULL((void*)0)|| destination_uri == NULL((void*)0)) {
6281 caja_window_slot_info_set_status (view->details->slot,
6282 _("There is nothing on the clipboard to paste.")dcgettext (((void*)0), "There is nothing on the clipboard to paste."
, 5)
);
6283 } else {
6284 fm_directory_view_move_copy_items (item_uris, NULL((void*)0), destination_uri,
6285 cut ? GDK_ACTION_MOVE : GDK_ACTION_COPY,
6286 0, 0,
6287 view);
6288
6289 /* If items are cut then remove from clipboard */
6290 if (cut) {
6291 gtk_clipboard_clear (caja_clipboard_get (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))));
6292 }
6293
6294 g_list_free_full (item_uris, g_free);
6295 }
6296}
6297
6298static void
6299paste_clipboard_received_callback (GtkClipboard *clipboard,
6300 GtkSelectionData *selection_data,
6301 gpointer data)
6302{
6303 FMDirectoryView *view;
6304 char *view_uri;
6305
6306 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6307
6308 view_uri = fm_directory_view_get_backing_uri (view);
6309
6310 if (view->details->window != NULL((void*)0)) {
6311 paste_clipboard_data (view, selection_data, view_uri);
6312 }
6313
6314 g_free (view_uri);
6315
6316 g_object_unref (view);
6317}
6318
6319typedef struct {
6320 FMDirectoryView *view;
6321 CajaFile *target;
6322} PasteIntoData;
6323
6324static void
6325paste_into_clipboard_received_callback (GtkClipboard *clipboard,
6326 GtkSelectionData *selection_data,
6327 gpointer callback_data)
6328{
6329 PasteIntoData *data;
6330 FMDirectoryView *view;
6331
6332 data = (PasteIntoData *) callback_data;
6333
6334 view = FM_DIRECTORY_VIEW (data->view)((((FMDirectoryView*) (void *) ((data->view)))));
6335
6336 if (view->details->window != NULL((void*)0)) {
6337 char *directory_uri;
6338
6339 directory_uri = caja_file_get_activation_uri (data->target);
6340
6341 paste_clipboard_data (view, selection_data, directory_uri);
6342
6343 g_free (directory_uri);
6344 }
6345
6346 g_object_unref (view);
6347 caja_file_unref (data->target);
6348 g_free (data);
6349}
6350
6351static void
6352action_paste_files_callback (GtkAction *action,
6353 gpointer callback_data)
6354{
6355 FMDirectoryView *view;
6356
6357 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6358
6359 g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view));
6360 gtk_clipboard_request_contents (caja_clipboard_get (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))),
6361 copied_files_atom,
6362 paste_clipboard_received_callback,
6363 view);
6364}
6365
6366static void
6367paste_into (FMDirectoryView *view,
6368 CajaFile *target)
6369{
6370 PasteIntoData *data;
6371
6372 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_268
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_268
= 1; else _g_boolean_var_268 = 0; _g_boolean_var_268; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 6372, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
6373 g_assert (CAJA_IS_FILE (target))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_269
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target)); GType __t = (caja_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_269
= 1; else _g_boolean_var_269 = 0; _g_boolean_var_269; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 6373, ((const char*) (__func__)), "CAJA_IS_FILE (target)");
} while (0)
;
6374
6375 data = g_new (PasteIntoData, 1)(PasteIntoData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (PasteIntoData); 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; }))
;
6376
6377 data->view = g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view));
6378 data->target = caja_file_ref (target);
6379
6380 gtk_clipboard_request_contents (caja_clipboard_get (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))),
6381 copied_files_atom,
6382 paste_into_clipboard_received_callback,
6383 data);
6384}
6385
6386static void
6387action_paste_files_into_callback (GtkAction *action,
6388 gpointer callback_data)
6389{
6390 FMDirectoryView *view;
6391 GList *selection;
6392
6393 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6394 selection = fm_directory_view_get_selection (view);
6395 if (selection != NULL((void*)0)) {
6396 paste_into (view, CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data))))));
6397 caja_file_list_free (selection);
6398 }
6399
6400}
6401
6402static void
6403real_action_undo (FMDirectoryView *view)
6404{
6405 CajaUndoStackManager *manager = caja_undostack_manager_instance ();
6406
6407 /* Disable menus because they are in an untrustworthy status */
6408 view->details->undo_active = FALSE(0);
6409 view->details->redo_active = FALSE(0);
6410 fm_directory_view_update_menus (view);
6411
6412 caja_undostack_manager_undo (manager, GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))), finish_undoredo_callback);
6413}
6414
6415static void
6416real_action_redo (FMDirectoryView *view)
6417{
6418 CajaUndoStackManager *manager = caja_undostack_manager_instance ();
6419
6420 /* Disable menus because they are in an untrustworthy status */
6421 view->details->undo_active = FALSE(0);
6422 view->details->redo_active = FALSE(0);
6423 fm_directory_view_update_menus (view);
6424
6425 caja_undostack_manager_redo (manager, GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))), finish_undoredo_callback);
6426}
6427
6428static void
6429real_action_rename (FMDirectoryView *view,
6430 gboolean select_all)
6431{
6432 GList *selection;
6433
6434 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_270
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_270
= 1; else _g_boolean_var_270 = 0; _g_boolean_var_270; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 6434, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
6435
6436 selection = fm_directory_view_get_selection (view);
6437
6438 if (selection_not_empty_in_menu_callback (view, selection)) {
6439 CajaFile *file;
6440
6441 file = CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data)))));
6442
6443 if (!select_all) {
6444 /* directories don't have a file extension, so
6445 * they are always pre-selected as a whole */
6446 select_all = caja_file_is_directory (file);
6447 }
6448 EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view, start_renaming_file, (view, file, select_all))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->start_renaming_file
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->start_renaming_file) (view, file, select_all); } } while
(0)
;
6449 }
6450
6451 caja_file_list_free (selection);
6452}
6453
6454static void
6455action_rename_callback (GtkAction *action,
6456 gpointer callback_data)
6457{
6458 real_action_rename (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))), FALSE(0));
6459}
6460
6461static void
6462action_rename_select_all_callback (GtkAction *action,
6463 gpointer callback_data)
6464{
6465 real_action_rename (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))), TRUE(!(0)));
6466}
6467
6468static void
6469file_mount_callback (CajaFile *file,
6470 GFile *result_location,
6471 GError *error,
6472 gpointer callback_data)
6473{
6474 if (error != NULL((void*)0) &&
6475 (error->domain != G_IO_ERRORg_io_error_quark() ||
6476 (error->code != G_IO_ERROR_CANCELLED &&
6477 error->code != G_IO_ERROR_FAILED_HANDLED &&
6478 error->code != G_IO_ERROR_ALREADY_MOUNTED))) {
6479 eel_show_error_dialog (_("Unable to mount location")dcgettext (((void*)0), "Unable to mount location", 5),
6480 error->message, NULL((void*)0));
6481 }
6482}
6483
6484static void
6485file_unmount_callback (CajaFile *file,
6486 GFile *result_location,
6487 GError *error,
6488 gpointer callback_data)
6489{
6490 FMDirectoryView *view;
6491
6492 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6493 fm_directory_view_set_initiated_unmount (view, FALSE(0));
6494 g_object_unref (view);
6495
6496 if (error != NULL((void*)0) &&
6497 (error->domain != G_IO_ERRORg_io_error_quark() ||
6498 (error->code != G_IO_ERROR_CANCELLED &&
6499 error->code != G_IO_ERROR_FAILED_HANDLED))) {
6500 eel_show_error_dialog (_("Unable to unmount location")dcgettext (((void*)0), "Unable to unmount location", 5),
6501 error->message, NULL((void*)0));
6502 }
6503}
6504
6505static void
6506file_eject_callback (CajaFile *file,
6507 GFile *result_location,
6508 GError *error,
6509 gpointer callback_data)
6510{
6511 FMDirectoryView *view;
6512
6513 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
6514 fm_directory_view_set_initiated_unmount (view, FALSE(0));
6515 g_object_unref (view);
6516
6517 if (error != NULL((void*)0) &&
6518 (error->domain != G_IO_ERRORg_io_error_quark() ||
6519 (error->code != G_IO_ERROR_CANCELLED &&
6520 error->code != G_IO_ERROR_FAILED_HANDLED))) {
6521 eel_show_error_dialog (_("Unable to eject location")dcgettext (((void*)0), "Unable to eject location", 5),
6522 error->message, NULL((void*)0));
6523 }
6524}
6525
6526static void
6527file_stop_callback (CajaFile *file,
6528 GFile *result_location,
6529 GError *error,
6530 gpointer callback_data)
6531{
6532 if (error != NULL((void*)0) &&
6533 (error->domain != G_IO_ERRORg_io_error_quark() ||
6534 (error->code != G_IO_ERROR_CANCELLED &&
6535 error->code != G_IO_ERROR_FAILED_HANDLED))) {
6536 eel_show_error_dialog (_("Unable to stop drive")dcgettext (((void*)0), "Unable to stop drive", 5),
6537 error->message, NULL((void*)0));
6538 }
6539}
6540
6541static void
6542action_mount_volume_callback (GtkAction *action,
6543 gpointer data)
6544{
6545 GList *selection, *l;
6546 FMDirectoryView *view;
6547 GMountOperation *mount_op;
6548 CajaFile *file = NULL((void*)0);
6549
6550 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6551
6552 selection = fm_directory_view_get_selection (view);
6553 for (l = selection; l != NULL((void*)0); l = l->next) {
6554 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
6555
6556 if (caja_file_can_mount (file)) {
6557 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6558 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
6559 caja_file_mount (file, mount_op, NULL((void*)0),
6560 file_mount_callback, NULL((void*)0));
6561 g_object_unref (mount_op);
6562 }
6563 }
6564 caja_file_list_free (selection);
6565}
6566
6567static void
6568action_unmount_volume_callback (GtkAction *action,
6569 gpointer data)
6570{
6571 GList *selection, *l;
6572 FMDirectoryView *view;
6573 CajaFile *file = NULL((void*)0);
6574
6575 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6576
6577 selection = fm_directory_view_get_selection (view);
6578
6579 for (l = selection; l != NULL((void*)0); l = l->next) {
6580 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
6581 if (caja_file_can_unmount (file)) {
6582 GMountOperation *mount_op;
6583 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6584 fm_directory_view_set_initiated_unmount (view, TRUE(!(0)));
6585 caja_file_unmount (file, mount_op, NULL((void*)0),
6586 file_unmount_callback, g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)));
6587 g_object_unref (mount_op);
6588 }
6589 }
6590 caja_file_list_free (selection);
6591}
6592
6593static void
6594action_format_volume_callback (GtkAction *action,
6595 gpointer data)
6596{
6597#ifdef TODO_GIO
6598 GList *selection, *l;
6599 FMDirectoryView *view;
6600 CajaFile *file = NULL((void*)0);
6601
6602 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6603
6604 selection = fm_directory_view_get_selection (view);
6605 for (l = selection; l != NULL((void*)0); l = l->next) {
6606 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
6607
6608 if (something) {
6609 g_spawn_command_line_async ("gfloppy", NULL((void*)0));
6610 }
6611 }
6612 caja_file_list_free (selection);
6613#endif
6614}
6615
6616static void
6617action_eject_volume_callback (GtkAction *action,
6618 gpointer data)
6619{
6620 GList *selection, *l;
6621 FMDirectoryView *view;
6622 CajaFile *file = NULL((void*)0);
6623
6624 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6625
6626 selection = fm_directory_view_get_selection (view);
6627 for (l = selection; l != NULL((void*)0); l = l->next) {
6628 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
6629
6630 if (caja_file_can_eject (file)) {
6631 GMountOperation *mount_op;
6632 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6633 fm_directory_view_set_initiated_unmount (view, TRUE(!(0)));
6634 caja_file_eject (file, mount_op, NULL((void*)0),
6635 file_eject_callback, g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)));
6636 g_object_unref (mount_op);
6637 }
6638 }
6639 caja_file_list_free (selection);
6640}
6641
6642static void
6643file_start_callback (CajaFile *file,
6644 GFile *result_location,
6645 GError *error,
6646 gpointer callback_data)
6647{
6648 if (error != NULL((void*)0) &&
6649 (error->domain != G_IO_ERRORg_io_error_quark() ||
6650 (error->code != G_IO_ERROR_CANCELLED &&
6651 error->code != G_IO_ERROR_FAILED_HANDLED &&
6652 error->code != G_IO_ERROR_ALREADY_MOUNTED))) {
6653 eel_show_error_dialog (_("Unable to start location")dcgettext (((void*)0), "Unable to start location", 5),
6654 error->message, NULL((void*)0));
6655 }
6656}
6657
6658static void
6659action_start_volume_callback (GtkAction *action,
6660 gpointer data)
6661{
6662 GList *selection, *l;
6663 FMDirectoryView *view;
6664 GMountOperation *mount_op;
6665 CajaFile *file = NULL((void*)0);
6666
6667 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6668
6669 selection = fm_directory_view_get_selection (view);
6670 for (l = selection; l != NULL((void*)0); l = l->next) {
6671 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
6672
6673 if (caja_file_can_start (file) || caja_file_can_start_degraded (file)) {
6674 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6675 caja_file_start (file, mount_op, NULL((void*)0),
6676 file_start_callback, NULL((void*)0));
6677 g_object_unref (mount_op);
6678 }
6679 }
6680 caja_file_list_free (selection);
6681}
6682
6683static void
6684action_stop_volume_callback (GtkAction *action,
6685 gpointer data)
6686{
6687 GList *selection, *l;
6688 FMDirectoryView *view;
6689 CajaFile *file = NULL((void*)0);
6690
6691 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6692
6693 selection = fm_directory_view_get_selection (view);
6694 for (l = selection; l != NULL((void*)0); l = l->next) {
6695 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
6696
6697 if (caja_file_can_stop (file)) {
6698 GMountOperation *mount_op;
6699 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6700 caja_file_stop (file, mount_op, NULL((void*)0),
6701 file_stop_callback, NULL((void*)0));
6702 g_object_unref (mount_op);
6703 }
6704 }
6705 caja_file_list_free (selection);
6706}
6707
6708static void
6709action_detect_media_callback (GtkAction *action,
6710 gpointer data)
6711{
6712 GList *selection, *l;
6713 FMDirectoryView *view;
6714 CajaFile *file = NULL((void*)0);
6715
6716 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6717
6718 selection = fm_directory_view_get_selection (view);
6719 for (l = selection; l != NULL((void*)0); l = l->next) {
6720 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
6721
6722 if (caja_file_can_poll_for_media (file) && !caja_file_is_media_check_automatic (file)) {
6723 caja_file_poll_for_media (file);
6724 }
6725 }
6726 caja_file_list_free (selection);
6727}
6728
6729static void
6730action_self_mount_volume_callback (GtkAction *action,
6731 gpointer data)
6732{
6733 CajaFile *file;
6734 FMDirectoryView *view;
6735 GMountOperation *mount_op;
6736
6737 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6738
6739 file = fm_directory_view_get_directory_as_file (view);
6740 if (file == NULL((void*)0)) {
6741 return;
6742 }
6743
6744 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6745 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
6746 caja_file_mount (file, mount_op, NULL((void*)0), file_mount_callback, NULL((void*)0));
6747 g_object_unref (mount_op);
6748}
6749
6750static void
6751action_self_unmount_volume_callback (GtkAction *action,
6752 gpointer data)
6753{
6754 CajaFile *file;
6755 FMDirectoryView *view;
6756 GMountOperation *mount_op;
6757
6758 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6759
6760 file = fm_directory_view_get_directory_as_file (view);
6761 if (file == NULL((void*)0)) {
6762 return;
6763 }
6764
6765 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6766 fm_directory_view_set_initiated_unmount (view, TRUE(!(0)));
6767 caja_file_unmount (file, mount_op, NULL((void*)0), file_unmount_callback, g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)));
6768 g_object_unref (mount_op);
6769}
6770
6771static void
6772action_self_eject_volume_callback (GtkAction *action,
6773 gpointer data)
6774{
6775 CajaFile *file;
6776 FMDirectoryView *view;
6777 GMountOperation *mount_op;
6778
6779 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6780
6781 file = fm_directory_view_get_directory_as_file (view);
6782 if (file == NULL((void*)0)) {
6783 return;
6784 }
6785
6786 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6787 fm_directory_view_set_initiated_unmount (view, TRUE(!(0)));
6788 caja_file_eject (file, mount_op, NULL((void*)0), file_eject_callback, g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)));
6789 g_object_unref (mount_op);
6790}
6791
6792static void
6793action_self_format_volume_callback (GtkAction *action,
6794 gpointer data)
6795{
6796 CajaFile *file;
6797 FMDirectoryView *view;
6798
6799 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6800
6801 file = fm_directory_view_get_directory_as_file (view);
6802 if (file == NULL((void*)0)) {
6803 return;
6804 }
6805
6806#ifdef TODO_GIO
6807 if (something) {
6808 g_spawn_command_line_async ("gfloppy", NULL((void*)0));
6809 }
6810#endif
6811}
6812
6813static void
6814action_self_start_volume_callback (GtkAction *action,
6815 gpointer data)
6816{
6817 CajaFile *file;
6818 FMDirectoryView *view;
6819 GMountOperation *mount_op;
6820
6821 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6822
6823 file = fm_directory_view_get_directory_as_file (view);
6824 if (file == NULL((void*)0)) {
6825 return;
6826 }
6827
6828 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6829 caja_file_start (file, mount_op, NULL((void*)0), file_start_callback, NULL((void*)0));
6830 g_object_unref (mount_op);
6831}
6832
6833static void
6834action_self_stop_volume_callback (GtkAction *action,
6835 gpointer data)
6836{
6837 CajaFile *file;
6838 FMDirectoryView *view;
6839 GMountOperation *mount_op;
6840
6841 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6842
6843 file = fm_directory_view_get_directory_as_file (view);
6844 if (file == NULL((void*)0)) {
6845 return;
6846 }
6847
6848 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6849 caja_file_stop (file, mount_op, NULL((void*)0),
6850 file_stop_callback, NULL((void*)0));
6851 g_object_unref (mount_op);
6852}
6853
6854static void
6855action_self_detect_media_callback (GtkAction *action,
6856 gpointer data)
6857{
6858 CajaFile *file;
6859 FMDirectoryView *view;
6860
6861 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6862
6863 file = fm_directory_view_get_directory_as_file (view);
6864 if (file == NULL((void*)0)) {
6865 return;
6866 }
6867
6868 caja_file_poll_for_media (file);
6869}
6870
6871static void
6872action_location_mount_volume_callback (GtkAction *action,
6873 gpointer data)
6874{
6875 CajaFile *file;
6876 FMDirectoryView *view;
6877 GMountOperation *mount_op;
6878
6879 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6880
6881 file = view->details->location_popup_directory_as_file;
6882 if (file == NULL((void*)0)) {
6883 return;
6884 }
6885
6886 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6887 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
6888 caja_file_mount (file, mount_op, NULL((void*)0), file_mount_callback, NULL((void*)0));
6889 g_object_unref (mount_op);
6890}
6891
6892static void
6893action_location_unmount_volume_callback (GtkAction *action,
6894 gpointer data)
6895{
6896 CajaFile *file;
6897 FMDirectoryView *view;
6898 GMountOperation *mount_op;
6899
6900 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6901
6902 file = view->details->location_popup_directory_as_file;
6903 if (file == NULL((void*)0)) {
6904 return;
6905 }
6906
6907 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6908 fm_directory_view_set_initiated_unmount (view, TRUE(!(0)));
6909 caja_file_unmount (file, mount_op, NULL((void*)0),
6910 file_unmount_callback, g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)));
6911 g_object_unref (mount_op);
6912}
6913
6914static void
6915action_location_eject_volume_callback (GtkAction *action,
6916 gpointer data)
6917{
6918 CajaFile *file;
6919 FMDirectoryView *view;
6920 GMountOperation *mount_op;
6921
6922 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6923
6924 file = view->details->location_popup_directory_as_file;
6925 if (file == NULL((void*)0)) {
6926 return;
6927 }
6928
6929 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6930 fm_directory_view_set_initiated_unmount (view, TRUE(!(0)));
6931 caja_file_eject (file, mount_op, NULL((void*)0),
6932 file_eject_callback, g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)));
6933 g_object_unref (mount_op);
6934}
6935
6936static void
6937action_location_format_volume_callback (GtkAction *action,
6938 gpointer data)
6939{
6940 CajaFile *file;
6941 FMDirectoryView *view;
6942
6943 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6944
6945 file = view->details->location_popup_directory_as_file;
6946 if (file == NULL((void*)0)) {
6947 return;
6948 }
6949
6950#ifdef TODO_GIO
6951 if (something) {
6952 g_spawn_command_line_async ("gfloppy", NULL((void*)0));
6953 }
6954#endif
6955}
6956
6957static void
6958action_location_start_volume_callback (GtkAction *action,
6959 gpointer data)
6960{
6961 CajaFile *file;
6962 FMDirectoryView *view;
6963 GMountOperation *mount_op;
6964
6965 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6966
6967 file = view->details->location_popup_directory_as_file;
6968 if (file == NULL((void*)0)) {
6969 return;
6970 }
6971
6972 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6973 caja_file_start (file, mount_op, NULL((void*)0), file_start_callback, NULL((void*)0));
6974 g_object_unref (mount_op);
6975}
6976
6977static void
6978action_location_stop_volume_callback (GtkAction *action,
6979 gpointer data)
6980{
6981 CajaFile *file;
6982 FMDirectoryView *view;
6983 GMountOperation *mount_op;
6984
6985 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
6986
6987 file = view->details->location_popup_directory_as_file;
6988 if (file == NULL((void*)0)) {
6989 return;
6990 }
6991
6992 mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
6993 caja_file_stop (file, mount_op, NULL((void*)0),
6994 file_stop_callback, NULL((void*)0));
6995 g_object_unref (mount_op);
6996}
6997
6998static void
6999action_location_detect_media_callback (GtkAction *action,
7000 gpointer data)
7001{
7002 CajaFile *file;
7003 FMDirectoryView *view;
7004
7005 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
7006
7007 file = view->details->location_popup_directory_as_file;
7008 if (file == NULL((void*)0)) {
7009 return;
7010 }
7011
7012 caja_file_poll_for_media (file);
7013}
7014
7015static void
7016connect_to_server_response_callback (GtkDialog *dialog,
7017 int response_id,
7018 gpointer data)
7019{
7020#ifdef GIO_CONVERSION_DONE
7021 GtkEntry *entry;
7022 char *uri;
7023 const char *name;
7024 char *icon;
7025
7026 entry = GTK_ENTRY (data)((((GtkEntry*) (void *) ((data)))));
7027
7028 switch (response_id) {
7029 case GTK_RESPONSE_OK:
7030 uri = g_object_get_data (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "link-uri");
7031 icon = g_object_get_data (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "link-icon");
7032 name = gtk_entry_get_text (entry);
7033 mate_vfs_connect_to_server (uri, (char *)name, icon);
7034 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
7035 break;
7036 case GTK_RESPONSE_NONE:
7037 case GTK_RESPONSE_DELETE_EVENT:
7038 case GTK_RESPONSE_CANCEL:
7039 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
7040 break;
7041 default :
7042 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 7042, ((const char*) (__func__)), ((void*)0)); } while (0)
;
7043 }
7044#endif
7045 /* FIXME: the above code should make a server connection permanent */
7046 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
7047}
7048
7049static void
7050entry_activate_callback (GtkEntry *entry,
7051 gpointer user_data)
7052{
7053 GtkDialog *dialog;
7054
7055 dialog = GTK_DIALOG (user_data)((((GtkDialog*) (void *) ((user_data)))));
7056 gtk_dialog_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_OK);
7057}
7058
7059static void
7060action_connect_to_server_link_callback (GtkAction *action,
7061 gpointer data)
7062{
7063 CajaFile *file;
7064 GList *selection;
7065 FMDirectoryView *view;
7066 char *uri;
7067 CajaIconInfo *icon;
7068 const char *icon_name;
7069 char *name;
7070 gint scale;
7071
7072 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
7073
7074 selection = fm_directory_view_get_selection (view);
7075
7076 if (!eel_g_list_exactly_one_item (selection)) {
7077 caja_file_list_free (selection);
7078 return;
7079 }
7080
7081 file = CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data)))));
7082 scale = gtk_widget_get_scale_factor (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
7083
7084 uri = caja_file_get_activation_uri (file);
7085 icon = caja_file_get_icon (file, CAJA_ICON_SIZE_STANDARD48, scale, 0);
7086 icon_name = caja_icon_info_get_used_name (icon);
7087 name = caja_file_get_display_name (file);
7088
7089 if (uri != NULL((void*)0)) {
7090 GtkWidget *dialog;
7091 GtkWidget *label;
7092 GtkWidget *entry;
7093 GtkWidget *box;
7094 char *title;
7095
7096 title = g_strdup_printf (_("Connect to Server %s")dcgettext (((void*)0), "Connect to Server %s", 5), name);
7097
7098 dialog = gtk_dialog_new ();
7099 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), title);
7100 gtk_window_set_transient_for (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), fm_directory_view_get_containing_window (view));
7101
7102 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
7103 _("_Cancel")dcgettext (((void*)0), "_Cancel", 5),
7104 "process-stop",
7105 GTK_RESPONSE_CANCEL);
7106
7107 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
7108 _("_Connect")dcgettext (((void*)0), "_Connect", 5),
7109 GTK_RESPONSE_OK);
7110
7111 g_object_set_data_full (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "link-uri", g_strdup (uri)g_strdup_inline (uri), g_free);
7112 g_object_set_data_full (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "link-icon", g_strdup (icon_name)g_strdup_inline (icon_name), g_free);
7113
7114 gtk_container_set_border_width (GTK_CONTAINER (dialog)((((GtkContainer*) (void *) ((dialog))))), 5);
7115 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dialog)))))))))))
, 2);
7116
7117 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
7118 gtk_widget_show (box);
7119 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dialog)))))))))))
,
7120 box, TRUE(!(0)), TRUE(!(0)), 0);
7121
7122 label = gtk_label_new_with_mnemonic (_("Link _name:")dcgettext (((void*)0), "Link _name:", 5));
7123 gtk_widget_show (label);
7124
7125 gtk_box_pack_start (GTK_BOX (box)((((GtkBox*) (void *) ((box))))), label, TRUE(!(0)), TRUE(!(0)), 12);
7126
7127 entry = gtk_entry_new ();
7128 if (name) {
7129 gtk_entry_set_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))), name);
7130 }
7131 g_signal_connect (entry,g_signal_connect_data ((entry), ("activate"), (((GCallback) (
entry_activate_callback))), (dialog), ((void*)0), (GConnectFlags
) 0)
7132 "activate",g_signal_connect_data ((entry), ("activate"), (((GCallback) (
entry_activate_callback))), (dialog), ((void*)0), (GConnectFlags
) 0)
7133 G_CALLBACK (entry_activate_callback),g_signal_connect_data ((entry), ("activate"), (((GCallback) (
entry_activate_callback))), (dialog), ((void*)0), (GConnectFlags
) 0)
7134 dialog)g_signal_connect_data ((entry), ("activate"), (((GCallback) (
entry_activate_callback))), (dialog), ((void*)0), (GConnectFlags
) 0)
;
7135
7136 gtk_widget_show (entry);
7137 gtk_label_set_mnemonic_widget (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), entry);
7138
7139 gtk_box_pack_start (GTK_BOX (box)((((GtkBox*) (void *) ((box))))), entry, TRUE(!(0)), TRUE(!(0)), 12);
7140
7141 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
7142 GTK_RESPONSE_OK);
7143 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
connect_to_server_response_callback))), (entry), ((void*)0), (
GConnectFlags) 0)
7144 G_CALLBACK (connect_to_server_response_callback),g_signal_connect_data ((dialog), ("response"), (((GCallback) (
connect_to_server_response_callback))), (entry), ((void*)0), (
GConnectFlags) 0)
7145 entry)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
connect_to_server_response_callback))), (entry), ((void*)0), (
GConnectFlags) 0)
;
7146 gtk_widget_show (dialog);
7147 }
7148
7149 g_free (uri);
7150 g_object_unref (icon);
7151 g_free (name);
7152}
7153
7154static void
7155action_location_open_alternate_callback (GtkAction *action,
7156 gpointer callback_data)
7157{
7158 FMDirectoryView *view;
7159 CajaFile *file;
7160
7161 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7162
7163 file = view->details->location_popup_directory_as_file;
7164 if (file == NULL((void*)0)) {
7165 return;
7166 }
7167
7168 fm_directory_view_activate_file (view,
7169 file,
7170 CAJA_WINDOW_OPEN_IN_NAVIGATION,
7171 0);
7172}
7173
7174static void
7175action_location_open_in_new_tab_callback (GtkAction *action,
7176 gpointer callback_data)
7177{
7178 FMDirectoryView *view;
7179 CajaFile *file;
7180
7181 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7182
7183 file = view->details->location_popup_directory_as_file;
7184 if (file == NULL((void*)0)) {
7185 return;
7186 }
7187
7188 fm_directory_view_activate_file (view,
7189 file,
7190 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
7191 CAJA_WINDOW_OPEN_FLAG_NEW_TAB);
7192}
7193
7194static void
7195action_location_open_folder_window_callback (GtkAction *action,
7196 gpointer callback_data)
7197{
7198 FMDirectoryView *view;
7199 CajaFile *file;
7200
7201 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7202
7203 file = view->details->location_popup_directory_as_file;
7204 g_return_if_fail (file != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_271
; if (file != ((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__)), "file != NULL"); return
; } } while (0)
;
7205
7206 fm_directory_view_activate_file (view,
7207 file,
7208 CAJA_WINDOW_OPEN_IN_SPATIAL,
7209 0);
7210}
7211
7212static void
7213action_location_cut_callback (GtkAction *action,
7214 gpointer callback_data)
7215{
7216 FMDirectoryView *view;
7217 CajaFile *file;
7218 GList *files;
7219
7220 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7221
7222 file = view->details->location_popup_directory_as_file;
7223 g_return_if_fail (file != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if (file != ((void*)0)) _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__)), "file != NULL"); return
; } } while (0)
;
7224
7225 files = g_list_append (NULL((void*)0), file);
7226 copy_or_cut_files (view, files, TRUE(!(0)));
7227 g_list_free (files);
7228}
7229
7230static void
7231action_location_copy_callback (GtkAction *action,
7232 gpointer callback_data)
7233{
7234 FMDirectoryView *view;
7235 CajaFile *file;
7236 GList *files;
7237
7238 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7239
7240 file = view->details->location_popup_directory_as_file;
7241 g_return_if_fail (file != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_273
; if (file != ((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__)), "file != NULL"); return
; } } while (0)
;
7242
7243 files = g_list_append (NULL((void*)0), file);
7244 copy_or_cut_files (view, files, FALSE(0));
7245 g_list_free (files);
7246}
7247
7248static void
7249action_location_paste_files_into_callback (GtkAction *action,
7250 gpointer callback_data)
7251{
7252 FMDirectoryView *view;
7253 CajaFile *file;
7254
7255 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7256
7257 file = view->details->location_popup_directory_as_file;
7258 g_return_if_fail (file != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_274
; if (file != ((void*)0)) _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__)), "file != NULL"); return
; } } while (0)
;
7259
7260 paste_into (view, file);
7261}
7262
7263static void
7264action_location_trash_callback (GtkAction *action,
7265 gpointer callback_data)
7266{
7267 FMDirectoryView *view;
7268 CajaFile *file;
7269 GList *files;
7270
7271 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7272
7273 file = view->details->location_popup_directory_as_file;
7274 g_return_if_fail (file != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_275
; if (file != ((void*)0)) _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__)), "file != NULL"); return
; } } while (0)
;
7275
7276 files = g_list_append (NULL((void*)0), file);
7277 trash_or_delete_files (fm_directory_view_get_containing_window (view),
7278 files, TRUE(!(0)),
7279 view);
7280 g_list_free (files);
7281}
7282
7283static void
7284action_location_delete_callback (GtkAction *action,
7285 gpointer callback_data)
7286{
7287 FMDirectoryView *view;
7288 CajaFile *file;
7289 GFile *location;
7290 GList *files;
7291
7292 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7293
7294 file = view->details->location_popup_directory_as_file;
7295 g_return_if_fail (file != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_276
; if (file != ((void*)0)) _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__)), "file != NULL"); return
; } } while (0)
;
7296
7297 location = caja_file_get_location (file);
7298
7299 files = g_list_append (NULL((void*)0), location);
7300 caja_file_operations_delete (files, fm_directory_view_get_containing_window (view),
7301 NULL((void*)0), NULL((void*)0));
7302
7303 g_list_free_full (files, g_object_unref);
7304}
7305
7306static void
7307action_location_restore_from_trash_callback (GtkAction *action,
7308 gpointer callback_data)
7309{
7310 FMDirectoryView *view;
7311 CajaFile *file;
7312 GList l;
7313
7314 view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
7315 file = view->details->location_popup_directory_as_file;
7316
7317 l.prev = NULL((void*)0);
7318 l.next = NULL((void*)0);
7319 l.data = file;
7320 caja_restore_files_from_trash (&l,
7321 fm_directory_view_get_containing_window (view));
7322}
7323
7324static void
7325fm_directory_view_init_show_hidden_files (FMDirectoryView *view)
7326{
7327 CajaWindowShowHiddenFilesMode mode;
7328 gboolean show_hidden_changed;
7329 gboolean show_hidden_default_setting;
7330
7331 if (view->details->ignore_hidden_file_preferences) {
7332 return;
7333 }
7334
7335 show_hidden_changed = FALSE(0);
7336 mode = caja_window_info_get_hidden_files_mode (view->details->window);
7337
7338 if (mode == CAJA_WINDOW_SHOW_HIDDEN_FILES_DEFAULT) {
7339 show_hidden_default_setting = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_HIDDEN_FILES"show-hidden-files");
7340 if (show_hidden_default_setting != view->details->show_hidden_files) {
7341 view->details->show_hidden_files = show_hidden_default_setting;
7342 show_hidden_changed = TRUE(!(0));
7343 }
7344 } else {
7345 if (mode == CAJA_WINDOW_SHOW_HIDDEN_FILES_ENABLE) {
7346 show_hidden_changed = !view->details->show_hidden_files;
7347 view->details->show_hidden_files = TRUE(!(0));
7348 } else {
7349 show_hidden_changed = view->details->show_hidden_files;
7350 view->details->show_hidden_files = FALSE(0);
7351 }
7352 }
7353
7354 if (show_hidden_changed && (view->details->model != NULL((void*)0))) {
7355 load_directory (view, view->details->model);
7356 }
7357
7358}
7359
7360static void
7361fm_directory_view_init_show_backup_files (FMDirectoryView *view)
7362{
7363 CajaWindowShowBackupFilesMode mode;
7364 gboolean show_backup_changed;
7365 gboolean show_backup_default_setting;
7366
7367 show_backup_changed = FALSE(0);
7368 mode = caja_window_info_get_backup_files_mode (view->details->window);
7369
7370 if (mode == CAJA_WINDOW_SHOW_BACKUP_FILES_DEFAULT) {
7371 show_backup_default_setting = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_BACKUP_FILES"show-backup-files");
7372 if (show_backup_default_setting != view->details->show_backup_files) {
7373 view->details->show_backup_files = show_backup_default_setting;
7374 show_backup_changed = TRUE(!(0));
7375 }
7376 } else {
7377 if (mode == CAJA_WINDOW_SHOW_BACKUP_FILES_ENABLE) {
7378 show_backup_changed = !view->details->show_backup_files;
7379 view->details->show_backup_files = TRUE(!(0));
7380 } else {
7381 show_backup_changed = view->details->show_backup_files;
7382 view->details->show_backup_files = FALSE(0);
7383 }
7384 }
7385
7386 if (show_backup_changed && (view->details->model != NULL((void*)0))) {
7387 load_directory (view, view->details->model);
7388 }
7389
7390}
7391
7392static const GtkActionEntry directory_view_entries[] = {
7393 /* name, icon name, label */ { "New Documents", "document-new", N_("Create _Document")("Create _Document"),
7394 NULL((void*)0), NULL((void*)0), NULL((void*)0) },
7395 /* name, icon name, label */ { "Open With", NULL((void*)0), N_("Open Wit_h")("Open Wit_h"),
7396 NULL((void*)0), N_("Choose a program with which to open the selected item")("Choose a program with which to open the selected item"), NULL((void*)0) },
7397 /* name, icon name */ { "Properties", "document-properties",
7398 /* label, accelerator */ N_("_Properties")("_Properties"), "<alt>Return",
7399 /* tooltip */ N_("View or modify the properties of each selected item")("View or modify the properties of each selected item"),
7400 G_CALLBACK (action_properties_callback)((GCallback) (action_properties_callback)) },
7401 /* name, icon name */ { "PropertiesAccel", NULL((void*)0),
7402 /* label, accelerator */ "PropertiesAccel", "<control>I",
7403 /* tooltip */ NULL((void*)0),
7404 G_CALLBACK (action_properties_callback)((GCallback) (action_properties_callback)) },
7405 /* name, icon name */ { "New Folder", "folder-new",
7406 /* label, accelerator */ N_("Create _Folder")("Create _Folder"), "<control><shift>N",
7407 /* tooltip */ N_("Create a new empty folder inside this folder")("Create a new empty folder inside this folder"),
7408 G_CALLBACK (action_new_folder_callback)((GCallback) (action_new_folder_callback)) },
7409 /* name, icon name, label */ { "No Templates", NULL((void*)0), N_("No templates installed")("No templates installed"), NULL((void*)0), NULL((void*)0), NULL((void*)0) },
7410 /* name, icon name */ { "New Empty File", NULL((void*)0),
7411 /* Translators: this is used to indicate that a file doesn't contain anything */
7412 /* label, accelerator */ N_("_Empty File")("_Empty File"), NULL((void*)0),
7413 /* tooltip */ N_("Create a new empty file inside this folder")("Create a new empty file inside this folder"),
7414 G_CALLBACK (action_new_empty_file_callback)((GCallback) (action_new_empty_file_callback)) },
7415 /* name, icon name */ { "New Launcher", NULL((void*)0),
7416 /* label, accelerator */ N_("Create L_auncher...")("Create L_auncher..."), NULL((void*)0),
7417 /* tooltip */ N_("Create a new launcher")("Create a new launcher"),
7418 G_CALLBACK (action_new_launcher_callback)((GCallback) (action_new_launcher_callback)) },
7419 /* name, icon name */ { "Open", NULL((void*)0),
7420 /* label, accelerator */ N_("_Open")("_Open"), "<control>o",
7421 /* tooltip */ N_("Open the selected item in this window")("Open the selected item in this window"),
7422 G_CALLBACK (action_open_callback)((GCallback) (action_open_callback)) },
7423 /* name, icon name */ { "OpenAccel", NULL((void*)0),
7424 /* label, accelerator */ "OpenAccel", "<alt>Down",
7425 /* tooltip */ NULL((void*)0),
7426 G_CALLBACK (action_open_callback)((GCallback) (action_open_callback)) },
7427 /* name, icon name */ { "OpenAlternate", NULL((void*)0),
7428 /* label, accelerator */ N_("Open in Navigation Window")("Open in Navigation Window"), "<control><shift>w",
7429 /* tooltip */ N_("Open each selected item in a navigation window")("Open each selected item in a navigation window"),
7430 G_CALLBACK (action_open_alternate_callback)((GCallback) (action_open_alternate_callback)) },
7431 /* name, icon name */ { "OpenInNewTab", NULL((void*)0),
7432 /* label, accelerator */ N_("Open in New _Tab")("Open in New _Tab"), "<control><shift>o",
7433 /* tooltip */ N_("Open each selected item in a new tab")("Open each selected item in a new tab"),
7434 G_CALLBACK (action_open_new_tab_callback)((GCallback) (action_open_new_tab_callback)) },
7435 /* name, icon name */ { "OpenFolderWindow", NULL((void*)0),
7436 /* label, accelerator */ N_("Open in _Folder Window")("Open in _Folder Window"), NULL((void*)0),
7437 /* tooltip */ N_("Open each selected item in a folder window")("Open each selected item in a folder window"),
7438 G_CALLBACK (action_open_folder_window_callback)((GCallback) (action_open_folder_window_callback)) },
7439 /* name, icon name */ { "OtherApplication1", NULL((void*)0),
7440 /* label, accelerator */ N_("Other _Application...")("Other _Application..."), NULL((void*)0),
7441 /* tooltip */ N_("Choose another application with which to open the selected item")("Choose another application with which to open the selected item"
)
,
7442 G_CALLBACK (action_other_application_callback)((GCallback) (action_other_application_callback)) },
7443 /* name, icon name */ { "OtherApplication2", NULL((void*)0),
7444 /* label, accelerator */ N_("Open With Other _Application...")("Open With Other _Application..."), NULL((void*)0),
7445 /* tooltip */ N_("Choose another application with which to open the selected item")("Choose another application with which to open the selected item"
)
,
7446 G_CALLBACK (action_other_application_callback)((GCallback) (action_other_application_callback)) },
7447 /* name, icon name */ { "Open Scripts Folder", NULL((void*)0),
7448 /* label, accelerator */ N_("_Open Scripts Folder")("_Open Scripts Folder"), NULL((void*)0),
7449 /* tooltip */ N_("Show the folder containing the scripts that appear in this menu")("Show the folder containing the scripts that appear in this menu"
)
,
7450 G_CALLBACK (action_open_scripts_folder_callback)((GCallback) (action_open_scripts_folder_callback)) },
7451 /* name, icon name */ { "Empty Trash", CAJA_ICON_TRASH"user-trash",
7452 /* label, accelerator */ N_("E_mpty Trash")("E_mpty Trash"), NULL((void*)0),
7453 /* tooltip */ N_("Delete all items in the Trash")("Delete all items in the Trash"),
7454 G_CALLBACK (action_empty_trash_callback)((GCallback) (action_empty_trash_callback)) },
7455 /* name, icon name */ { "Cut", "edit-cut",
7456 /* label, accelerator */ N_("Cu_t")("Cu_t"), "<control>X",
7457 /* tooltip */ N_("Prepare the selected files to be moved with a Paste command")("Prepare the selected files to be moved with a Paste command"
)
,
7458 G_CALLBACK (action_cut_files_callback)((GCallback) (action_cut_files_callback)) },
7459 /* name, icon name */ { "Copy", "edit-copy",
7460 /* label, accelerator */ N_("_Copy")("_Copy"), "<control>C",
7461 /* tooltip */ N_("Prepare the selected files to be copied with a Paste command")("Prepare the selected files to be copied with a Paste command"
)
,
7462 G_CALLBACK (action_copy_files_callback)((GCallback) (action_copy_files_callback)) },
7463 /* name, icon name */ { "Paste", "edit-paste",
7464 /* label, accelerator */ N_("_Paste")("_Paste"), "<control>V",
7465 /* tooltip */ N_("Move or copy files previously selected by a Cut or Copy command")("Move or copy files previously selected by a Cut or Copy command"
)
,
7466 G_CALLBACK (action_paste_files_callback)((GCallback) (action_paste_files_callback)) },
7467 /* We make accelerator "" instead of null here to not inherit the stock
7468 accelerator for paste */
7469 /* name, icon name */ { "Paste Files Into", "edit-paste",
7470 /* label, accelerator */ N_("_Paste Into Folder")("_Paste Into Folder"), "",
7471 /* tooltip */ N_("Move or copy files previously selected by a Cut or Copy command into the selected folder")("Move or copy files previously selected by a Cut or Copy command into the selected folder"
)
,
7472 G_CALLBACK (action_paste_files_into_callback)((GCallback) (action_paste_files_into_callback)) },
7473 /* name, icon name, label */ { "CopyToMenu", NULL((void*)0), N_("Cop_y to")("Cop_y to"),
7474 NULL((void*)0), NULL((void*)0), NULL((void*)0) },
7475 /* name, icon name, label */ { "MoveToMenu", NULL((void*)0), N_("M_ove to")("M_ove to"),
7476 NULL((void*)0), NULL((void*)0), NULL((void*)0) },
7477 /* name, icon name */ { "Select All", NULL((void*)0),
7478 /* label, accelerator */ N_("Select _All")("Select _All"), "<control>A",
7479 /* tooltip */ N_("Select all items in this window")("Select all items in this window"),
7480 G_CALLBACK (action_select_all_callback)((GCallback) (action_select_all_callback)) },
7481 /* name, icon name */ { "Select Pattern", NULL((void*)0),
7482 /* label, accelerator */ N_("Select I_tems Matching...")("Select I_tems Matching..."), "<control>S",
7483 /* tooltip */ N_("Select items in this window matching a given pattern")("Select items in this window matching a given pattern"),
7484 G_CALLBACK (action_select_pattern_callback)((GCallback) (action_select_pattern_callback)) },
7485 /* name, icon name */ { "Invert Selection", NULL((void*)0),
7486 /* label, accelerator */ N_("_Invert Selection")("_Invert Selection"), "<control><shift>I",
7487 /* tooltip */ N_("Select all and only the items that are not currently selected")("Select all and only the items that are not currently selected"
)
,
7488 G_CALLBACK (action_invert_selection_callback)((GCallback) (action_invert_selection_callback)) },
7489 /* name, icon name */ { "Duplicate", NULL((void*)0),
7490 /* label, accelerator */ N_("D_uplicate")("D_uplicate"), NULL((void*)0),
7491 /* tooltip */ N_("Duplicate each selected item")("Duplicate each selected item"),
7492 G_CALLBACK (action_duplicate_callback)((GCallback) (action_duplicate_callback)) },
7493 /* name, icon name */ { "Create Link", NULL((void*)0),
7494 /* label, accelerator */ N_("Ma_ke Link")("Ma_ke Link"), "<control>M",
7495 /* tooltip */ N_("Create a symbolic link for each selected item")("Create a symbolic link for each selected item"),
7496 G_CALLBACK (action_create_link_callback)((GCallback) (action_create_link_callback)) },
7497 /* name, icon name */ { "Rename", NULL((void*)0),
7498 /* label, accelerator */ N_("_Rename...")("_Rename..."), "F2",
7499 /* tooltip */ N_("Rename selected item")("Rename selected item"),
7500 G_CALLBACK (action_rename_callback)((GCallback) (action_rename_callback)) },
7501 /* name, icon name */ { "RenameSelectAll", NULL((void*)0),
7502 /* label, accelerator */ "RenameSelectAll", "<shift>F2",
7503 /* tooltip */ NULL((void*)0),
7504 G_CALLBACK (action_rename_select_all_callback)((GCallback) (action_rename_select_all_callback)) },
7505 /* name, icon name */ { "Trash", NULL((void*)0),
7506 /* label, accelerator */ N_("Mo_ve to Trash")("Mo_ve to Trash"), NULL((void*)0),
7507 /* tooltip */ N_("Move each selected item to the Trash")("Move each selected item to the Trash"),
7508 G_CALLBACK (action_trash_callback)((GCallback) (action_trash_callback)) },
7509 /* name, icon name */ { "Delete", NULL((void*)0),
7510 /* label, accelerator */ N_("_Delete")("_Delete"), NULL((void*)0),
7511 /* tooltip */ N_("Delete each selected item, without moving to the Trash")("Delete each selected item, without moving to the Trash"),
7512 G_CALLBACK (action_delete_callback)((GCallback) (action_delete_callback)) },
7513 /* name, icon name */ { "Restore From Trash", NULL((void*)0),
7514 /* label, accelerator */ N_("_Restore")("_Restore"), NULL((void*)0),
7515 NULL((void*)0),
7516 G_CALLBACK (action_restore_from_trash_callback)((GCallback) (action_restore_from_trash_callback)) },
7517 /* name, icon name */ { FM_ACTION_UNDO"Undo", "edit-undo",
7518 /* label, accelerator */ N_("_Undo")("_Undo"), "<control>Z",
7519 /* tooltip */ N_("Undo the last action")("Undo the last action"),
7520 G_CALLBACK (action_undo_callback)((GCallback) (action_undo_callback)) },
7521 /* name, icon name */ { FM_ACTION_REDO"Redo", "edit-redo",
7522 /* label, accelerator */ N_("_Redo")("_Redo"), "<control>Y",
7523 /* tooltip */ N_("Redo the last undone action")("Redo the last undone action"),
7524 G_CALLBACK (action_redo_callback)((GCallback) (action_redo_callback)) },
7525
7526 /*
7527 * multiview-TODO: decide whether "Reset to Defaults" should
7528 * be window-wide, and not just view-wide.
7529 * Since this also resets the "Show hidden files" mode,
7530 * it is a mixture of both ATM.
7531 */
7532 /* name, icon name */ { "Reset to Defaults", NULL((void*)0),
7533 /* label, accelerator */ N_("Reset View to _Defaults")("Reset View to _Defaults"), NULL((void*)0),
7534 /* tooltip */ N_("Reset sorting order and zoom level to match preferences for this view")("Reset sorting order and zoom level to match preferences for this view"
)
,
7535 G_CALLBACK (action_reset_to_defaults_callback)((GCallback) (action_reset_to_defaults_callback)) },
7536 /* name, icon name */ { "Connect To Server Link", NULL((void*)0),
7537 /* label, accelerator */ N_("Connect To This Server")("Connect To This Server"), NULL((void*)0),
7538 /* tooltip */ N_("Make a permanent connection to this server")("Make a permanent connection to this server"),
7539 G_CALLBACK (action_connect_to_server_link_callback)((GCallback) (action_connect_to_server_link_callback)) },
7540 /* name, icon name */ { "Mount Volume", NULL((void*)0),
7541 /* label, accelerator */ N_("_Mount")("_Mount"), NULL((void*)0),
7542 /* tooltip */ N_("Mount the selected volume")("Mount the selected volume"),
7543 G_CALLBACK (action_mount_volume_callback)((GCallback) (action_mount_volume_callback)) },
7544 /* name, icon name */ { "Unmount Volume", NULL((void*)0),
7545 /* label, accelerator */ N_("_Unmount")("_Unmount"), NULL((void*)0),
7546 /* tooltip */ N_("Unmount the selected volume")("Unmount the selected volume"),
7547 G_CALLBACK (action_unmount_volume_callback)((GCallback) (action_unmount_volume_callback)) },
7548 /* name, icon name */ { "Eject Volume", NULL((void*)0),
7549 /* label, accelerator */ N_("_Eject")("_Eject"), NULL((void*)0),
7550 /* tooltip */ N_("Eject the selected volume")("Eject the selected volume"),
7551 G_CALLBACK (action_eject_volume_callback)((GCallback) (action_eject_volume_callback)) },
7552 /* name, icon name */ { "Format Volume", NULL((void*)0),
7553 /* label, accelerator */ N_("_Format")("_Format"), NULL((void*)0),
7554 /* tooltip */ N_("Format the selected volume")("Format the selected volume"),
7555 G_CALLBACK (action_format_volume_callback)((GCallback) (action_format_volume_callback)) },
7556 /* name, icon name */ { "Start Volume", NULL((void*)0),
7557 /* label, accelerator */ N_("_Start")("_Start"), NULL((void*)0),
7558 /* tooltip */ N_("Start the selected volume")("Start the selected volume"),
7559 G_CALLBACK (action_start_volume_callback)((GCallback) (action_start_volume_callback)) },
7560 /* name, icon name */ { "Stop Volume", NULL((void*)0),
7561 /* label, accelerator */ N_("_Stop")("_Stop"), NULL((void*)0),
7562 /* tooltip */ N_("Stop the selected volume")("Stop the selected volume"),
7563 G_CALLBACK (action_stop_volume_callback)((GCallback) (action_stop_volume_callback)) },
7564 /* name, icon name */ { "Poll", NULL((void*)0),
7565 /* label, accelerator */ N_("_Detect Media")("_Detect Media"), NULL((void*)0),
7566 /* tooltip */ N_("Detect media in the selected drive")("Detect media in the selected drive"),
7567 G_CALLBACK (action_detect_media_callback)((GCallback) (action_detect_media_callback)) },
7568 /* name, icon name */ { "Self Mount Volume", NULL((void*)0),
7569 /* label, accelerator */ N_("_Mount")("_Mount"), NULL((void*)0),
7570 /* tooltip */ N_("Mount the volume associated with the open folder")("Mount the volume associated with the open folder"),
7571 G_CALLBACK (action_self_mount_volume_callback)((GCallback) (action_self_mount_volume_callback)) },
7572 /* name, icon name */ { "Self Unmount Volume", NULL((void*)0),
7573 /* label, accelerator */ N_("_Unmount")("_Unmount"), NULL((void*)0),
7574 /* tooltip */ N_("Unmount the volume associated with the open folder")("Unmount the volume associated with the open folder"),
7575 G_CALLBACK (action_self_unmount_volume_callback)((GCallback) (action_self_unmount_volume_callback)) },
7576 /* name, icon name */ { "Self Eject Volume", NULL((void*)0),
7577 /* label, accelerator */ N_("_Eject")("_Eject"), NULL((void*)0),
7578 /* tooltip */ N_("Eject the volume associated with the open folder")("Eject the volume associated with the open folder"),
7579 G_CALLBACK (action_self_eject_volume_callback)((GCallback) (action_self_eject_volume_callback)) },
7580 /* name, icon name */ { "Self Format Volume", NULL((void*)0),
7581 /* label, accelerator */ N_("_Format")("_Format"), NULL((void*)0),
7582 /* tooltip */ N_("Format the volume associated with the open folder")("Format the volume associated with the open folder"),
7583 G_CALLBACK (action_self_format_volume_callback)((GCallback) (action_self_format_volume_callback)) },
7584 /* name, icon name */ { "Self Start Volume", NULL((void*)0),
7585 /* label, accelerator */ N_("_Start")("_Start"), NULL((void*)0),
7586 /* tooltip */ N_("Start the volume associated with the open folder")("Start the volume associated with the open folder"),
7587 G_CALLBACK (action_self_start_volume_callback)((GCallback) (action_self_start_volume_callback)) },
7588 /* name, icon name */ { "Self Stop Volume", NULL((void*)0),
7589 /* label, accelerator */ N_("_Stop")("_Stop"), NULL((void*)0),
7590 /* tooltip */ N_("Stop the volume associated with the open folder")("Stop the volume associated with the open folder"),
7591 G_CALLBACK (action_self_stop_volume_callback)((GCallback) (action_self_stop_volume_callback)) },
7592 /* name, icon name */ { "Self Poll", NULL((void*)0),
7593 /* label, accelerator */ N_("_Detect Media")("_Detect Media"), NULL((void*)0),
7594 /* tooltip */ N_("Detect media in the selected drive")("Detect media in the selected drive"),
7595 G_CALLBACK (action_self_detect_media_callback)((GCallback) (action_self_detect_media_callback)) },
7596 /* name, icon name */ { "OpenCloseParent", NULL((void*)0),
7597 /* label, accelerator */ N_("Open File and Close window")("Open File and Close window"), "<alt><shift>Down",
7598 /* tooltip */ NULL((void*)0),
7599 G_CALLBACK (action_open_close_parent_callback)((GCallback) (action_open_close_parent_callback)) },
7600 /* name, icon name */ { "Save Search", NULL((void*)0),
7601 /* label, accelerator */ N_("Sa_ve Search")("Sa_ve Search"), NULL((void*)0),
7602 /* tooltip */ N_("Save the edited search")("Save the edited search"),
7603 G_CALLBACK (action_save_search_callback)((GCallback) (action_save_search_callback)) },
7604 /* name, icon name */ { "Save Search As", NULL((void*)0),
7605 /* label, accelerator */ N_("Sa_ve Search As...")("Sa_ve Search As..."), NULL((void*)0),
7606 /* tooltip */ N_("Save the current search as a file")("Save the current search as a file"),
7607 G_CALLBACK (action_save_search_as_callback)((GCallback) (action_save_search_as_callback)) },
7608
7609 /* Location-specific actions */
7610 /* name, icon name */ { FM_ACTION_LOCATION_OPEN_ALTERNATE"LocationOpenAlternate", NULL((void*)0),
7611 /* label, accelerator */ N_("Open in Navigation Window")("Open in Navigation Window"), "",
7612 /* tooltip */ N_("Open this folder in a navigation window")("Open this folder in a navigation window"),
7613 G_CALLBACK (action_location_open_alternate_callback)((GCallback) (action_location_open_alternate_callback)) },
7614 /* name, icon name */ { FM_ACTION_LOCATION_OPEN_IN_NEW_TAB"LocationOpenInNewTab", NULL((void*)0),
7615 /* label, accelerator */ N_("Open in New _Tab")("Open in New _Tab"), "",
7616 /* tooltip */ N_("Open this folder in a new tab")("Open this folder in a new tab"),
7617 G_CALLBACK (action_location_open_in_new_tab_callback)((GCallback) (action_location_open_in_new_tab_callback)) },
7618
7619 /* name, icon name */ { FM_ACTION_LOCATION_OPEN_FOLDER_WINDOW"LocationOpenFolderWindow", NULL((void*)0),
7620 /* label, accelerator */ N_("Open in _Folder Window")("Open in _Folder Window"), "",
7621 /* tooltip */ N_("Open this folder in a folder window")("Open this folder in a folder window"),
7622 G_CALLBACK (action_location_open_folder_window_callback)((GCallback) (action_location_open_folder_window_callback)) },
7623
7624 /* name, icon name */ { FM_ACTION_LOCATION_CUT"LocationCut", "edit-cut",
7625 /* label, accelerator */ N_("Cu_t")("Cu_t"), "",
7626 /* tooltip */ N_("Prepare this folder to be moved with a Paste command")("Prepare this folder to be moved with a Paste command"),
7627 G_CALLBACK (action_location_cut_callback)((GCallback) (action_location_cut_callback)) },
7628 /* name, icon name */ { FM_ACTION_LOCATION_COPY"LocationCopy", "edit-copy",
7629 /* label, accelerator */ N_("_Copy")("_Copy"), "",
7630 /* tooltip */ N_("Prepare this folder to be copied with a Paste command")("Prepare this folder to be copied with a Paste command"),
7631 G_CALLBACK (action_location_copy_callback)((GCallback) (action_location_copy_callback)) },
7632 /* name, icon name */ { FM_ACTION_LOCATION_PASTE_FILES_INTO"LocationPasteFilesInto", "edit-paste",
7633 /* label, accelerator */ N_("_Paste Into Folder")("_Paste Into Folder"), "",
7634 /* tooltip */ N_("Move or copy files previously selected by a Cut or Copy command into this folder")("Move or copy files previously selected by a Cut or Copy command into this folder"
)
,
7635 G_CALLBACK (action_location_paste_files_into_callback)((GCallback) (action_location_paste_files_into_callback)) },
7636
7637 /* name, icon name */ { FM_ACTION_LOCATION_TRASH"LocationTrash", NULL((void*)0),
7638 /* label, accelerator */ N_("Mo_ve to Trash")("Mo_ve to Trash"), "",
7639 /* tooltip */ N_("Move this folder to the Trash")("Move this folder to the Trash"),
7640 G_CALLBACK (action_location_trash_callback)((GCallback) (action_location_trash_callback)) },
7641 /* name, icon name */ { FM_ACTION_LOCATION_DELETE"LocationDelete", CAJA_ICON_DELETE"edit-delete",
7642 /* label, accelerator */ N_("_Delete")("_Delete"), "",
7643 /* tooltip */ N_("Delete this folder, without moving to the Trash")("Delete this folder, without moving to the Trash"),
7644 G_CALLBACK (action_location_delete_callback)((GCallback) (action_location_delete_callback)) },
7645 /* name, icon name */ { FM_ACTION_LOCATION_RESTORE_FROM_TRASH"LocationRestoreFromTrash", NULL((void*)0),
7646 /* label, accelerator */ N_("_Restore")("_Restore"), NULL((void*)0), NULL((void*)0),
7647 G_CALLBACK (action_location_restore_from_trash_callback)((GCallback) (action_location_restore_from_trash_callback)) },
7648
7649 /* name, icon name */ { "Location Mount Volume", NULL((void*)0),
7650 /* label, accelerator */ N_("_Mount")("_Mount"), NULL((void*)0),
7651 /* tooltip */ N_("Mount the volume associated with this folder")("Mount the volume associated with this folder"),
7652 G_CALLBACK (action_location_mount_volume_callback)((GCallback) (action_location_mount_volume_callback)) },
7653 /* name, icon name */ { "Location Unmount Volume", NULL((void*)0),
7654 /* label, accelerator */ N_("_Unmount")("_Unmount"), NULL((void*)0),
7655 /* tooltip */ N_("Unmount the volume associated with this folder")("Unmount the volume associated with this folder"),
7656 G_CALLBACK (action_location_unmount_volume_callback)((GCallback) (action_location_unmount_volume_callback)) },
7657 /* name, icon name */ { "Location Eject Volume", NULL((void*)0),
7658 /* label, accelerator */ N_("_Eject")("_Eject"), NULL((void*)0),
7659 /* tooltip */ N_("Eject the volume associated with this folder")("Eject the volume associated with this folder"),
7660 G_CALLBACK (action_location_eject_volume_callback)((GCallback) (action_location_eject_volume_callback)) },
7661 /* name, icon name */ { "Location Format Volume", NULL((void*)0),
7662 /* label, accelerator */ N_("_Format")("_Format"), NULL((void*)0),
7663 /* tooltip */ N_("Format the volume associated with this folder")("Format the volume associated with this folder"),
7664 G_CALLBACK (action_location_format_volume_callback)((GCallback) (action_location_format_volume_callback)) },
7665 /* name, icon name */ { "Location Start Volume", NULL((void*)0),
7666 /* label, accelerator */ N_("_Start")("_Start"), NULL((void*)0),
7667 /* tooltip */ N_("Start the volume associated with this folder")("Start the volume associated with this folder"),
7668 G_CALLBACK (action_location_start_volume_callback)((GCallback) (action_location_start_volume_callback)) },
7669 /* name, icon name */ { "Location Stop Volume", NULL((void*)0),
7670 /* label, accelerator */ N_("_Stop")("_Stop"), NULL((void*)0),
7671 /* tooltip */ N_("Stop the volume associated with this folder")("Stop the volume associated with this folder"),
7672 G_CALLBACK (action_location_stop_volume_callback)((GCallback) (action_location_stop_volume_callback)) },
7673 /* name, icon name */ { "Location Poll", NULL((void*)0),
7674 /* label, accelerator */ N_("_Detect Media")("_Detect Media"), NULL((void*)0),
7675 /* tooltip */ N_("Detect media in the selected drive")("Detect media in the selected drive"),
7676 G_CALLBACK (action_location_detect_media_callback)((GCallback) (action_location_detect_media_callback)) },
7677
7678 /* name, icon name */ { "LocationProperties", "document-properties",
7679 /* label, accelerator */ N_("_Properties")("_Properties"), NULL((void*)0),
7680 /* tooltip */ N_("View or modify the properties of this folder")("View or modify the properties of this folder"),
7681 G_CALLBACK (action_location_properties_callback)((GCallback) (action_location_properties_callback)) },
7682
7683 /* name, icon name, label */ {FM_ACTION_COPY_TO_NEXT_PANE"Copy to next pane", NULL((void*)0), N_("_Other pane")("_Other pane"),
7684 NULL((void*)0), N_("Copy the current selection to the other pane in the window")("Copy the current selection to the other pane in the window"
)
,
7685 G_CALLBACK (action_copy_to_next_pane_callback)((GCallback) (action_copy_to_next_pane_callback)) },
7686 /* name, icon name, label */ {FM_ACTION_MOVE_TO_NEXT_PANE"Move to next pane", NULL((void*)0), N_("_Other pane")("_Other pane"),
7687 NULL((void*)0), N_("Move the current selection to the other pane in the window")("Move the current selection to the other pane in the window"
)
,
7688 G_CALLBACK (action_move_to_next_pane_callback)((GCallback) (action_move_to_next_pane_callback)) },
7689 /* name, icon name, label */ {FM_ACTION_COPY_TO_HOME"Copy to Home", CAJA_ICON_HOME"user-home",
7690 N_("_Home Folder")("_Home Folder"), NULL((void*)0),
7691 N_("Copy the current selection to the home folder")("Copy the current selection to the home folder"),
7692 G_CALLBACK (action_copy_to_home_callback)((GCallback) (action_copy_to_home_callback)) },
7693 /* name, icon name, label */ {FM_ACTION_MOVE_TO_HOME"Move to Home", CAJA_ICON_HOME"user-home",
7694 N_("_Home Folder")("_Home Folder"), NULL((void*)0),
7695 N_("Move the current selection to the home folder")("Move the current selection to the home folder"),
7696 G_CALLBACK (action_move_to_home_callback)((GCallback) (action_move_to_home_callback)) },
7697 /* name, icon name, label */ {FM_ACTION_COPY_TO_DESKTOP"Copy to Desktop", CAJA_ICON_DESKTOP"user-desktop",
7698 N_("_Desktop")("_Desktop"), NULL((void*)0),
7699 N_("Copy the current selection to the desktop")("Copy the current selection to the desktop"),
7700 G_CALLBACK (action_copy_to_desktop_callback)((GCallback) (action_copy_to_desktop_callback)) },
7701 /* name, icon name, label */ {FM_ACTION_MOVE_TO_DESKTOP"Move to Desktop", CAJA_ICON_DESKTOP"user-desktop",
7702 N_("_Desktop")("_Desktop"), NULL((void*)0),
7703 N_("Move the current selection to the desktop")("Move the current selection to the desktop"),
7704 G_CALLBACK (action_move_to_desktop_callback)((GCallback) (action_move_to_desktop_callback)) },
7705};
7706
7707static void
7708connect_proxy (FMDirectoryView *view,
7709 GtkAction *action,
7710 GtkWidget *proxy,
7711 GtkActionGroup *action_group)
7712{
7713 const gchar *action_name;
7714
7715 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
7716 action_name = gtk_action_get_name (action);
7717 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
7718
7719 if (strcmp (action_name, FM_ACTION_NEW_EMPTY_FILE"New Empty File") == 0 &&
7720 GTK_IS_IMAGE_MENU_ITEM (proxy)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(proxy)); GType __t = ((gtk_image_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; }))))
) {
7721 cairo_surface_t *surface;
7722
7723 surface = get_menu_icon ("text-x-generic", GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
7724
7725 if (surface != NULL((void*)0)) {
7726 GtkWidget *image;
7727
7728 image = gtk_image_new_from_surface (surface);
7729 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy)((((GtkImageMenuItem*) (void *) ((proxy))))), image);
7730
7731 cairo_surface_destroy (surface);
7732 }
7733 }
7734}
7735
7736static void
7737pre_activate (FMDirectoryView *view,
7738 GtkAction *action,
7739 GtkActionGroup *action_group)
7740{
7741 GdkEvent *event;
7742 GtkWidget *proxy;
7743 gboolean activated_from_popup;
7744
7745 /* check whether action was activated through a popup menu.
7746 * If not, unset the last stored context menu popup position */
7747 activated_from_popup = FALSE(0);
7748
7749 event = gtk_get_current_event ();
7750 proxy = gtk_get_event_widget (event);
7751
7752 if (proxy != NULL((void*)0)) {
7753 GtkWidget *toplevel;
7754 GdkWindowTypeHint hint;
7755
7756 toplevel = gtk_widget_get_toplevel (proxy);
7757
7758 if (GTK_IS_WINDOW (toplevel)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(toplevel)); GType __t = ((gtk_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; }))))
) {
7759 hint = gtk_window_get_type_hint (GTK_WINDOW (toplevel)((((GtkWindow*) (void *) ((toplevel))))));
7760
7761 if (hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU) {
7762 activated_from_popup = TRUE(!(0));
7763 }
7764 }
7765 }
7766
7767 if (!activated_from_popup) {
7768 update_context_menu_position_from_event (view, NULL((void*)0));
7769 }
7770}
7771
7772static void
7773real_merge_menus (FMDirectoryView *view)
7774{
7775 GtkActionGroup *action_group;
7776 GtkUIManager *ui_manager;
7777 GtkAction *action;
7778 const char *ui;
7779 char *tooltip;
7780
7781 ui_manager = caja_window_info_get_ui_manager (view->details->window);
7782
7783 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
7784 action_group = gtk_action_group_new ("DirViewActions");
7785#ifdef ENABLE_NLS1
7786 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE"caja");
7787#endif /* ENABLE_NLS */
7788 view->details->dir_action_group = action_group;
7789 gtk_action_group_add_actions (action_group,
7790 directory_view_entries, G_N_ELEMENTS (directory_view_entries)(sizeof (directory_view_entries) / sizeof ((directory_view_entries
)[0]))
,
7791 view);
7792 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
7793
7794 /* Translators: %s is a directory */
7795 tooltip = g_strdup_printf(_("Run or manage scripts from %s")dcgettext (((void*)0), "Run or manage scripts from %s", 5), "~/.config/caja/scripts");
7796 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
7797 /* Create a script action here specially because its tooltip is dynamic */
7798 action = gtk_action_new ("Scripts", _("_Scripts")dcgettext (((void*)0), "_Scripts", 5), tooltip, NULL((void*)0));
7799 gtk_action_group_add_action (action_group, action);
7800 g_object_unref (action);
7801 g_free (tooltip);
7802
7803 action = gtk_action_group_get_action (action_group, FM_ACTION_NO_TEMPLATES"No Templates");
7804 gtk_action_set_sensitive (action, FALSE(0));
7805 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
7806
7807 g_signal_connect_object (action_group, "connect-proxy",
7808 G_CALLBACK (connect_proxy)((GCallback) (connect_proxy)), G_OBJECT (view)((((GObject*) (void *) ((view))))),
7809 G_CONNECT_SWAPPED);
7810 g_signal_connect_object (action_group, "pre-activate",
7811 G_CALLBACK (pre_activate)((GCallback) (pre_activate)), G_OBJECT (view)((((GObject*) (void *) ((view))))),
7812 G_CONNECT_SWAPPED);
7813
7814 /* Insert action group at end so clipboard action group ends up before it */
7815 gtk_ui_manager_insert_action_group (ui_manager, action_group, -1);
7816 g_object_unref (action_group); /* owned by ui manager */
7817
7818 ui = caja_ui_string_get ("caja-directory-view-ui.xml");
7819 view->details->dir_merge_id = gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL((void*)0));
7820 g_signal_connect_object (fm_directory_view_get_background (view), "settings_changed",
7821 G_CALLBACK (schedule_update_menus)((GCallback) (schedule_update_menus)), G_OBJECT (view)((((GObject*) (void *) ((view))))),
7822 G_CONNECT_SWAPPED);
7823 view->details->scripts_invalid = TRUE(!(0));
7824 view->details->templates_invalid = TRUE(!(0));
7825}
7826
7827
7828static gboolean
7829can_paste_into_file (CajaFile *file)
7830{
7831 if (caja_file_is_directory (file) &&
7832 caja_file_can_write (file)) {
7833 return TRUE(!(0));
7834 }
7835 if (caja_file_has_activation_uri (file)) {
7836 GFile *location;
7837 CajaFile *activation_file;
7838 gboolean res;
7839
7840 location = caja_file_get_activation_location (file);
7841 activation_file = caja_file_get (location);
7842 g_object_unref (location);
7843
7844 /* The target location might not have data for it read yet,
7845 and we can't want to do sync I/O, so treat the unknown
7846 case as can-write */
7847 res = (caja_file_get_file_type (activation_file) == G_FILE_TYPE_UNKNOWN) ||
7848 (caja_file_get_file_type (activation_file) == G_FILE_TYPE_DIRECTORY &&
7849 caja_file_can_write (activation_file));
7850
7851 caja_file_unref (activation_file);
7852
7853 return res;
7854 }
7855
7856 return FALSE(0);
7857}
7858
7859static void
7860clipboard_targets_received (GtkClipboard *clipboard,
7861 GdkAtom *targets,
7862 int n_targets,
7863 gpointer user_data)
7864{
7865 FMDirectoryView *view;
7866 gboolean can_paste;
7867 GList *selection;
7868 int count;
7869 GtkAction *action;
7870
7871 view = FM_DIRECTORY_VIEW (user_data)((((FMDirectoryView*) (void *) ((user_data)))));
7872 can_paste = FALSE(0);
7873
7874 if (view->details->window == NULL((void*)0) ||
7875 !view->details->active) {
7876 /* We've been destroyed or became inactive since call */
7877 g_object_unref (view);
7878 return;
7879 }
7880
7881 if (targets) {
7882 int i;
7883
7884 for (i=0; i < n_targets; i++) {
7885 if (targets[i] == copied_files_atom) {
7886 can_paste = TRUE(!(0));
7887 }
7888 }
7889 }
7890
7891
7892 selection = fm_directory_view_get_selection (view);
7893 count = g_list_length (selection);
7894
7895 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
7896 action = gtk_action_group_get_action (view->details->dir_action_group,
7897 FM_ACTION_PASTE"Paste");
7898 gtk_action_set_sensitive (action,
7899 can_paste && !fm_directory_view_is_read_only (view));
7900
7901 action = gtk_action_group_get_action (view->details->dir_action_group,
7902 FM_ACTION_PASTE_FILES_INTO"Paste Files Into");
7903 gtk_action_set_sensitive (action,
7904 can_paste && count == 1 &&
7905 can_paste_into_file (CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data)))))));
7906
7907 action = gtk_action_group_get_action (view->details->dir_action_group,
7908 FM_ACTION_LOCATION_PASTE_FILES_INTO"LocationPasteFilesInto");
7909 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
7910 g_object_set_data (G_OBJECT (action)((((GObject*) (void *) ((action))))),
7911 "can-paste-according-to-clipboard",
7912 GINT_TO_POINTER (can_paste)((gpointer) (glong) (can_paste)));
7913 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
7914 gtk_action_set_sensitive (action,
7915 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-clipboard")))
7916 "can-paste-according-to-clipboard"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-clipboard")))
&&
7917 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-destination")))
7918 "can-paste-according-to-destination"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-destination")))
);
7919 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
7920
7921 caja_file_list_free (selection);
7922
7923 g_object_unref (view);
7924}
7925
7926static gboolean
7927showing_trash_directory (FMDirectoryView *view)
7928{
7929 CajaFile *file;
7930
7931 file = fm_directory_view_get_directory_as_file (view);
7932 if (file != NULL((void*)0)) {
7933 return caja_file_is_in_trash (file);
7934 }
7935 return FALSE(0);
7936}
7937
7938static gboolean
7939should_show_empty_trash (FMDirectoryView *view)
7940{
7941 return (showing_trash_directory (view) || caja_window_info_get_window_type (view->details->window) == CAJA_WINDOW_NAVIGATION);
7942}
7943
7944static gboolean
7945file_list_all_are_folders (GList *file_list)
7946{
7947 GList *l;
7948 char *activation_uri;
7949 gboolean is_dir;
7950 CajaFile *linked_file;
7951 CajaFile *file = NULL((void*)0);
7952
7953 for (l = file_list; l != NULL((void*)0); l = l->next) {
7954 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
7955 if (caja_file_is_caja_link (file) &&
7956 !CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
7957 if (caja_file_is_launcher (file)) {
7958 return FALSE(0);
7959 }
7960
7961 activation_uri = caja_file_get_activation_uri (file);
7962
7963 if (activation_uri == NULL((void*)0)) {
7964 g_free (activation_uri);
7965 return FALSE(0);
7966 }
7967
7968 linked_file = caja_file_get_existing_by_uri (activation_uri);
7969
7970 /* We might not actually know the type of the linked file yet,
7971 * however we don't want to schedule a read, since that might do things
7972 * like ask for password etc. This is a bit unfortunate, but I don't
7973 * know any way around it, so we do various heuristics here
7974 * to get things mostly right
7975 */
7976 is_dir =
7977 (linked_file != NULL((void*)0) &&
7978 caja_file_is_directory (linked_file)) ||
7979 (activation_uri != NULL((void*)0) &&
7980 activation_uri[strlen (activation_uri) - 1] == '/');
7981
7982 caja_file_unref (linked_file);
7983 g_free (activation_uri);
7984
7985 if (!is_dir) {
7986 return FALSE(0);
7987 }
7988 } else if (!(caja_file_is_directory (file) ||
7989 CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
)) {
7990 return FALSE(0);
7991 }
7992 }
7993 return TRUE(!(0));
7994}
7995
7996static void
7997file_should_show_foreach (CajaFile *file,
7998 gboolean *show_mount,
7999 gboolean *show_unmount,
8000 gboolean *show_eject,
8001 gboolean *show_connect,
8002 gboolean *show_format,
8003 gboolean *show_start,
8004 gboolean *show_stop,
8005 gboolean *show_poll,
8006 GDriveStartStopType *start_stop_type)
8007{
8008 *show_mount = FALSE(0);
8009 *show_unmount = FALSE(0);
8010 *show_eject = FALSE(0);
8011 *show_connect = FALSE(0);
8012 *show_format = FALSE(0);
8013 *show_start = FALSE(0);
8014 *show_stop = FALSE(0);
8015 *show_poll = FALSE(0);
8016
8017 if (caja_file_can_eject (file)) {
8018 *show_eject = TRUE(!(0));
8019 }
8020
8021 if (caja_file_can_mount (file)) {
8022 *show_mount = TRUE(!(0));
8023
8024#ifdef TODO_GIO
8025 if (something &&
8026 g_find_program_in_path ("gfloppy")) {
8027 *show_format = TRUE(!(0));
8028 }
8029#endif
8030 }
8031
8032 if (caja_file_can_start (file) || caja_file_can_start_degraded (file)) {
8033 *show_start = TRUE(!(0));
8034 }
8035
8036 if (caja_file_can_stop (file)) {
8037 *show_stop = TRUE(!(0));
8038 }
8039
8040 /* Dot not show both Unmount and Eject/Safe Removal; too confusing to
8041 * have too many menu entries */
8042 if (caja_file_can_unmount (file) && !*show_eject && !*show_stop) {
8043 *show_unmount = TRUE(!(0));
8044 }
8045
8046 if (caja_file_can_poll_for_media (file) && !caja_file_is_media_check_automatic (file)) {
8047 *show_poll = TRUE(!(0));
8048 }
8049
8050 *start_stop_type = caja_file_get_start_stop_type (file);
8051
8052 if (caja_file_is_caja_link (file)) {
8053 char *uri;
8054
8055 uri = caja_file_get_activation_uri (file);
8056 if (uri != NULL((void*)0) &&
8057 (eel_istr_has_prefix (uri, "ftp:") ||
8058 eel_istr_has_prefix (uri, "ssh:") ||
8059 eel_istr_has_prefix (uri, "sftp:") ||
8060 eel_istr_has_prefix (uri, "dav:") ||
8061 eel_istr_has_prefix (uri, "davs:"))) {
8062 *show_connect = TRUE(!(0));
8063 }
8064 g_free (uri);
8065 }
8066}
8067
8068static void
8069file_should_show_self (CajaFile *file,
8070 gboolean *show_mount,
8071 gboolean *show_unmount,
8072 gboolean *show_eject,
8073 gboolean *show_format,
8074 gboolean *show_start,
8075 gboolean *show_stop,
8076 gboolean *show_poll,
8077 GDriveStartStopType *start_stop_type)
8078{
8079 *show_mount = FALSE(0);
8080 *show_unmount = FALSE(0);
8081 *show_eject = FALSE(0);
8082 *show_format = FALSE(0);
8083 *show_start = FALSE(0);
8084 *show_stop = FALSE(0);
8085 *show_poll = FALSE(0);
8086
8087 if (file == NULL((void*)0)) {
8088 return;
8089 }
8090
8091 if (caja_file_can_eject (file)) {
8092 *show_eject = TRUE(!(0));
8093 }
8094
8095 if (caja_file_can_mount (file)) {
8096 *show_mount = TRUE(!(0));
8097 }
8098
8099#ifdef TODO_GIO
8100 if (something && g_find_program_in_path ("gfloppy")) {
8101 *show_format = TRUE(!(0));
8102 }
8103#endif
8104
8105 if (caja_file_can_start (file) || caja_file_can_start_degraded (file)) {
8106 *show_start = TRUE(!(0));
8107 }
8108
8109 if (caja_file_can_stop (file)) {
8110 *show_stop = TRUE(!(0));
8111 }
8112
8113 /* Dot not show both Unmount and Eject/Safe Removal; too confusing to
8114 * have too many menu entries */
8115 if (caja_file_can_unmount (file) && !*show_eject && !*show_stop) {
8116 *show_unmount = TRUE(!(0));
8117 }
8118
8119 if (caja_file_can_poll_for_media (file) && !caja_file_is_media_check_automatic (file)) {
8120 *show_poll = TRUE(!(0));
8121 }
8122
8123 *start_stop_type = caja_file_get_start_stop_type (file);
8124
8125}
8126
8127static gboolean
8128files_are_all_directories (GList *files)
8129{
8130 GList *l;
8131 gboolean all_directories;
8132 CajaFile *file = NULL((void*)0);
8133
8134 all_directories = TRUE(!(0));
8135
8136 for (l = files; l != NULL((void*)0); l = l->next) {
8137 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8138 all_directories &= caja_file_is_directory (file);
8139 }
8140
8141 return all_directories;
8142}
8143
8144static gboolean
8145files_is_none_directory (GList *files)
8146{
8147 GList *l;
8148 gboolean no_directory;
8149 CajaFile *file = NULL((void*)0);
8150
8151 no_directory = TRUE(!(0));
8152
8153 for (l = files; l != NULL((void*)0); l = l->next) {
8154 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8155 no_directory &= !caja_file_is_directory (file);
8156 }
8157
8158 return no_directory;
8159}
8160
8161static void
8162update_restore_from_trash_action (GtkAction *action,
8163 GList *files,
8164 gboolean is_self)
8165{
8166 CajaFile *original_file;
8167 CajaFile *original_dir;
8168 GHashTable *original_dirs_hash;
8169 GList *original_dirs;
8170 GFile *original_location;
8171 char *original_name;
8172
8173 original_file = NULL((void*)0);
8174 original_dir = NULL((void*)0);
8175 original_dirs = NULL((void*)0);
8176 original_dirs_hash = NULL((void*)0);
8177 original_location = NULL((void*)0);
8178 original_name = NULL((void*)0);
8179
8180 if (files != NULL((void*)0)) {
8181 if (g_list_length (files) == 1) {
8182 original_file = caja_file_get_trash_original_file (files->data);
8183 } else {
8184 original_dirs_hash = caja_trashed_files_get_original_directories (files, NULL((void*)0));
8185 if (original_dirs_hash != NULL((void*)0)) {
8186 original_dirs = g_hash_table_get_keys (original_dirs_hash);
8187 if (g_list_length (original_dirs) == 1) {
8188 original_dir = caja_file_ref (CAJA_FILE (original_dirs->data)((((CajaFile*) (void *) ((original_dirs->data))))));
8189 }
8190 }
8191 }
8192 }
8193
8194 if (original_file != NULL((void*)0) || original_dirs != NULL((void*)0)) {
8195 char *tooltip;
8196
8197 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8198 gtk_action_set_visible (action, TRUE(!(0)));
8199 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8200
8201 if (original_file != NULL((void*)0)) {
8202 original_location = caja_file_get_location (original_file);
8203 } else if (original_dir != NULL((void*)0)) {
8204 original_location = caja_file_get_location (original_dir);
8205 }
8206
8207 if (original_location != NULL((void*)0)) {
8208 original_name = g_file_get_parse_name (original_location);
8209 }
8210
8211 if (is_self) {
8212 g_assert (g_list_length (files) == 1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_277
; if (g_list_length (files) == 1) _g_boolean_var_277 = 1; else
_g_boolean_var_277 = 0; _g_boolean_var_277; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 8212, ((const char*) (
__func__)), "g_list_length (files) == 1"); } while (0)
;
8213 g_assert (original_location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_278
; if (original_location != ((void*)0)) _g_boolean_var_278 = 1
; else _g_boolean_var_278 = 0; _g_boolean_var_278; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 8213, ((const char*) (__func__)), "original_location != NULL"
); } while (0)
;
8214 tooltip = g_strdup_printf (_("Move the open folder out of the trash to \"%s\"")dcgettext (((void*)0), "Move the open folder out of the trash to \"%s\""
, 5)
, original_name);
8215 } else if (files_are_all_directories (files)) {
8216 if (original_name != NULL((void*)0)) {
8217 tooltip = g_strdup_printf (ngettext ("Move the selected folder out of the trash to \"%s\"",dcngettext (((void*)0), "Move the selected folder out of the trash to \"%s\""
, "Move the selected folders out of the trash to \"%s\"", g_list_length
(files), 5)
8218 "Move the selected folders out of the trash to \"%s\"",dcngettext (((void*)0), "Move the selected folder out of the trash to \"%s\""
, "Move the selected folders out of the trash to \"%s\"", g_list_length
(files), 5)
8219 g_list_length (files))dcngettext (((void*)0), "Move the selected folder out of the trash to \"%s\""
, "Move the selected folders out of the trash to \"%s\"", g_list_length
(files), 5)
, original_name);
8220 } else {
8221 tooltip = g_strdup_printf (ngettext ("Move the selected folder out of the trash",dcngettext (((void*)0), "Move the selected folder out of the trash"
, "Move the selected folders out of the trash", g_list_length
(files), 5)
8222 "Move the selected folders out of the trash",dcngettext (((void*)0), "Move the selected folder out of the trash"
, "Move the selected folders out of the trash", g_list_length
(files), 5)
8223 g_list_length (files))dcngettext (((void*)0), "Move the selected folder out of the trash"
, "Move the selected folders out of the trash", g_list_length
(files), 5)
);
8224 }
8225 } else if (files_is_none_directory (files)) {
8226 if (original_name != NULL((void*)0)) {
8227 tooltip = g_strdup_printf (ngettext ("Move the selected file out of the trash to \"%s\"",dcngettext (((void*)0), "Move the selected file out of the trash to \"%s\""
, "Move the selected files out of the trash to \"%s\"", g_list_length
(files), 5)
8228 "Move the selected files out of the trash to \"%s\"",dcngettext (((void*)0), "Move the selected file out of the trash to \"%s\""
, "Move the selected files out of the trash to \"%s\"", g_list_length
(files), 5)
8229 g_list_length (files))dcngettext (((void*)0), "Move the selected file out of the trash to \"%s\""
, "Move the selected files out of the trash to \"%s\"", g_list_length
(files), 5)
, original_name);
8230 } else {
8231 tooltip = g_strdup_printf (ngettext ("Move the selected file out of the trash",dcngettext (((void*)0), "Move the selected file out of the trash"
, "Move the selected files out of the trash", g_list_length (
files), 5)
8232 "Move the selected files out of the trash",dcngettext (((void*)0), "Move the selected file out of the trash"
, "Move the selected files out of the trash", g_list_length (
files), 5)
8233 g_list_length (files))dcngettext (((void*)0), "Move the selected file out of the trash"
, "Move the selected files out of the trash", g_list_length (
files), 5)
);
8234 }
8235 } else {
8236 if (original_name != NULL((void*)0)) {
8237 tooltip = g_strdup_printf (ngettext ("Move the selected item out of the trash to \"%s\"",dcngettext (((void*)0), "Move the selected item out of the trash to \"%s\""
, "Move the selected items out of the trash to \"%s\"", g_list_length
(files), 5)
8238 "Move the selected items out of the trash to \"%s\"",dcngettext (((void*)0), "Move the selected item out of the trash to \"%s\""
, "Move the selected items out of the trash to \"%s\"", g_list_length
(files), 5)
8239 g_list_length (files))dcngettext (((void*)0), "Move the selected item out of the trash to \"%s\""
, "Move the selected items out of the trash to \"%s\"", g_list_length
(files), 5)
, original_name);
8240 } else {
8241 tooltip = g_strdup_printf (ngettext ("Move the selected item out of the trash",dcngettext (((void*)0), "Move the selected item out of the trash"
, "Move the selected items out of the trash", g_list_length (
files), 5)
8242 "Move the selected items out of the trash",dcngettext (((void*)0), "Move the selected item out of the trash"
, "Move the selected items out of the trash", g_list_length (
files), 5)
8243 g_list_length (files))dcngettext (((void*)0), "Move the selected item out of the trash"
, "Move the selected items out of the trash", g_list_length (
files), 5)
);
8244 }
8245 }
8246 g_free (original_name);
8247
8248 g_object_set (action, "tooltip", tooltip, NULL((void*)0));
8249
8250 if (original_location != NULL((void*)0)) {
8251 g_object_unref (original_location);
8252 }
8253 } else {
8254 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8255 gtk_action_set_visible (action, FALSE(0));
8256 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8257 }
8258
8259 caja_file_unref (original_file);
8260 caja_file_unref (original_dir);
8261 g_list_free (original_dirs);
8262
8263 if (original_dirs_hash != NULL((void*)0)) {
8264 g_hash_table_destroy (original_dirs_hash);
8265 }
8266}
8267
8268static void
8269real_update_menus_volumes (FMDirectoryView *view,
8270 GList *selection,
8271 gint selection_count)
8272{
8273 GList *l;
8274 CajaFile *file;
8275 gboolean show_mount;
8276 gboolean show_unmount;
8277 gboolean show_eject;
8278 gboolean show_connect;
8279 gboolean show_format;
8280 gboolean show_start;
8281 gboolean show_stop;
8282 gboolean show_poll;
8283 GDriveStartStopType start_stop_type;
8284 gboolean show_self_mount;
8285 gboolean show_self_unmount;
8286 gboolean show_self_eject;
8287 gboolean show_self_format;
8288 gboolean show_self_start;
8289 gboolean show_self_stop;
8290 gboolean show_self_poll;
8291 GDriveStartStopType self_start_stop_type;
8292 GtkAction *action;
8293
8294 show_mount = (selection != NULL((void*)0));
8295 show_unmount = (selection != NULL((void*)0));
8296 show_eject = (selection != NULL((void*)0));
8297 show_connect = (selection != NULL((void*)0) && selection_count == 1);
8298 show_format = (selection != NULL((void*)0) && selection_count == 1);
8299 show_start = (selection != NULL((void*)0) && selection_count == 1);
8300 show_stop = (selection != NULL((void*)0) && selection_count == 1);
8301 show_poll = (selection != NULL((void*)0) && selection_count == 1);
8302 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
8303 self_start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
8304
8305 for (l = selection; l != NULL((void*)0) && (show_mount || show_unmount
8306 || show_eject || show_connect
8307 || show_format || show_start
8308 || show_stop || show_poll);
8309 l = l->next) {
8310 gboolean show_mount_one;
8311 gboolean show_unmount_one;
8312 gboolean show_eject_one;
8313 gboolean show_connect_one;
8314 gboolean show_format_one;
8315 gboolean show_start_one;
8316 gboolean show_stop_one;
8317 gboolean show_poll_one;
8318
8319 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8320 file_should_show_foreach (file,
8321 &show_mount_one,
8322 &show_unmount_one,
8323 &show_eject_one,
8324 &show_connect_one,
8325 &show_format_one,
8326 &show_start_one,
8327 &show_stop_one,
8328 &show_poll_one,
8329 &start_stop_type);
8330
8331 show_mount &= show_mount_one;
8332 show_unmount &= show_unmount_one;
8333 show_eject &= show_eject_one;
8334 show_connect &= show_connect_one;
8335 show_format &= show_format_one;
8336 show_start &= show_start_one;
8337 show_stop &= show_stop_one;
8338 show_poll &= show_poll_one;
8339 }
8340
8341 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8342 action = gtk_action_group_get_action (view->details->dir_action_group,
8343 FM_ACTION_CONNECT_TO_SERVER_LINK"Connect To Server Link");
8344 gtk_action_set_visible (action, show_connect);
8345
8346 action = gtk_action_group_get_action (view->details->dir_action_group,
8347 FM_ACTION_MOUNT_VOLUME"Mount Volume");
8348 gtk_action_set_visible (action, show_mount);
8349
8350 action = gtk_action_group_get_action (view->details->dir_action_group,
8351 FM_ACTION_UNMOUNT_VOLUME"Unmount Volume");
8352 gtk_action_set_visible (action, show_unmount);
8353
8354 action = gtk_action_group_get_action (view->details->dir_action_group,
8355 FM_ACTION_EJECT_VOLUME"Eject Volume");
8356 gtk_action_set_visible (action, show_eject);
8357
8358 action = gtk_action_group_get_action (view->details->dir_action_group,
8359 FM_ACTION_FORMAT_VOLUME"Format Volume");
8360 gtk_action_set_visible (action, show_format);
8361
8362 action = gtk_action_group_get_action (view->details->dir_action_group,
8363 FM_ACTION_START_VOLUME"Start Volume");
8364 gtk_action_set_visible (action, show_start);
8365 if (show_start) {
8366 switch (start_stop_type) {
8367 default:
8368 case G_DRIVE_START_STOP_TYPE_UNKNOWN:
8369 gtk_action_set_label (action, _("_Start")dcgettext (((void*)0), "_Start", 5));
8370 gtk_action_set_tooltip (action, _("Start the selected drive")dcgettext (((void*)0), "Start the selected drive", 5));
8371 break;
8372 case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
8373 gtk_action_set_label (action, _("_Start")dcgettext (((void*)0), "_Start", 5));
8374 gtk_action_set_tooltip (action, _("Start the selected drive")dcgettext (((void*)0), "Start the selected drive", 5));
8375 break;
8376 case G_DRIVE_START_STOP_TYPE_NETWORK:
8377 gtk_action_set_label (action, _("_Connect")dcgettext (((void*)0), "_Connect", 5));
8378 gtk_action_set_tooltip (action, _("Connect to the selected drive")dcgettext (((void*)0), "Connect to the selected drive", 5));
8379 break;
8380 case G_DRIVE_START_STOP_TYPE_MULTIDISK:
8381 gtk_action_set_label (action, _("_Start Multi-disk Drive")dcgettext (((void*)0), "_Start Multi-disk Drive", 5));
8382 gtk_action_set_tooltip (action, _("Start the selected multi-disk drive")dcgettext (((void*)0), "Start the selected multi-disk drive",
5)
);
8383 break;
8384 case G_DRIVE_START_STOP_TYPE_PASSWORD:
8385 gtk_action_set_label (action, _("U_nlock Drive")dcgettext (((void*)0), "U_nlock Drive", 5));
8386 gtk_action_set_tooltip (action, _("Unlock the selected drive")dcgettext (((void*)0), "Unlock the selected drive", 5));
8387 break;
8388 }
8389 }
8390
8391 action = gtk_action_group_get_action (view->details->dir_action_group,
8392 FM_ACTION_STOP_VOLUME"Stop Volume");
8393 gtk_action_set_visible (action, show_stop);
8394 if (show_stop) {
8395 switch (start_stop_type) {
8396 default:
8397 case G_DRIVE_START_STOP_TYPE_UNKNOWN:
8398 gtk_action_set_label (action, _("_Stop")dcgettext (((void*)0), "_Stop", 5));
8399 gtk_action_set_tooltip (action, _("Stop the selected drive")dcgettext (((void*)0), "Stop the selected drive", 5));
8400 break;
8401 case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
8402 gtk_action_set_label (action, _("_Safely Remove Drive")dcgettext (((void*)0), "_Safely Remove Drive", 5));
8403 gtk_action_set_tooltip (action, _("Safely remove the selected drive")dcgettext (((void*)0), "Safely remove the selected drive", 5));
8404 break;
8405 case G_DRIVE_START_STOP_TYPE_NETWORK:
8406 gtk_action_set_label (action, _("_Disconnect")dcgettext (((void*)0), "_Disconnect", 5));
8407 gtk_action_set_tooltip (action, _("Disconnect the selected drive")dcgettext (((void*)0), "Disconnect the selected drive", 5));
8408 break;
8409 case G_DRIVE_START_STOP_TYPE_MULTIDISK:
8410 gtk_action_set_label (action, _("_Stop Multi-disk Drive")dcgettext (((void*)0), "_Stop Multi-disk Drive", 5));
8411 gtk_action_set_tooltip (action, _("Stop the selected multi-disk drive")dcgettext (((void*)0), "Stop the selected multi-disk drive", 5
)
);
8412 break;
8413 case G_DRIVE_START_STOP_TYPE_PASSWORD:
8414 gtk_action_set_label (action, _("_Lock Drive")dcgettext (((void*)0), "_Lock Drive", 5));
8415 gtk_action_set_tooltip (action, _("Lock the selected drive")dcgettext (((void*)0), "Lock the selected drive", 5));
8416 break;
8417 }
8418 }
8419
8420 action = gtk_action_group_get_action (view->details->dir_action_group,
8421 FM_ACTION_POLL"Poll");
8422 gtk_action_set_visible (action, show_poll);
8423 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8424
8425 show_self_mount = show_self_unmount = show_self_eject =
8426 show_self_format = show_self_start = show_self_stop = show_self_poll = FALSE(0);
8427
8428 file = fm_directory_view_get_directory_as_file (view);
8429 file_should_show_self (file,
8430 &show_self_mount,
8431 &show_self_unmount,
8432 &show_self_eject,
8433 &show_self_format,
8434 &show_self_start,
8435 &show_self_stop,
8436 &show_self_poll,
8437 &self_start_stop_type);
8438
8439 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8440 action = gtk_action_group_get_action (view->details->dir_action_group,
8441 FM_ACTION_SELF_MOUNT_VOLUME"Self Mount Volume");
8442 gtk_action_set_visible (action, show_self_mount);
8443
8444 action = gtk_action_group_get_action (view->details->dir_action_group,
8445 FM_ACTION_SELF_UNMOUNT_VOLUME"Self Unmount Volume");
8446 gtk_action_set_visible (action, show_self_unmount);
8447
8448 action = gtk_action_group_get_action (view->details->dir_action_group,
8449 FM_ACTION_SELF_EJECT_VOLUME"Self Eject Volume");
8450 gtk_action_set_visible (action, show_self_eject);
8451
8452 action = gtk_action_group_get_action (view->details->dir_action_group,
8453 FM_ACTION_SELF_FORMAT_VOLUME"Self Format Volume");
8454 gtk_action_set_visible (action, show_self_format);
8455
8456 action = gtk_action_group_get_action (view->details->dir_action_group,
8457 FM_ACTION_SELF_START_VOLUME"Self Start Volume");
8458 gtk_action_set_visible (action, show_self_start);
8459 if (show_self_start) {
8460 switch (self_start_stop_type) {
8461 default:
8462 case G_DRIVE_START_STOP_TYPE_UNKNOWN:
8463 gtk_action_set_label (action, _("_Start")dcgettext (((void*)0), "_Start", 5));
8464 gtk_action_set_tooltip (action, _("Start the drive associated with the open folder")dcgettext (((void*)0), "Start the drive associated with the open folder"
, 5)
);
8465 break;
8466 case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
8467 gtk_action_set_label (action, _("_Start")dcgettext (((void*)0), "_Start", 5));
8468 gtk_action_set_tooltip (action, _("Start the drive associated with the open folder")dcgettext (((void*)0), "Start the drive associated with the open folder"
, 5)
);
8469 break;
8470 case G_DRIVE_START_STOP_TYPE_NETWORK:
8471 gtk_action_set_label (action, _("_Connect")dcgettext (((void*)0), "_Connect", 5));
8472 gtk_action_set_tooltip (action, _("Connect to the drive associated with the open folder")dcgettext (((void*)0), "Connect to the drive associated with the open folder"
, 5)
);
8473 break;
8474 case G_DRIVE_START_STOP_TYPE_MULTIDISK:
8475 gtk_action_set_label (action, _("_Start Multi-disk Drive")dcgettext (((void*)0), "_Start Multi-disk Drive", 5));
8476 gtk_action_set_tooltip (action, _("Start the multi-disk drive associated with the open folder")dcgettext (((void*)0), "Start the multi-disk drive associated with the open folder"
, 5)
);
8477 break;
8478 case G_DRIVE_START_STOP_TYPE_PASSWORD:
8479 gtk_action_set_label (action, _("_Unlock Drive")dcgettext (((void*)0), "_Unlock Drive", 5));
8480 gtk_action_set_tooltip (action, _("Unlock the drive associated with the open folder")dcgettext (((void*)0), "Unlock the drive associated with the open folder"
, 5)
);
8481 break;
8482 }
8483 }
8484
8485 action = gtk_action_group_get_action (view->details->dir_action_group,
8486 FM_ACTION_SELF_STOP_VOLUME"Self Stop Volume");
8487 gtk_action_set_visible (action, show_self_stop);
8488 if (show_self_stop) {
8489 switch (self_start_stop_type) {
8490 default:
8491 case G_DRIVE_START_STOP_TYPE_UNKNOWN:
8492 gtk_action_set_label (action, _("_Stop")dcgettext (((void*)0), "_Stop", 5));
8493 gtk_action_set_tooltip (action, _("_Stop the drive associated with the open folder")dcgettext (((void*)0), "_Stop the drive associated with the open folder"
, 5)
);
8494 break;
8495 case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
8496 gtk_action_set_label (action, _("_Safely Remove Drive")dcgettext (((void*)0), "_Safely Remove Drive", 5));
8497 gtk_action_set_tooltip (action, _("Safely remove the drive associated with the open folder")dcgettext (((void*)0), "Safely remove the drive associated with the open folder"
, 5)
);
8498 break;
8499 case G_DRIVE_START_STOP_TYPE_NETWORK:
8500 gtk_action_set_label (action, _("_Disconnect")dcgettext (((void*)0), "_Disconnect", 5));
8501 gtk_action_set_tooltip (action, _("Disconnect the drive associated with the open folder")dcgettext (((void*)0), "Disconnect the drive associated with the open folder"
, 5)
);
8502 break;
8503 case G_DRIVE_START_STOP_TYPE_MULTIDISK:
8504 gtk_action_set_label (action, _("_Stop Multi-disk Drive")dcgettext (((void*)0), "_Stop Multi-disk Drive", 5));
8505 gtk_action_set_tooltip (action, _("Stop the multi-disk drive associated with the open folder")dcgettext (((void*)0), "Stop the multi-disk drive associated with the open folder"
, 5)
);
8506 break;
8507 case G_DRIVE_START_STOP_TYPE_PASSWORD:
8508 gtk_action_set_label (action, _("_Lock Drive")dcgettext (((void*)0), "_Lock Drive", 5));
8509 gtk_action_set_tooltip (action, _("Lock the drive associated with the open folder")dcgettext (((void*)0), "Lock the drive associated with the open folder"
, 5)
);
8510 break;
8511 }
8512 }
8513
8514 action = gtk_action_group_get_action (view->details->dir_action_group,
8515 FM_ACTION_SELF_POLL"Self Poll");
8516 gtk_action_set_visible (action, show_self_poll);
8517 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8518
8519}
8520
8521static void
8522real_update_location_menu_volumes (FMDirectoryView *view)
8523{
8524 GtkAction *action;
8525 CajaFile *file;
8526 gboolean show_mount;
8527 gboolean show_unmount;
8528 gboolean show_eject;
8529 gboolean show_connect;
8530 gboolean show_format;
8531 gboolean show_start;
8532 gboolean show_stop;
8533 gboolean show_poll;
8534 GDriveStartStopType start_stop_type;
8535
8536 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_279
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_279
= 1; else _g_boolean_var_279 = 0; _g_boolean_var_279; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 8536, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
8537 g_assert (CAJA_IS_FILE (view->details->location_popup_directory_as_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_280
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view->details->location_popup_directory_as_file));
GType __t = (caja_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_280 = 1; else _g_boolean_var_280
= 0; _g_boolean_var_280; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 8537, ((const char*) (
__func__)), "CAJA_IS_FILE (view->details->location_popup_directory_as_file)"
); } while (0)
;
8538
8539 file = CAJA_FILE (view->details->location_popup_directory_as_file)((((CajaFile*) (void *) ((view->details->location_popup_directory_as_file
)))))
;
8540 file_should_show_foreach (file,
8541 &show_mount,
8542 &show_unmount,
8543 &show_eject,
8544 &show_connect,
8545 &show_format,
8546 &show_start,
8547 &show_stop,
8548 &show_poll,
8549 &start_stop_type);
8550
8551 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8552 action = gtk_action_group_get_action (view->details->dir_action_group,
8553 FM_ACTION_LOCATION_MOUNT_VOLUME"Location Mount Volume");
8554 gtk_action_set_visible (action, show_mount);
8555
8556 action = gtk_action_group_get_action (view->details->dir_action_group,
8557 FM_ACTION_LOCATION_UNMOUNT_VOLUME"Location Unmount Volume");
8558 gtk_action_set_visible (action, show_unmount);
8559
8560 action = gtk_action_group_get_action (view->details->dir_action_group,
8561 FM_ACTION_LOCATION_EJECT_VOLUME"Location Eject Volume");
8562 gtk_action_set_visible (action, show_eject);
8563
8564 action = gtk_action_group_get_action (view->details->dir_action_group,
8565 FM_ACTION_LOCATION_FORMAT_VOLUME"Location Format Volume");
8566 gtk_action_set_visible (action, show_format);
8567
8568 action = gtk_action_group_get_action (view->details->dir_action_group,
8569 FM_ACTION_LOCATION_START_VOLUME"Location Start Volume");
8570 gtk_action_set_visible (action, show_start);
8571 if (show_start) {
8572 switch (start_stop_type) {
8573 default:
8574 case G_DRIVE_START_STOP_TYPE_UNKNOWN:
8575 gtk_action_set_label (action, _("_Start")dcgettext (((void*)0), "_Start", 5));
8576 gtk_action_set_tooltip (action, _("Start the selected drive")dcgettext (((void*)0), "Start the selected drive", 5));
8577 break;
8578 case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
8579 gtk_action_set_label (action, _("_Start")dcgettext (((void*)0), "_Start", 5));
8580 gtk_action_set_tooltip (action, _("Start the selected drive")dcgettext (((void*)0), "Start the selected drive", 5));
8581 break;
8582 case G_DRIVE_START_STOP_TYPE_NETWORK:
8583 gtk_action_set_label (action, _("_Connect")dcgettext (((void*)0), "_Connect", 5));
8584 gtk_action_set_tooltip (action, _("Connect to the selected drive")dcgettext (((void*)0), "Connect to the selected drive", 5));
8585 break;
8586 case G_DRIVE_START_STOP_TYPE_MULTIDISK:
8587 gtk_action_set_label (action, _("_Start Multi-disk Drive")dcgettext (((void*)0), "_Start Multi-disk Drive", 5));
8588 gtk_action_set_tooltip (action, _("Start the selected multi-disk drive")dcgettext (((void*)0), "Start the selected multi-disk drive",
5)
);
8589 break;
8590 case G_DRIVE_START_STOP_TYPE_PASSWORD:
8591 gtk_action_set_label (action, _("_Unlock Drive")dcgettext (((void*)0), "_Unlock Drive", 5));
8592 gtk_action_set_tooltip (action, _("Unlock the selected drive")dcgettext (((void*)0), "Unlock the selected drive", 5));
8593 break;
8594 }
8595 }
8596
8597 action = gtk_action_group_get_action (view->details->dir_action_group,
8598 FM_ACTION_LOCATION_STOP_VOLUME"Location Stop Volume");
8599 gtk_action_set_visible (action, show_stop);
8600 if (show_stop) {
8601 switch (start_stop_type) {
8602 default:
8603 case G_DRIVE_START_STOP_TYPE_UNKNOWN:
8604 gtk_action_set_label (action, _("_Stop")dcgettext (((void*)0), "_Stop", 5));
8605 gtk_action_set_tooltip (action, _("Stop the selected volume")dcgettext (((void*)0), "Stop the selected volume", 5));
8606 break;
8607 case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
8608 gtk_action_set_label (action, _("_Safely Remove Drive")dcgettext (((void*)0), "_Safely Remove Drive", 5));
8609 gtk_action_set_tooltip (action, _("Safely remove the selected drive")dcgettext (((void*)0), "Safely remove the selected drive", 5));
8610 break;
8611 case G_DRIVE_START_STOP_TYPE_NETWORK:
8612 gtk_action_set_label (action, _("_Disconnect")dcgettext (((void*)0), "_Disconnect", 5));
8613 gtk_action_set_tooltip (action, _("Disconnect the selected drive")dcgettext (((void*)0), "Disconnect the selected drive", 5));
8614 break;
8615 case G_DRIVE_START_STOP_TYPE_MULTIDISK:
8616 gtk_action_set_label (action, _("_Stop Multi-disk Drive")dcgettext (((void*)0), "_Stop Multi-disk Drive", 5));
8617 gtk_action_set_tooltip (action, _("Stop the selected multi-disk drive")dcgettext (((void*)0), "Stop the selected multi-disk drive", 5
)
);
8618 break;
8619 case G_DRIVE_START_STOP_TYPE_PASSWORD:
8620 gtk_action_set_label (action, _("_Lock Drive")dcgettext (((void*)0), "_Lock Drive", 5));
8621 gtk_action_set_tooltip (action, _("Lock the selected drive")dcgettext (((void*)0), "Lock the selected drive", 5));
8622 break;
8623 }
8624 }
8625
8626 action = gtk_action_group_get_action (view->details->dir_action_group,
8627 FM_ACTION_LOCATION_POLL"Location Poll");
8628 gtk_action_set_visible (action, show_poll);
8629 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8630}
8631
8632/* TODO: we should split out this routine into two functions:
8633 * Update on clipboard changes
8634 * Update on selection changes
8635 */
8636static void
8637real_update_paste_menu (FMDirectoryView *view,
8638 GList *selection,
8639 gint selection_count)
8640{
8641 gboolean can_paste_files_into;
8642 gboolean selection_is_read_only;
8643 gboolean is_read_only;
8644 GtkAction *action;
8645
8646 selection_is_read_only = selection_count == 1 &&
8647 (!caja_file_can_write (CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data)))))) &&
8648 !caja_file_has_activation_uri (CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data)))))));
8649
8650 is_read_only = fm_directory_view_is_read_only (view);
8651
8652 can_paste_files_into = (selection_count == 1 &&
8653 can_paste_into_file (CAJA_FILE (selection->data)((((CajaFile*) (void *) ((selection->data)))))));
8654
8655 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8656 action = gtk_action_group_get_action (view->details->dir_action_group,
8657 FM_ACTION_PASTE"Paste");
8658 gtk_action_set_sensitive (action, !is_read_only);
8659
8660 action = gtk_action_group_get_action (view->details->dir_action_group,
8661 FM_ACTION_PASTE_FILES_INTO"Paste Files Into");
8662 gtk_action_set_visible (action, can_paste_files_into);
8663 gtk_action_set_sensitive (action, !selection_is_read_only);
8664 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8665
8666 /* Ask the clipboard */
8667 g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view)); /* Need to keep the object alive until we get the reply */
8668 gtk_clipboard_request_targets (caja_clipboard_get (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))),
8669 clipboard_targets_received,
8670 view);
8671}
8672
8673static void
8674real_update_location_menu (FMDirectoryView *view)
8675{
8676 GtkAction *action;
8677 CajaFile *file;
8678 gboolean is_special_link;
8679 gboolean is_desktop_or_home_dir;
8680 gboolean can_delete_file, show_delete;
8681 gboolean show_separate_delete_command;
8682 gboolean show_open_folder_window;
8683 gboolean show_open_in_new_tab;
8684 GList l;
8685 char *label;
8686 char *tip;
8687
8688 show_open_folder_window = FALSE(0);
8689 show_open_in_new_tab = FALSE(0);
8690
8691 if (caja_window_info_get_window_type (view->details->window) == CAJA_WINDOW_NAVIGATION) {
8692 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
8693 label = _("Open in New _Window")dcgettext (((void*)0), "Open in New _Window", 5);
8694 } else {
8695 label = _("Browse in New _Window")dcgettext (((void*)0), "Browse in New _Window", 5);
8696 show_open_folder_window = TRUE(!(0));
8697 }
8698
8699 show_open_in_new_tab = TRUE(!(0));
8700 } else {
8701 label = g_strdup (ngettext ("_Browse Folder",g_strdup_inline (dcngettext (((void*)0), "_Browse Folder", "_Browse Folders"
, 1, 5))
8702 "_Browse Folders", 1))g_strdup_inline (dcngettext (((void*)0), "_Browse Folder", "_Browse Folders"
, 1, 5))
;
8703 }
8704 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8705 action = gtk_action_group_get_action (view->details->dir_action_group,
8706 FM_ACTION_LOCATION_OPEN_ALTERNATE"LocationOpenAlternate");
8707 g_object_set (action,
8708 "label", label,
8709 NULL((void*)0));
8710
8711 action = gtk_action_group_get_action (view->details->dir_action_group,
8712 FM_ACTION_LOCATION_OPEN_IN_NEW_TAB"LocationOpenInNewTab");
8713 gtk_action_set_visible (action, show_open_in_new_tab);
8714 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8715
8716 if (show_open_in_new_tab) {
8717 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
8718 label = _("Open in New _Tab")dcgettext (((void*)0), "Open in New _Tab", 5);
8719 } else {
8720 label = _("Browse in New _Tab")dcgettext (((void*)0), "Browse in New _Tab", 5);
8721 }
8722 g_object_set (action,
8723 "label", label,
8724 NULL((void*)0));
8725 }
8726
8727 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8728 action = gtk_action_group_get_action (view->details->dir_action_group,
8729 FM_ACTION_LOCATION_OPEN_FOLDER_WINDOW"LocationOpenFolderWindow");
8730 gtk_action_set_visible (action, show_open_folder_window);
8731 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8732
8733 file = view->details->location_popup_directory_as_file;
8734 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_281
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_281
= 1; else _g_boolean_var_281 = 0; _g_boolean_var_281; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 8734, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
8735 g_assert (caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO |do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if (caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO
| CAJA_FILE_ATTRIBUTE_MOUNT | CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO
)) _g_boolean_var_282 = 1; else _g_boolean_var_282 = 0; _g_boolean_var_282
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 8737, ((const char*) (__func__)), "caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_MOUNT | CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO)"
); } while (0)
8736 CAJA_FILE_ATTRIBUTE_MOUNT |do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if (caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO
| CAJA_FILE_ATTRIBUTE_MOUNT | CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO
)) _g_boolean_var_282 = 1; else _g_boolean_var_282 = 0; _g_boolean_var_282
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 8737, ((const char*) (__func__)), "caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_MOUNT | CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO)"
); } while (0)
8737 CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if (caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO
| CAJA_FILE_ATTRIBUTE_MOUNT | CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO
)) _g_boolean_var_282 = 1; else _g_boolean_var_282 = 0; _g_boolean_var_282
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 8737, ((const char*) (__func__)), "caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_MOUNT | CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO)"
); } while (0)
;
8738
8739 is_special_link = CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
;
8740 is_desktop_or_home_dir = caja_file_is_home (file)
8741 || caja_file_is_desktop_directory (file);
8742
8743 can_delete_file =
8744 caja_file_can_delete (file) &&
8745 !is_special_link &&
8746 !is_desktop_or_home_dir;
8747
8748 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8749 action = gtk_action_group_get_action (view->details->dir_action_group,
8750 FM_ACTION_LOCATION_CUT"LocationCut");
8751 gtk_action_set_sensitive (action, can_delete_file);
8752
8753 action = gtk_action_group_get_action (view->details->dir_action_group,
8754 FM_ACTION_LOCATION_PASTE_FILES_INTO"LocationPasteFilesInto");
8755 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8756 g_object_set_data (G_OBJECT (action)((((GObject*) (void *) ((action))))),
8757 "can-paste-according-to-destination",
8758 GINT_TO_POINTER (can_paste_into_file (file))((gpointer) (glong) (can_paste_into_file (file))));
8759 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8760 gtk_action_set_sensitive (action,
8761 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-clipboard")))
8762 "can-paste-according-to-clipboard"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-clipboard")))
&&
8763 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-destination")))
8764 "can-paste-according-to-destination"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
action))))), "can-paste-according-to-destination")))
);
8765 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8766
8767 show_delete = TRUE(!(0));
8768
8769 if (file != NULL((void*)0) &&
8770 caja_file_is_in_trash (file)) {
8771 if (caja_file_is_self_owned (file)) {
8772 show_delete = FALSE(0);
8773 }
8774
8775 label = _("_Delete Permanently")dcgettext (((void*)0), "_Delete Permanently", 5);
8776 tip = _("Delete the open folder permanently")dcgettext (((void*)0), "Delete the open folder permanently", 5
)
;
8777 show_separate_delete_command = FALSE(0);
8778 } else {
8779 label = _("Mo_ve to Trash")dcgettext (((void*)0), "Mo_ve to Trash", 5);
8780 tip = _("Move the open folder to the Trash")dcgettext (((void*)0), "Move the open folder to the Trash", 5
)
;
8781 show_separate_delete_command = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ENABLE_DELETE"enable-delete");
8782 }
8783
8784 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8785 action = gtk_action_group_get_action (view->details->dir_action_group,
8786 FM_ACTION_LOCATION_TRASH"LocationTrash");
8787 g_object_set (action,
8788 "label", label,
8789 "tooltip", tip,
8790 "icon-name", (file != NULL((void*)0) &&
8791 caja_file_is_in_trash (file)) ?
8792 CAJA_ICON_DELETE"edit-delete" : CAJA_ICON_TRASH_FULL"user-trash-full",
8793 NULL((void*)0));
8794 gtk_action_set_sensitive (action, can_delete_file);
8795 gtk_action_set_visible (action, show_delete);
8796
8797 action = gtk_action_group_get_action (view->details->dir_action_group,
8798 FM_ACTION_LOCATION_DELETE"LocationDelete");
8799 gtk_action_set_visible (action, show_separate_delete_command);
8800 if (show_separate_delete_command) {
8801 gtk_action_set_sensitive (action, can_delete_file);
8802 g_object_set (action,
8803 "icon-name", CAJA_ICON_DELETE"edit-delete",
8804 "sensitive", can_delete_file,
8805 NULL((void*)0));
8806 }
8807
8808 action = gtk_action_group_get_action (view->details->dir_action_group,
8809 FM_ACTION_LOCATION_RESTORE_FROM_TRASH"LocationRestoreFromTrash");
8810 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8811 l.prev = NULL((void*)0);
8812 l.next = NULL((void*)0);
8813 l.data = file;
8814 update_restore_from_trash_action (action, &l, TRUE(!(0)));
8815
8816 real_update_location_menu_volumes (view);
8817
8818 /* we silently assume that fm_directory_view_supports_properties always returns the same value.
8819 * Therefore, we don't update the sensitivity of FM_ACTION_LOCATION_PROPERTIES */
8820}
8821
8822static void
8823clipboard_changed_callback (CajaClipboardMonitor *monitor, FMDirectoryView *view)
8824{
8825 GList *selection;
8826 gint selection_count;
8827
8828 if (!view->details->active) {
8829 return;
8830 }
8831
8832 selection = fm_directory_view_get_selection (view);
8833 selection_count = g_list_length (selection);
8834
8835 real_update_paste_menu (view, selection, selection_count);
8836
8837 caja_file_list_free (selection);
8838
8839}
8840
8841static gboolean
8842can_delete_all (GList *files)
8843{
8844 GList *l;
8845 CajaFile *file = NULL((void*)0);
8846
8847 for (l = files; l != NULL((void*)0); l = l->next) {
8848 file = l->data;
8849 if (!caja_file_can_delete (file)) {
8850 return FALSE(0);
8851 }
8852 }
8853 return TRUE(!(0));
8854}
8855
8856static gboolean
8857has_writable_extra_pane (FMDirectoryView *view)
8858{
8859 FMDirectoryView *other_view;
8860
8861 other_view = get_directory_view_of_extra_pane (view);
8862 if (other_view != NULL((void*)0)) {
8863 return !fm_directory_view_is_read_only (other_view);
8864 }
8865 return FALSE(0);
8866}
8867
8868static void
8869real_update_menus (FMDirectoryView *view)
8870{
8871 GList *selection, *l;
8872 gint selection_count;
8873 const char *tip, *label;
8874 char *label_with_underscore;
8875 gboolean selection_contains_special_link;
8876 gboolean selection_contains_desktop_or_home_dir;
8877 gboolean can_create_files;
8878 gboolean can_delete_files;
8879 gboolean can_copy_files;
8880 gboolean can_link_files;
8881 gboolean can_duplicate_files;
8882 gboolean show_separate_delete_command;
8883 gboolean vfolder_directory;
8884 gboolean disable_command_line;
8885 gboolean show_open_alternate;
8886 gboolean can_open;
8887 gboolean show_app;
8888 gboolean show_save_search;
8889 gboolean save_search_sensitive;
8890 gboolean show_save_search_as;
8891 gboolean show_open_folder_window;
8892 GtkAction *action;
8893 GAppInfo *app;
8894 GIcon *app_icon;
8895 GtkWidget *menuitem;
8896 gboolean next_pane_is_writable;
8897 gboolean show_properties;
8898
8899 selection = fm_directory_view_get_selection (view);
8900 selection_count = g_list_length (selection);
8901
8902 selection_contains_special_link = special_link_in_selection (view);
8903 selection_contains_desktop_or_home_dir = desktop_or_home_dir_in_selection (view);
8904
8905 can_create_files = fm_directory_view_supports_creating_files (view);
8906 can_delete_files =
8907 can_delete_all (selection) &&
8908 selection_count != 0 &&
8909 !selection_contains_special_link &&
8910 !selection_contains_desktop_or_home_dir;
8911 can_copy_files = selection_count != 0
8912 && !selection_contains_special_link;
8913
8914 can_duplicate_files = can_create_files && can_copy_files;
8915 can_link_files = can_create_files && can_copy_files;
8916
8917 vfolder_directory = we_are_in_vfolder_desktop_dir (view);
8918
8919 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
8920 action = gtk_action_group_get_action (view->details->dir_action_group,
8921 FM_ACTION_RENAME"Rename");
8922 gtk_action_set_sensitive (action,
8923 selection_count == 1 &&
8924 fm_directory_view_can_rename_file (view, selection->data));
8925
8926 action = gtk_action_group_get_action (view->details->dir_action_group,
8927 FM_ACTION_NEW_FOLDER"New Folder");
8928 gtk_action_set_sensitive (action, can_create_files);
8929
8930 action = gtk_action_group_get_action (view->details->dir_action_group,
8931 FM_ACTION_OPEN"Open");
8932 gtk_action_set_sensitive (action, selection_count != 0);
8933 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
8934
8935 can_open = show_app = selection_count != 0;
8936
8937 for (l = selection; l != NULL((void*)0); l = l->next) {
8938 CajaFile *file;
8939
8940 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8941
8942 /* Double-check if the files' MIME types have changed before we
8943 commit to a choice of applications for them. This can happen
8944 if, for instance, a file was originally created with 0 bytes
8945 and then content was added to it later-- it will change from
8946 plaintext to something else. */
8947 caja_file_refresh_info (file);
8948
8949 if (!caja_mime_file_opens_in_external_app (file)) {
8950 show_app = FALSE(0);
8951 }
8952
8953 if (!show_app) {
8954 break;
8955 }
8956 }
8957
8958 label_with_underscore = NULL((void*)0);
8959
8960 app = NULL((void*)0);
8961 app_icon = NULL((void*)0);
8962
8963 if (can_open && show_app) {
8964 app = caja_mime_get_default_application_for_files (selection);
8965 }
8966
8967 if (app != NULL((void*)0)) {
8968 char *escaped_app;
8969
8970 escaped_app = eel_str_double_underscores (g_app_info_get_display_name (app));
8971 label_with_underscore = g_strdup_printf (_("_Open With %s")dcgettext (((void*)0), "_Open With %s", 5),
8972 escaped_app);
8973
8974 app_icon = g_app_info_get_icon (app);
8975 if (app_icon != NULL((void*)0)) {
8976 g_object_ref (app_icon)((__typeof__ (app_icon)) (g_object_ref) (app_icon));
8977 }
8978
8979 g_free (escaped_app);
8980 g_object_unref (app);
8981 }
8982
8983 g_object_set (action, "label",
8984 label_with_underscore ? label_with_underscore : _("_Open")dcgettext (((void*)0), "_Open", 5),
8985 NULL((void*)0));
8986
8987 menuitem = gtk_ui_manager_get_widget (
8988 caja_window_info_get_ui_manager (view->details->window),
8989 FM_DIRECTORY_VIEW_MENU_PATH_OPEN"/MenuBar/File/Open Placeholder/Open");
8990
8991 /* Only force displaying the icon if it is an application icon */
8992 gtk_image_menu_item_set_always_show_image (
8993 GTK_IMAGE_MENU_ITEM (menuitem)((((GtkImageMenuItem*) (void *) ((menuitem))))), app_icon != NULL((void*)0));
8994
8995 menuitem = gtk_ui_manager_get_widget (
8996 caja_window_info_get_ui_manager (view->details->window),
8997 FM_DIRECTORY_VIEW_POPUP_PATH_OPEN"/selection/Open Placeholder/Open");
8998
8999 /* Only force displaying the icon if it is an application icon */
9000 gtk_image_menu_item_set_always_show_image (
9001 GTK_IMAGE_MENU_ITEM (menuitem)((((GtkImageMenuItem*) (void *) ((menuitem))))), app_icon != NULL((void*)0));
9002
9003 if (app_icon == NULL((void*)0)) {
9004 app_icon = g_themed_icon_new ("document-open");
9005 }
9006
9007 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9008 gtk_action_set_gicon (action, app_icon);
9009 g_object_unref (app_icon);
9010
9011 gtk_action_set_visible (action, can_open);
9012 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9013
9014 g_free (label_with_underscore);
9015
9016 show_open_alternate = file_list_all_are_folders (selection) &&
9017 selection_count > 0 &&
9018 !(caja_window_info_get_window_type (view->details->window) == CAJA_WINDOW_DESKTOP &&
9019 g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser"));
9020 show_open_folder_window = FALSE(0);
9021 if (caja_window_info_get_window_type (view->details->window) == CAJA_WINDOW_NAVIGATION) {
9022 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
9023 if (selection_count == 0 || selection_count == 1) {
9024 label_with_underscore = g_strdup (_("Open in New _Window"))g_strdup_inline (dcgettext (((void*)0), "Open in New _Window"
, 5))
;
9025 } else {
9026 label_with_underscore = g_strdup_printf (ngettext("Open in %'d New _Window",dcngettext (((void*)0), "Open in %'d New _Window", "Open in %'d New _Windows"
, selection_count, 5)
9027 "Open in %'d New _Windows",dcngettext (((void*)0), "Open in %'d New _Window", "Open in %'d New _Windows"
, selection_count, 5)
9028 selection_count)dcngettext (((void*)0), "Open in %'d New _Window", "Open in %'d New _Windows"
, selection_count, 5)
,
9029 selection_count);
9030 }
9031 } else {
9032 if (selection_count == 0 || selection_count == 1) {
9033 label_with_underscore = g_strdup (_("Browse in New _Window"))g_strdup_inline (dcgettext (((void*)0), "Browse in New _Window"
, 5))
;
9034 } else {
9035 label_with_underscore = g_strdup_printf (ngettext("Browse in %'d New _Window",dcngettext (((void*)0), "Browse in %'d New _Window", "Browse in %'d New _Windows"
, selection_count, 5)
9036 "Browse in %'d New _Windows",dcngettext (((void*)0), "Browse in %'d New _Window", "Browse in %'d New _Windows"
, selection_count, 5)
9037 selection_count)dcngettext (((void*)0), "Browse in %'d New _Window", "Browse in %'d New _Windows"
, selection_count, 5)
,
9038 selection_count);
9039 }
9040 show_open_folder_window = show_open_alternate;
9041 }
9042 } else {
9043 label_with_underscore = g_strdup (ngettext ("_Browse Folder",g_strdup_inline (dcngettext (((void*)0), "_Browse Folder", "_Browse Folders"
, selection_count, 5))
9044 "_Browse Folders",g_strdup_inline (dcngettext (((void*)0), "_Browse Folder", "_Browse Folders"
, selection_count, 5))
9045 selection_count))g_strdup_inline (dcngettext (((void*)0), "_Browse Folder", "_Browse Folders"
, selection_count, 5))
;
9046 }
9047
9048 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9049 action = gtk_action_group_get_action (view->details->dir_action_group,
9050 FM_ACTION_OPEN_ALTERNATE"OpenAlternate");
9051 g_object_set (action, "label",
9052 label_with_underscore,
9053 NULL((void*)0));
9054 g_free (label_with_underscore);
9055
9056 gtk_action_set_sensitive (action, selection_count != 0);
9057 gtk_action_set_visible (action, show_open_alternate);
9058 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9059
9060 /* Open in New Tab action */
9061 if (caja_window_info_get_window_type (view->details->window) == CAJA_WINDOW_NAVIGATION) {
9062
9063 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
9064 if (selection_count == 0 || selection_count == 1) {
9065 label_with_underscore = g_strdup (_("Open in New _Tab"))g_strdup_inline (dcgettext (((void*)0), "Open in New _Tab", 5
))
;
9066 } else {
9067 label_with_underscore = g_strdup_printf (ngettext("Open in %'d New _Tab",dcngettext (((void*)0), "Open in %'d New _Tab", "Open in %'d New _Tabs"
, selection_count, 5)
9068 "Open in %'d New _Tabs",dcngettext (((void*)0), "Open in %'d New _Tab", "Open in %'d New _Tabs"
, selection_count, 5)
9069 selection_count)dcngettext (((void*)0), "Open in %'d New _Tab", "Open in %'d New _Tabs"
, selection_count, 5)
,
9070 selection_count);
9071 }
9072 } else {
9073 if (selection_count == 0 || selection_count == 1) {
9074 label_with_underscore = g_strdup (_("Browse in New _Tab"))g_strdup_inline (dcgettext (((void*)0), "Browse in New _Tab",
5))
;
9075 } else {
9076 label_with_underscore = g_strdup_printf (ngettext("Browse in %'d New _Tab",dcngettext (((void*)0), "Browse in %'d New _Tab", "Browse in %'d New _Tabs"
, selection_count, 5)
9077 "Browse in %'d New _Tabs",dcngettext (((void*)0), "Browse in %'d New _Tab", "Browse in %'d New _Tabs"
, selection_count, 5)
9078 selection_count)dcngettext (((void*)0), "Browse in %'d New _Tab", "Browse in %'d New _Tabs"
, selection_count, 5)
,
9079 selection_count);
9080 }
9081 }
9082 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9083 action = gtk_action_group_get_action (view->details->dir_action_group,
9084 FM_ACTION_OPEN_IN_NEW_TAB"OpenInNewTab");
9085 gtk_action_set_sensitive (action, selection_count != 0);
9086 gtk_action_set_visible (action, show_open_alternate);
9087 g_object_set (action, "label",
9088 label_with_underscore,
9089 NULL((void*)0));
9090 g_free (label_with_underscore);
9091 } else {
9092 action = gtk_action_group_get_action (view->details->dir_action_group,
9093 FM_ACTION_OPEN_IN_NEW_TAB"OpenInNewTab");
9094 gtk_action_set_visible (action, FALSE(0));
9095 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9096 }
9097
9098 /* next pane actions, only in navigation mode */
9099 if (caja_window_info_get_window_type (view->details->window) != CAJA_WINDOW_NAVIGATION) {
9100 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9101 action = gtk_action_group_get_action (view->details->dir_action_group,
9102 FM_ACTION_COPY_TO_NEXT_PANE"Copy to next pane");
9103 gtk_action_set_visible (action, FALSE(0));
9104 action = gtk_action_group_get_action (view->details->dir_action_group,
9105 FM_ACTION_MOVE_TO_NEXT_PANE"Move to next pane");
9106 gtk_action_set_visible (action, FALSE(0));
9107 }
9108
9109 action = gtk_action_group_get_action (view->details->dir_action_group,
9110 FM_ACTION_OPEN_FOLDER_WINDOW"OpenFolderWindow");
9111 gtk_action_set_visible (action, show_open_folder_window);
9112 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9113
9114 /* Broken into its own function just for convenience */
9115 reset_open_with_menu (view, selection);
9116 reset_extension_actions_menu (view, selection);
9117
9118 if (all_selected_items_in_trash (view)) {
9119 label = _("_Delete Permanently")dcgettext (((void*)0), "_Delete Permanently", 5);
9120 tip = _("Delete all selected items permanently")dcgettext (((void*)0), "Delete all selected items permanently"
, 5)
;
9121 show_separate_delete_command = FALSE(0);
9122 } else {
9123 label = _("Mo_ve to Trash")dcgettext (((void*)0), "Mo_ve to Trash", 5);
9124 tip = _("Move each selected item to the Trash")dcgettext (((void*)0), "Move each selected item to the Trash"
, 5)
;
9125 show_separate_delete_command = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ENABLE_DELETE"enable-delete");
9126 }
9127
9128 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9129 action = gtk_action_group_get_action (view->details->dir_action_group,
9130 FM_ACTION_TRASH"Trash");
9131 g_object_set (action,
9132 "label", label,
9133 "tooltip", tip,
9134 "icon-name", all_selected_items_in_trash (view) ?
9135 CAJA_ICON_DELETE"edit-delete" : CAJA_ICON_TRASH_FULL"user-trash-full",
9136 NULL((void*)0));
9137 gtk_action_set_sensitive (action, can_delete_files);
9138
9139 action = gtk_action_group_get_action (view->details->dir_action_group,
9140 FM_ACTION_DELETE"Delete");
9141 gtk_action_set_visible (action, show_separate_delete_command);
9142
9143 if (show_separate_delete_command) {
9144 g_object_set (action,
9145 "label", _("_Delete")dcgettext (((void*)0), "_Delete", 5),
9146 "icon-name", CAJA_ICON_DELETE"edit-delete",
9147 NULL((void*)0));
9148 }
9149 gtk_action_set_sensitive (action, can_delete_files);
9150
9151
9152 action = gtk_action_group_get_action (view->details->dir_action_group,
9153 FM_ACTION_RESTORE_FROM_TRASH"Restore From Trash");
9154 update_restore_from_trash_action (action, selection, FALSE(0));
9155
9156 action = gtk_action_group_get_action (view->details->dir_action_group,
9157 FM_ACTION_DUPLICATE"Duplicate");
9158 gtk_action_set_sensitive (action, can_duplicate_files);
9159
9160 action = gtk_action_group_get_action (view->details->dir_action_group,
9161 FM_ACTION_CREATE_LINK"Create Link");
9162 gtk_action_set_sensitive (action, can_link_files);
9163 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9164 g_object_set (action, "label",
9165 ngettext ("Ma_ke Link",dcngettext (((void*)0), "Ma_ke Link", "Ma_ke Links", selection_count
, 5)
9166 "Ma_ke Links",dcngettext (((void*)0), "Ma_ke Link", "Ma_ke Links", selection_count
, 5)
9167 selection_count)dcngettext (((void*)0), "Ma_ke Link", "Ma_ke Links", selection_count
, 5)
,
9168 NULL((void*)0));
9169
9170 show_properties = (!FM_IS_DESKTOP_ICON_VIEW (view)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view)); GType __t = (fm_desktop_icon_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; }))))
|| selection_count > 0) &&
9171 fm_directory_view_supports_properties (view);
9172
9173 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9174 action = gtk_action_group_get_action (view->details->dir_action_group,
9175 FM_ACTION_PROPERTIES"Properties");
9176
9177 gtk_action_set_sensitive (action, show_properties);
9178
9179 if (selection_count == 0) {
9180 gtk_action_set_tooltip (action, _("View or modify the properties of the open folder")dcgettext (((void*)0), "View or modify the properties of the open folder"
, 5)
);
9181 } else {
9182 gtk_action_set_tooltip (action, _("View or modify the properties of each selected item")dcgettext (((void*)0), "View or modify the properties of each selected item"
, 5)
);
9183 }
9184
9185 gtk_action_set_visible (action, show_properties);
9186
9187 action = gtk_action_group_get_action (view->details->dir_action_group,
9188 FM_ACTION_PROPERTIES_ACCEL"PropertiesAccel");
9189
9190 gtk_action_set_sensitive (action, show_properties);
9191
9192 action = gtk_action_group_get_action (view->details->dir_action_group,
9193 FM_ACTION_EMPTY_TRASH"Empty Trash");
9194 g_object_set (action,
9195 "label", _("E_mpty Trash")dcgettext (((void*)0), "E_mpty Trash", 5),
9196 NULL((void*)0));
9197 gtk_action_set_sensitive (action, !caja_trash_monitor_is_empty ());
9198 gtk_action_set_visible (action, should_show_empty_trash (view));
9199 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9200
9201 show_save_search = FALSE(0);
9202 save_search_sensitive = FALSE(0);
9203 show_save_search_as = FALSE(0);
9204 if (view->details->model &&
9205 CAJA_IS_SEARCH_DIRECTORY (view->details->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->details->model)); GType __t = (caja_search_directory_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; }))))
) {
9206 CajaSearchDirectory *search;
9207
9208 search = CAJA_SEARCH_DIRECTORY (view->details->model)((((CajaSearchDirectory*) (void *) ((view->details->model
)))))
;
9209 if (caja_search_directory_is_saved_search (search)) {
9210 show_save_search = TRUE(!(0));
9211 save_search_sensitive = caja_search_directory_is_modified (search);
9212 } else {
9213 show_save_search_as = TRUE(!(0));
9214 }
9215 }
9216 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9217 action = gtk_action_group_get_action (view->details->dir_action_group,
9218 FM_ACTION_SAVE_SEARCH"Save Search");
9219 gtk_action_set_visible (action, show_save_search);
9220 gtk_action_set_sensitive (action, save_search_sensitive);
9221 action = gtk_action_group_get_action (view->details->dir_action_group,
9222 FM_ACTION_SAVE_SEARCH_AS"Save Search As");
9223 gtk_action_set_visible (action, show_save_search_as);
9224
9225
9226 action = gtk_action_group_get_action (view->details->dir_action_group,
9227 FM_ACTION_SELECT_ALL"Select All");
9228 gtk_action_set_sensitive (action, !fm_directory_view_is_empty (view));
9229
9230 action = gtk_action_group_get_action (view->details->dir_action_group,
9231 FM_ACTION_SELECT_PATTERN"Select Pattern");
9232 gtk_action_set_sensitive (action, !fm_directory_view_is_empty (view));
9233
9234 action = gtk_action_group_get_action (view->details->dir_action_group,
9235 FM_ACTION_INVERT_SELECTION"Invert Selection");
9236 gtk_action_set_sensitive (action, !fm_directory_view_is_empty (view));
9237
9238 action = gtk_action_group_get_action (view->details->dir_action_group,
9239 FM_ACTION_CUT"Cut");
9240 gtk_action_set_sensitive (action, can_delete_files);
9241
9242 action = gtk_action_group_get_action (view->details->dir_action_group,
9243 FM_ACTION_COPY"Copy");
9244 gtk_action_set_sensitive (action, can_copy_files);
9245 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9246
9247 real_update_paste_menu (view, selection, selection_count);
9248
9249 disable_command_line = g_settings_get_boolean (mate_lockdown_preferences, CAJA_PREFERENCES_LOCKDOWN_COMMAND_LINE"disable-command-line");
9250 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9251 action = gtk_action_group_get_action (view->details->dir_action_group,
9252 FM_ACTION_NEW_LAUNCHER"New Launcher");
9253 gtk_action_set_visible (action, vfolder_directory && !disable_command_line);
9254 gtk_action_set_sensitive (action, can_create_files);
9255 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9256
9257 real_update_menus_volumes (view, selection, selection_count);
9258
9259 undo_update_menu (view);
9260
9261 caja_file_list_free (selection);
9262
9263 if (view->details->scripts_invalid) {
9264 update_scripts_menu (view);
9265 }
9266
9267 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9268 action = gtk_action_group_get_action (view->details->dir_action_group,
9269 FM_ACTION_NEW_DOCUMENTS"New Documents");
9270 gtk_action_set_sensitive (action, can_create_files);
9271 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9272
9273 if (can_create_files && view->details->templates_invalid) {
9274 update_templates_menu (view);
9275 }
9276
9277 next_pane_is_writable = has_writable_extra_pane (view);
9278
9279 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
9280 /* next pane: works if file is copyable, and next pane is writable */
9281 action = gtk_action_group_get_action (view->details->dir_action_group,
9282 FM_ACTION_COPY_TO_NEXT_PANE"Copy to next pane");
9283 gtk_action_set_sensitive (action, can_copy_files && next_pane_is_writable);
9284
9285 /* move to next pane: works if file is cuttable, and next pane is writable */
9286 action = gtk_action_group_get_action (view->details->dir_action_group,
9287 FM_ACTION_MOVE_TO_NEXT_PANE"Move to next pane");
9288 gtk_action_set_sensitive (action, can_delete_files && next_pane_is_writable);
9289
9290
9291 action = gtk_action_group_get_action (view->details->dir_action_group,
9292 FM_ACTION_COPY_TO_HOME"Copy to Home");
9293 gtk_action_set_sensitive (action, can_copy_files);
9294 action = gtk_action_group_get_action (view->details->dir_action_group,
9295 FM_ACTION_COPY_TO_DESKTOP"Copy to Desktop");
9296 gtk_action_set_sensitive (action, can_copy_files);
9297
9298 action = gtk_action_group_get_action (view->details->dir_action_group,
9299 FM_ACTION_MOVE_TO_HOME"Move to Home");
9300 gtk_action_set_sensitive (action, can_delete_files);
9301 action = gtk_action_group_get_action (view->details->dir_action_group,
9302 FM_ACTION_MOVE_TO_DESKTOP"Move to Desktop");
9303 gtk_action_set_sensitive (action, can_delete_files);
9304
9305 action = gtk_action_group_get_action (view->details->dir_action_group,
9306 "CopyToMenu");
9307 gtk_action_set_sensitive (action, can_copy_files);
9308 action = gtk_action_group_get_action (view->details->dir_action_group,
9309 "MoveToMenu");
9310 gtk_action_set_sensitive (action, can_delete_files);
9311 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
9312}
9313
9314/**
9315 * fm_directory_view_pop_up_selection_context_menu
9316 *
9317 * Pop up a context menu appropriate to the selected items.
9318 * @view: FMDirectoryView of interest.
9319 * @event: The event that triggered this context menu.
9320 *
9321 * Return value: CajaDirectory for this view.
9322 *
9323 **/
9324void
9325fm_directory_view_pop_up_selection_context_menu (FMDirectoryView *view,
9326 GdkEventButton *event)
9327{
9328 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_283
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_283
= 1; else _g_boolean_var_283 = 0; _g_boolean_var_283; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9328, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9329
9330 /* Make the context menu items not flash as they update to proper disabled,
9331 * etc. states by forcing menus to update now.
9332 */
9333 update_menus_if_pending (view);
9334
9335 update_context_menu_position_from_event (view, event);
9336
9337 /* FIXME: passing event from here won't work
9338 * for gtk_menu_popup_at_pointer (in eel_pop_up_context_menu() )
9339 * if the menu is being triggered from here by the menu key
9340 */
9341 eel_pop_up_context_menu (create_popup_menu
9342 (view, FM_DIRECTORY_VIEW_POPUP_PATH_SELECTION"/selection"),
9343 NULL((void*)0));
9344}
9345
9346/**
9347 * fm_directory_view_pop_up_background_context_menu
9348 *
9349 * Pop up a context menu appropriate to the view globally at the last right click location.
9350 * @view: FMDirectoryView of interest.
9351 *
9352 * Return value: CajaDirectory for this view.
9353 *
9354 **/
9355void
9356fm_directory_view_pop_up_background_context_menu (FMDirectoryView *view,
9357 GdkEventButton *event)
9358{
9359 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_284
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_284
= 1; else _g_boolean_var_284 = 0; _g_boolean_var_284; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9359, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9360
9361 /* Make the context menu items not flash as they update to proper disabled,
9362 * etc. states by forcing menus to update now.
9363 */
9364 update_menus_if_pending (view);
9365
9366 update_context_menu_position_from_event (view, event);
9367
9368 eel_pop_up_context_menu (create_popup_menu
9369 (view, FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND"/background"),
9370 event);
9371}
9372
9373static void
9374real_pop_up_location_context_menu (FMDirectoryView *view)
9375{
9376 /* always update the menu before showing it. Shouldn't be too expensive. */
9377 real_update_location_menu (view);
9378
9379 update_context_menu_position_from_event (view, view->details->location_popup_event);
9380
9381 eel_pop_up_context_menu (create_popup_menu
9382 (view, FM_DIRECTORY_VIEW_POPUP_PATH_LOCATION"/location"),
9383 view->details->location_popup_event);
9384}
9385
9386static void
9387location_popup_file_attributes_ready (CajaFile *file,
9388 gpointer data)
9389{
9390 FMDirectoryView *view;
9391
9392 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
9393 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_285
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_285
= 1; else _g_boolean_var_285 = 0; _g_boolean_var_285; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9393, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9394
9395 g_assert (file == view->details->location_popup_directory_as_file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_286
; if (file == view->details->location_popup_directory_as_file
) _g_boolean_var_286 = 1; else _g_boolean_var_286 = 0; _g_boolean_var_286
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9395, ((const char*) (__func__)), "file == view->details->location_popup_directory_as_file"
); } while (0)
;
9396
9397 real_pop_up_location_context_menu (view);
9398}
9399
9400static void
9401unschedule_pop_up_location_context_menu (FMDirectoryView *view)
9402{
9403 if (view->details->location_popup_directory_as_file != NULL((void*)0)) {
9404 g_assert (CAJA_IS_FILE (view->details->location_popup_directory_as_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_287
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view->details->location_popup_directory_as_file));
GType __t = (caja_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_287 = 1; else _g_boolean_var_287
= 0; _g_boolean_var_287; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 9404, ((const char*) (
__func__)), "CAJA_IS_FILE (view->details->location_popup_directory_as_file)"
); } while (0)
;
9405 caja_file_cancel_call_when_ready (view->details->location_popup_directory_as_file,
9406 location_popup_file_attributes_ready,
9407 view);
9408 caja_file_unref (view->details->location_popup_directory_as_file);
9409 view->details->location_popup_directory_as_file = NULL((void*)0);
9410 }
9411}
9412
9413static void
9414schedule_pop_up_location_context_menu (FMDirectoryView *view,
9415 GdkEventButton *event,
9416 CajaFile *file)
9417{
9418 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_288
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_288
= 1; else _g_boolean_var_288 = 0; _g_boolean_var_288; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9418, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
9419
9420 if (view->details->location_popup_event != NULL((void*)0)) {
9421 gdk_event_free ((GdkEvent *) view->details->location_popup_event);
9422 }
9423 view->details->location_popup_event = (GdkEventButton *) gdk_event_copy ((GdkEvent *)event);
9424
9425 if (file == view->details->location_popup_directory_as_file) {
9426 if (caja_file_check_if_ready (file, CAJA_FILE_ATTRIBUTE_INFO |
9427 CAJA_FILE_ATTRIBUTE_MOUNT |
9428 CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO)) {
9429 real_pop_up_location_context_menu (view);
9430 }
9431 } else {
9432 unschedule_pop_up_location_context_menu (view);
9433
9434 view->details->location_popup_directory_as_file = caja_file_ref (file);
9435 caja_file_call_when_ready (view->details->location_popup_directory_as_file,
9436 CAJA_FILE_ATTRIBUTE_INFO |
9437 CAJA_FILE_ATTRIBUTE_MOUNT |
9438 CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO,
9439 location_popup_file_attributes_ready,
9440 view);
9441 }
9442}
9443
9444/**
9445 * fm_directory_view_pop_up_location_context_menu
9446 *
9447 * Pop up a context menu appropriate to the view globally.
9448 * @view: FMDirectoryView of interest.
9449 * @event: GdkEventButton triggering the popup.
9450 * @location: The location the popup-menu should be created for,
9451 * or NULL for the currently displayed location.
9452 *
9453 **/
9454void
9455fm_directory_view_pop_up_location_context_menu (FMDirectoryView *view,
9456 GdkEventButton *event,
9457 const char *location)
9458{
9459 CajaFile *file;
9460
9461 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_289
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_289
= 1; else _g_boolean_var_289 = 0; _g_boolean_var_289; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9461, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9462
9463 if (location != NULL((void*)0)) {
9464 file = caja_file_get_by_uri (location);
9465 } else {
9466 file = caja_file_ref (view->details->directory_as_file);
9467 }
9468
9469 if (file != NULL((void*)0)) {
9470 schedule_pop_up_location_context_menu (view, event, file);
9471 caja_file_unref (file);
9472 }
9473}
9474
9475static void
9476fm_directory_view_drop_proxy_received_uris (FMDirectoryView *view,
9477 const GList *source_uri_list,
9478 const char *target_uri,
9479 GdkDragAction action)
9480{
9481 char *container_uri;
9482
9483 container_uri = NULL((void*)0);
9484 if (target_uri == NULL((void*)0)) {
9485 container_uri = fm_directory_view_get_backing_uri (view);
9486 g_assert (container_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_290
; if (container_uri != ((void*)0)) _g_boolean_var_290 = 1; else
_g_boolean_var_290 = 0; _g_boolean_var_290; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 9486, ((const char*) (
__func__)), "container_uri != NULL"); } while (0)
;
9487 }
9488
9489 if (action == GDK_ACTION_ASK) {
9490 action = caja_drag_drop_action_ask
9491 (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))),
9492 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
9493 if (action == 0) {
9494 return;
9495 }
9496 }
9497
9498 caja_clipboard_clear_if_colliding_uris (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))),
9499 source_uri_list,
9500 fm_directory_view_get_copied_files_atom (view));
9501
9502 fm_directory_view_move_copy_items (source_uri_list, NULL((void*)0),
9503 target_uri != NULL((void*)0) ? target_uri : container_uri,
9504 action, 0, 0, view);
9505
9506 g_free (container_uri);
9507}
9508
9509static void
9510fm_directory_view_drop_proxy_received_netscape_url (FMDirectoryView *view,
9511 const char *netscape_url,
9512 const char *target_uri,
9513 GdkDragAction action)
9514{
9515 fm_directory_view_handle_netscape_url_drop (view,
9516 netscape_url,
9517 target_uri,
9518 action, 0, 0);
9519}
9520
9521static void
9522schedule_update_menus (FMDirectoryView *view)
9523{
9524 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_291
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_291
= 1; else _g_boolean_var_291 = 0; _g_boolean_var_291; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9524, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9525
9526 /* Don't schedule updates after destroy (#349551),
9527 * or if we are not active.
9528 */
9529 if (view->details->window == NULL((void*)0) ||
9530 !view->details->active) {
9531 return;
9532 }
9533
9534 view->details->menu_states_untrustworthy = TRUE(!(0));
9535
9536 /* Schedule a menu update with the current update interval */
9537 if (view->details->update_menus_timeout_id == 0) {
9538 view->details->update_menus_timeout_id
9539 = g_timeout_add (view->details->update_interval, update_menus_timeout_callback, view);
9540 }
9541}
9542
9543static void
9544remove_update_status_idle_callback (FMDirectoryView *view)
9545{
9546 if (view->details->update_status_idle_id != 0) {
9547 g_source_remove (view->details->update_status_idle_id);
9548 view->details->update_status_idle_id = 0;
9549 }
9550}
9551
9552static gboolean
9553update_status_idle_callback (gpointer data)
9554{
9555 FMDirectoryView *view;
9556
9557 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
9558 fm_directory_view_display_selection_info (view);
9559 view->details->update_status_idle_id = 0;
9560 return FALSE(0);
9561}
9562
9563static void
9564schedule_update_status (FMDirectoryView *view)
9565{
9566 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_292
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_292
= 1; else _g_boolean_var_292 = 0; _g_boolean_var_292; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9566, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9567
9568 /* Make sure we haven't already destroyed it */
9569 if (view->details->window == NULL((void*)0)) {
9570 return;
9571 }
9572
9573 if (view->details->loading) {
9574 /* Don't update status bar while loading the dir */
9575 return;
9576 }
9577
9578 if (view->details->update_status_idle_id == 0) {
9579 view->details->update_status_idle_id =
9580 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE200 - 20,
9581 update_status_idle_callback, view, NULL((void*)0));
9582 }
9583}
9584
9585/**
9586 * fm_directory_view_notify_selection_changed:
9587 *
9588 * Notify this view that the selection has changed. This is normally
9589 * called only by subclasses.
9590 * @view: FMDirectoryView whose selection has changed.
9591 *
9592 **/
9593void
9594fm_directory_view_notify_selection_changed (FMDirectoryView *view)
9595{
9596 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_293
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_293
= 1; else _g_boolean_var_293 = 0; _g_boolean_var_293; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
9597
9598 if (caja_debug_log_is_domain_enabled (CAJA_DEBUG_LOG_DOMAIN_USER"USER")) {
9599 GList *selection;
9600 GtkWindow *window;
9601
9602 selection = fm_directory_view_get_selection (view);
9603
9604 window = fm_directory_view_get_containing_window (view);
9605 caja_debug_log_with_file_list (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER", selection,
9606 "selection changed in window %p",
9607 window);
9608 caja_file_list_free (selection);
9609 }
9610
9611 view->details->selection_was_removed = FALSE(0);
9612
9613 if (!view->details->selection_change_is_due_to_shell) {
9614 view->details->send_selection_change_to_shell = TRUE(!(0));
9615 }
9616
9617 /* Schedule a display of the new selection. */
9618 if (view->details->display_selection_idle_id == 0) {
9619 view->details->display_selection_idle_id
9620 = g_idle_add (display_selection_info_idle_callback,
9621 view);
9622 }
9623
9624 if (view->details->batching_selection_level != 0) {
9625 view->details->selection_changed_while_batched = TRUE(!(0));
9626 } else {
9627 /* Here is the work we do only when we're not
9628 * batching selection changes. In other words, it's the slower
9629 * stuff that we don't want to slow down selection techniques
9630 * such as rubberband-selecting in icon view.
9631 */
9632
9633 /* Schedule an update of menu item states to match selection */
9634 schedule_update_menus (view);
9635 }
9636}
9637
9638static void
9639file_changed_callback (CajaFile *file, gpointer callback_data)
9640{
9641 FMDirectoryView *view = FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data)))));
9642
9643 schedule_changes (view);
9644
9645 schedule_update_menus (view);
9646 schedule_update_status (view);
9647
9648 /* We might have different capabilities, so we need to update
9649 * relative icon emblems . (Writeable etc).
9650 * Don't do this for trash, as it never changes writability
9651 * but does change a lot for the file count attribute.
9652 */
9653 if (!caja_file_is_in_trash (file)) {
9654 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->emblems_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->emblems_changed) (view); } } while (0)
9655 (FM_DIRECTORY_VIEW_CLASS, view, emblems_changed, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->emblems_changed
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->emblems_changed) (view); } } while (0)
;
9656 }
9657}
9658
9659/**
9660 * load_directory:
9661 *
9662 * Switch the displayed location to a new uri. If the uri is not valid,
9663 * the location will not be switched; user feedback will be provided instead.
9664 * @view: FMDirectoryView whose location will be changed.
9665 * @uri: A string representing the uri to switch to.
9666 *
9667 **/
9668static void
9669load_directory (FMDirectoryView *view,
9670 CajaDirectory *directory)
9671{
9672 CajaDirectory *old_directory;
9673 CajaFile *old_file;
9674 CajaFileAttributes attributes;
9675
9676 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_294
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_294
= 1; else _g_boolean_var_294 = 0; _g_boolean_var_294; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9676, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9677 g_assert (CAJA_IS_DIRECTORY (directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_295
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9677, ((const char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"
); } while (0)
;
9678
9679 fm_directory_view_stop (view);
9680 fm_directory_view_clear (view);
9681
9682 view->details->loading = TRUE(!(0));
9683
9684 /* Update menus when directory is empty, before going to new
9685 * location, so they won't have any false lingering knowledge
9686 * of old selection.
9687 */
9688 schedule_update_menus (view);
9689
9690 while (view->details->subdirectory_list != NULL((void*)0)) {
9691 fm_directory_view_remove_subdirectory (view,
9692 view->details->subdirectory_list->data);
9693 }
9694
9695 disconnect_model_handlers (view);
9696
9697 old_directory = view->details->model;
9698 caja_directory_ref (directory);
9699 view->details->model = directory;
9700 caja_directory_unref (old_directory);
9701
9702 old_file = view->details->directory_as_file;
9703 view->details->directory_as_file =
9704 caja_directory_get_corresponding_file (directory);
9705 caja_file_unref (old_file);
9706
9707 view->details->reported_load_error = FALSE(0);
9708
9709 /* FIXME bugzilla.gnome.org 45062: In theory, we also need to monitor metadata here (as
9710 * well as doing a call when ready), in case external forces
9711 * change the directory's file metadata.
9712 */
9713 attributes =
9714 CAJA_FILE_ATTRIBUTE_INFO |
9715 CAJA_FILE_ATTRIBUTE_MOUNT |
9716 CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO;
9717 view->details->metadata_for_directory_as_file_pending = TRUE(!(0));
9718 view->details->metadata_for_files_in_directory_pending = TRUE(!(0));
9719 caja_file_call_when_ready
9720 (view->details->directory_as_file,
9721 attributes,
9722 metadata_for_directory_as_file_ready_callback, view);
9723 caja_directory_call_when_ready
9724 (view->details->model,
9725 attributes,
9726 FALSE(0),
9727 metadata_for_files_in_directory_ready_callback, view);
9728
9729 /* If capabilities change, then we need to update the menus
9730 * because of New Folder, and relative emblems.
9731 */
9732 attributes =
9733 CAJA_FILE_ATTRIBUTE_INFO |
9734 CAJA_FILE_ATTRIBUTE_FILESYSTEM_INFO;
9735 caja_file_monitor_add (view->details->directory_as_file,
9736 &view->details->directory_as_file,
9737 attributes);
9738
9739 view->details->file_changed_handler_id = g_signal_connectg_signal_connect_data ((view->details->directory_as_file
), ("changed"), (((GCallback) (file_changed_callback))), (view
), ((void*)0), (GConnectFlags) 0)
9740 (view->details->directory_as_file, "changed",g_signal_connect_data ((view->details->directory_as_file
), ("changed"), (((GCallback) (file_changed_callback))), (view
), ((void*)0), (GConnectFlags) 0)
9741 G_CALLBACK (file_changed_callback), view)g_signal_connect_data ((view->details->directory_as_file
), ("changed"), (((GCallback) (file_changed_callback))), (view
), ((void*)0), (GConnectFlags) 0)
;
9742}
9743
9744static void
9745finish_loading (FMDirectoryView *view)
9746{
9747 CajaFileAttributes attributes;
9748
9749 caja_window_info_report_load_underway (view->details->window,
9750 CAJA_VIEW (view)((((CajaView*) (void *) ((view))))));
9751
9752 /* Tell interested parties that we've begun loading this directory now.
9753 * Subclasses use this to know that the new metadata is now available.
9754 */
9755 fm_directory_view_begin_loading (view);
9756
9757 /* Assume we have now all information to show window */
9758 caja_window_info_view_visible (view->details->window, CAJA_VIEW (view)((((CajaView*) (void *) ((view))))));
9759
9760 if (caja_directory_are_all_files_seen (view->details->model)) {
9761 /* Unschedule a pending update and schedule a new one with the minimal
9762 * update interval. This gives the view a short chance at gathering the
9763 * (cached) deep counts.
9764 */
9765 unschedule_display_of_pending_files (view);
9766 schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN100);
9767 }
9768
9769 /* Start loading. */
9770
9771 /* Connect handlers to learn about loading progress. */
9772 view->details->done_loading_handler_id = g_signal_connectg_signal_connect_data ((view->details->model), ("done_loading"
), (((GCallback) (done_loading_callback))), (view), ((void*)0
), (GConnectFlags) 0)
9773 (view->details->model, "done_loading",g_signal_connect_data ((view->details->model), ("done_loading"
), (((GCallback) (done_loading_callback))), (view), ((void*)0
), (GConnectFlags) 0)
9774 G_CALLBACK (done_loading_callback), view)g_signal_connect_data ((view->details->model), ("done_loading"
), (((GCallback) (done_loading_callback))), (view), ((void*)0
), (GConnectFlags) 0)
;
9775 view->details->load_error_handler_id = g_signal_connectg_signal_connect_data ((view->details->model), ("load_error"
), (((GCallback) (load_error_callback))), (view), ((void*)0),
(GConnectFlags) 0)
9776 (view->details->model, "load_error",g_signal_connect_data ((view->details->model), ("load_error"
), (((GCallback) (load_error_callback))), (view), ((void*)0),
(GConnectFlags) 0)
9777 G_CALLBACK (load_error_callback), view)g_signal_connect_data ((view->details->model), ("load_error"
), (((GCallback) (load_error_callback))), (view), ((void*)0),
(GConnectFlags) 0)
;
9778
9779 /* Monitor the things needed to get the right icon. Also
9780 * monitor a directory's item count because the "size"
9781 * attribute is based on that, and the file's metadata
9782 * and possible custom name.
9783 */
9784 attributes =
9785 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
|
9786 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
9787 CAJA_FILE_ATTRIBUTE_INFO |
9788 CAJA_FILE_ATTRIBUTE_LINK_INFO |
9789 CAJA_FILE_ATTRIBUTE_MOUNT |
9790 CAJA_FILE_ATTRIBUTE_EXTENSION_INFO;
9791
9792 caja_directory_file_monitor_add (view->details->model,
9793 &view->details->model,
9794 view->details->show_hidden_files,
9795 attributes,
9796 files_added_callback, view);
9797
9798 view->details->files_added_handler_id = g_signal_connectg_signal_connect_data ((view->details->model), ("files_added"
), (((GCallback) (files_added_callback))), (view), ((void*)0)
, (GConnectFlags) 0)
9799 (view->details->model, "files_added",g_signal_connect_data ((view->details->model), ("files_added"
), (((GCallback) (files_added_callback))), (view), ((void*)0)
, (GConnectFlags) 0)
9800 G_CALLBACK (files_added_callback), view)g_signal_connect_data ((view->details->model), ("files_added"
), (((GCallback) (files_added_callback))), (view), ((void*)0)
, (GConnectFlags) 0)
;
9801 view->details->files_changed_handler_id = g_signal_connectg_signal_connect_data ((view->details->model), ("files_changed"
), (((GCallback) (files_changed_callback))), (view), ((void*)
0), (GConnectFlags) 0)
9802 (view->details->model, "files_changed",g_signal_connect_data ((view->details->model), ("files_changed"
), (((GCallback) (files_changed_callback))), (view), ((void*)
0), (GConnectFlags) 0)
9803 G_CALLBACK (files_changed_callback), view)g_signal_connect_data ((view->details->model), ("files_changed"
), (((GCallback) (files_changed_callback))), (view), ((void*)
0), (GConnectFlags) 0)
;
9804}
9805
9806static void
9807finish_loading_if_all_metadata_loaded (FMDirectoryView *view)
9808{
9809 if (!view->details->metadata_for_directory_as_file_pending &&
9810 !view->details->metadata_for_files_in_directory_pending) {
9811 finish_loading (view);
9812 }
9813}
9814
9815static void
9816metadata_for_directory_as_file_ready_callback (CajaFile *file,
9817 gpointer callback_data)
9818{
9819 FMDirectoryView *view;
9820
9821 view = callback_data;
9822
9823 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_296
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_296
= 1; else _g_boolean_var_296 = 0; _g_boolean_var_296; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9823, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9824 g_assert (view->details->directory_as_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_297
; if (view->details->directory_as_file == file) _g_boolean_var_297
= 1; else _g_boolean_var_297 = 0; _g_boolean_var_297; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9824, ((const char*) (__func__)), "view->details->directory_as_file == file"
); } while (0)
;
9825 g_assert (view->details->metadata_for_directory_as_file_pending)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_298
; if (view->details->metadata_for_directory_as_file_pending
) _g_boolean_var_298 = 1; else _g_boolean_var_298 = 0; _g_boolean_var_298
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9825, ((const char*) (__func__)), "view->details->metadata_for_directory_as_file_pending"
); } while (0)
;
9826
9827 view->details->metadata_for_directory_as_file_pending = FALSE(0);
9828
9829 finish_loading_if_all_metadata_loaded (view);
9830}
9831
9832static void
9833metadata_for_files_in_directory_ready_callback (CajaDirectory *directory,
9834 GList *files,
9835 gpointer callback_data)
9836{
9837 FMDirectoryView *view;
9838
9839 view = callback_data;
9840
9841 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_299
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_299
= 1; else _g_boolean_var_299 = 0; _g_boolean_var_299; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9841, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9842 g_assert (view->details->model == directory)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_300
; if (view->details->model == directory) _g_boolean_var_300
= 1; else _g_boolean_var_300 = 0; _g_boolean_var_300; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9842, ((const char*) (__func__)), "view->details->model == directory"
); } while (0)
;
9843 g_assert (view->details->metadata_for_files_in_directory_pending)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_301
; if (view->details->metadata_for_files_in_directory_pending
) _g_boolean_var_301 = 1; else _g_boolean_var_301 = 0; _g_boolean_var_301
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9843, ((const char*) (__func__)), "view->details->metadata_for_files_in_directory_pending"
); } while (0)
;
9844
9845 view->details->metadata_for_files_in_directory_pending = FALSE(0);
9846
9847 finish_loading_if_all_metadata_loaded (view);
9848}
9849
9850static void
9851finish_undoredo_callback (gpointer data)
9852{
9853}
9854
9855char **
9856fm_directory_view_get_emblem_names_to_exclude (FMDirectoryView *view)
9857{
9858 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_302
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_302
= 1; else _g_boolean_var_302 = 0; _g_boolean_var_302; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
9859
9860 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_emblem_names_to_exclude
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_emblem_names_to_exclude) (view))
9861 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_emblem_names_to_exclude
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_emblem_names_to_exclude) (view))
9862 get_emblem_names_to_exclude, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_emblem_names_to_exclude
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_emblem_names_to_exclude) (view))
;
9863}
9864
9865static char **
9866real_get_emblem_names_to_exclude (FMDirectoryView *view)
9867{
9868 char **excludes;
9869 int i;
9870
9871 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_303
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_303
= 1; else _g_boolean_var_303 = 0; _g_boolean_var_303; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 9871, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
9872
9873 excludes = g_new (char *, 3)(char * *) (__extension__ ({ gsize __n = (gsize) (3); 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;
}))
;
9874
9875 i = 0;
9876 excludes[i++] = g_strdup (CAJA_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash");
9877
9878 if (!caja_file_can_write (view->details->directory_as_file)) {
9879 excludes[i++] = g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite");
9880 }
9881
9882 excludes[i++] = NULL((void*)0);
9883
9884 return excludes;
9885}
9886
9887/**
9888 * fm_directory_view_merge_menus:
9889 *
9890 * Add this view's menus to the window's menu bar.
9891 * @view: FMDirectoryView in question.
9892 */
9893static void
9894fm_directory_view_merge_menus (FMDirectoryView *view)
9895{
9896 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_304
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_304
= 1; else _g_boolean_var_304 = 0; _g_boolean_var_304; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
9897
9898 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->merge_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->merge_menus) (view); } } while (0)
9899 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->merge_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->merge_menus) (view); } } while (0)
9900 merge_menus, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->merge_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->merge_menus) (view); } } while (0)
;
9901}
9902
9903static void
9904fm_directory_view_unmerge_menus (FMDirectoryView *view)
9905{
9906 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_305
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_305
= 1; else _g_boolean_var_305 = 0; _g_boolean_var_305; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
9907
9908 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->unmerge_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->unmerge_menus) (view); } } while (0)
9909 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->unmerge_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->unmerge_menus) (view); } } while (0)
9910 unmerge_menus, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->unmerge_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->unmerge_menus) (view); } } while (0)
;
9911}
9912
9913static void
9914disconnect_handler (GObject *object, guint *id)
9915{
9916 if (*id != 0) {
9917 g_signal_handler_disconnect (object, *id);
9918 *id = 0;
9919 }
9920}
9921
9922static void
9923disconnect_directory_handler (FMDirectoryView *view, guint *id)
9924{
9925 disconnect_handler (G_OBJECT (view->details->model)((((GObject*) (void *) ((view->details->model))))), id);
9926}
9927
9928static void
9929disconnect_directory_as_file_handler (FMDirectoryView *view, guint *id)
9930{
9931 disconnect_handler (G_OBJECT (view->details->directory_as_file)((((GObject*) (void *) ((view->details->directory_as_file
)))))
, id);
9932}
9933
9934static void
9935disconnect_model_handlers (FMDirectoryView *view)
9936{
9937 if (view->details->model == NULL((void*)0)) {
9938 return;
9939 }
9940 disconnect_directory_handler (view, &view->details->files_added_handler_id);
9941 disconnect_directory_handler (view, &view->details->files_changed_handler_id);
9942 disconnect_directory_handler (view, &view->details->done_loading_handler_id);
9943 disconnect_directory_handler (view, &view->details->load_error_handler_id);
9944 disconnect_directory_as_file_handler (view, &view->details->file_changed_handler_id);
9945 caja_file_cancel_call_when_ready (view->details->directory_as_file,
9946 metadata_for_directory_as_file_ready_callback,
9947 view);
9948 caja_directory_cancel_callback (view->details->model,
9949 metadata_for_files_in_directory_ready_callback,
9950 view);
9951 caja_directory_file_monitor_remove (view->details->model,
9952 &view->details->model);
9953 caja_file_monitor_remove (view->details->directory_as_file,
9954 &view->details->directory_as_file);
9955}
9956
9957/**
9958 * fm_directory_view_reset_to_defaults:
9959 *
9960 * set sorting order, zoom level, etc. to match defaults
9961 *
9962 **/
9963void
9964fm_directory_view_reset_to_defaults (FMDirectoryView *view)
9965{
9966 CajaWindowShowHiddenFilesMode mode;
9967
9968 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_306
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_306
= 1; else _g_boolean_var_306 = 0; _g_boolean_var_306; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
9969
9970 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->reset_to_defaults
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->reset_to_defaults) (view); } } while (0)
9971 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->reset_to_defaults
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->reset_to_defaults) (view); } } while (0)
9972 reset_to_defaults, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->reset_to_defaults
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->reset_to_defaults) (view); } } while (0)
;
9973 mode = caja_window_info_get_hidden_files_mode (view->details->window);
9974 if (mode != CAJA_WINDOW_SHOW_HIDDEN_FILES_DEFAULT) {
9975 caja_window_info_set_hidden_files_mode (view->details->window,
9976 CAJA_WINDOW_SHOW_HIDDEN_FILES_DEFAULT);
9977 }
9978}
9979
9980/**
9981 * fm_directory_view_select_all:
9982 *
9983 * select all the items in the view
9984 *
9985 **/
9986void
9987fm_directory_view_select_all (FMDirectoryView *view)
9988{
9989 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_307
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_307
= 1; else _g_boolean_var_307 = 0; _g_boolean_var_307; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
9990
9991 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->select_all
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->select_all) (view); } } while (0)
9992 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->select_all
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->select_all) (view); } } while (0)
9993 select_all, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->select_all
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->select_all) (view); } } while (0)
;
9994}
9995
9996/**
9997 * fm_directory_view_set_selection:
9998 *
9999 * set the selection to the items identified in @selection. @selection
10000 * should be a list of CajaFiles
10001 *
10002 **/
10003void
10004fm_directory_view_set_selection (FMDirectoryView *view, GList *selection)
10005{
10006 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_308
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_308
= 1; else _g_boolean_var_308 = 0; _g_boolean_var_308; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
10007
10008 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->set_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->set_selection) (view, selection); } } while (0)
10009 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->set_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->set_selection) (view, selection); } } while (0)
10010 set_selection, (view, selection))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->set_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->set_selection) (view, selection); } } while (0)
;
10011}
10012
10013static void
10014fm_directory_view_select_file (FMDirectoryView *view, CajaFile *file)
10015{
10016 GList file_list;
10017
10018 file_list.data = file;
10019 file_list.next = NULL((void*)0);
10020 file_list.prev = NULL((void*)0);
10021 fm_directory_view_set_selection (view, &file_list);
10022}
10023
10024/**
10025 * fm_directory_view_get_selected_icon_locations:
10026 *
10027 * return an array of locations of selected icons if available
10028 * Return value: GArray of GdkPoints
10029 *
10030 **/
10031GArray *
10032fm_directory_view_get_selected_icon_locations (FMDirectoryView *view)
10033{
10034 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_309
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_309
= 1; else _g_boolean_var_309 = 0; _g_boolean_var_309; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
10035
10036 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selected_icon_locations
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selected_icon_locations) (view))
10037 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selected_icon_locations
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selected_icon_locations) (view))
10038 get_selected_icon_locations, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->get_selected_icon_locations
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->get_selected_icon_locations) (view))
;
10039}
10040
10041/**
10042 * fm_directory_view_reveal_selection:
10043 *
10044 * Scroll as necessary to reveal the selected items.
10045 **/
10046void
10047fm_directory_view_reveal_selection (FMDirectoryView *view)
10048{
10049 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_310
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_310
= 1; else _g_boolean_var_310 = 0; _g_boolean_var_310; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
10050
10051 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->reveal_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->reveal_selection) (view); } } while (0)
10052 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->reveal_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->reveal_selection) (view); } } while (0)
10053 reveal_selection, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->reveal_selection
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->reveal_selection) (view); } } while (0)
;
10054}
10055
10056/**
10057 * fm_directory_view_stop:
10058 *
10059 * Stop the current ongoing process, such as switching to a new uri.
10060 * @view: FMDirectoryView in question.
10061 *
10062 **/
10063void
10064fm_directory_view_stop (FMDirectoryView *view)
10065{
10066 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_311
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_311
= 1; else _g_boolean_var_311 = 0; _g_boolean_var_311; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
10067
10068 unschedule_display_of_pending_files (view);
10069 reset_update_interval (view);
10070
10071 /* Free extra undisplayed files */
10072 file_and_directory_list_free (view->details->new_added_files);
10073 view->details->new_added_files = NULL((void*)0);
10074 file_and_directory_list_free (view->details->new_changed_files);
10075 view->details->new_changed_files = NULL((void*)0);
10076 g_hash_table_remove_all (view->details->non_ready_files);
10077 file_and_directory_list_free (view->details->old_added_files);
10078 view->details->old_added_files = NULL((void*)0);
10079 file_and_directory_list_free (view->details->old_changed_files);
10080 view->details->old_changed_files = NULL((void*)0);
10081 g_list_free_full (view->details->pending_locations_selected, g_object_unref);
10082 view->details->pending_locations_selected = NULL((void*)0);
10083
10084 if (view->details->model != NULL((void*)0)) {
10085 caja_directory_file_monitor_remove (view->details->model, view);
10086 }
10087 done_loading (view, FALSE(0));
10088}
10089
10090gboolean
10091fm_directory_view_is_read_only (FMDirectoryView *view)
10092{
10093 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_312
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_312
= 1; else _g_boolean_var_312 = 0; _g_boolean_var_312; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10094
10095 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->is_read_only
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->is_read_only) (view))
10096 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->is_read_only
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->is_read_only) (view))
10097 is_read_only, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->is_read_only
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->is_read_only) (view))
;
10098}
10099
10100gboolean
10101fm_directory_view_is_empty (FMDirectoryView *view)
10102{
10103 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_313
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_313
= 1; else _g_boolean_var_313 = 0; _g_boolean_var_313; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10104
10105 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->is_empty ==
((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *) ((
((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))
)))))))->is_empty) (view))
10106 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->is_empty ==
((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *) ((
((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))
)))))))->is_empty) (view))
10107 is_empty, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->is_empty ==
((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *) ((
((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))
)))))))->is_empty) (view))
;
10108}
10109
10110gboolean
10111fm_directory_view_is_editable (FMDirectoryView *view)
10112{
10113 CajaDirectory *directory;
10114
10115 directory = fm_directory_view_get_model (view);
10116
10117 if (directory != NULL((void*)0)) {
10118 return caja_directory_is_editable (directory);
10119 }
10120
10121 return TRUE(!(0));
10122}
10123
10124void
10125fm_directory_view_set_initiated_unmount (FMDirectoryView *view,
10126 gboolean initiated_unmount)
10127{
10128 if (view->details->window != NULL((void*)0)) {
10129 caja_window_info_set_initiated_unmount(view->details->window,
10130 initiated_unmount);
10131 }
10132}
10133
10134static gboolean
10135real_is_read_only (FMDirectoryView *view)
10136{
10137 CajaFile *file;
10138
10139 if (!fm_directory_view_is_editable (view)) {
10140 return TRUE(!(0));
10141 }
10142
10143 file = fm_directory_view_get_directory_as_file (view);
10144 if (file != NULL((void*)0)) {
10145 return !caja_file_can_write (file);
10146 }
10147 return FALSE(0);
10148}
10149
10150gboolean
10151fm_directory_view_supports_creating_files (FMDirectoryView *view)
10152{
10153 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_314
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_314
= 1; else _g_boolean_var_314 = 0; _g_boolean_var_314; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10154
10155 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_creating_files
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_creating_files) (view))
10156 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_creating_files
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_creating_files) (view))
10157 supports_creating_files, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_creating_files
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_creating_files) (view))
;
10158}
10159
10160gboolean
10161fm_directory_view_accepts_dragged_files (FMDirectoryView *view)
10162{
10163 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_315
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_315
= 1; else _g_boolean_var_315 = 0; _g_boolean_var_315; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10164
10165 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->accepts_dragged_files
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->accepts_dragged_files) (view))
10166 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->accepts_dragged_files
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->accepts_dragged_files) (view))
10167 accepts_dragged_files, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->accepts_dragged_files
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->accepts_dragged_files) (view))
;
10168}
10169
10170/**
10171 * fm_directory_view_should_show_file
10172 *
10173 * Returns whether or not this file should be displayed based on
10174 * current filtering options.
10175 */
10176gboolean
10177fm_directory_view_should_show_file (FMDirectoryView *view, CajaFile *file)
10178{
10179 return caja_file_should_show (file,
10180 view->details->show_hidden_files,
10181 view->details->show_foreign_files,
10182 view->details->show_backup_files);
10183}
10184
10185static gboolean
10186real_supports_creating_files (FMDirectoryView *view)
10187{
10188 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_316
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_316
= 1; else _g_boolean_var_316 = 0; _g_boolean_var_316; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10189
10190 return !fm_directory_view_is_read_only (view) && !showing_trash_directory (view);
10191}
10192
10193static gboolean
10194real_accepts_dragged_files (FMDirectoryView *view)
10195{
10196 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_317
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_317
= 1; else _g_boolean_var_317 = 0; _g_boolean_var_317; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10197
10198 return !fm_directory_view_is_read_only (view);
10199}
10200
10201gboolean
10202fm_directory_view_supports_properties (FMDirectoryView *view)
10203{
10204 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_318
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_318
= 1; else _g_boolean_var_318 = 0; _g_boolean_var_318; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10205
10206 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_properties
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_properties) (view))
10207 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_properties
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_properties) (view))
10208 supports_properties, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_properties
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_properties) (view))
;
10209}
10210
10211static gboolean
10212real_supports_properties (FMDirectoryView *view)
10213{
10214 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_319
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_319
= 1; else _g_boolean_var_319 = 0; _g_boolean_var_319; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10215
10216 return TRUE(!(0));
10217}
10218
10219gboolean
10220fm_directory_view_supports_zooming (FMDirectoryView *view)
10221{
10222 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_320
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_320
= 1; else _g_boolean_var_320 = 0; _g_boolean_var_320; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10223
10224 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_zooming
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_zooming) (view))
10225 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_zooming
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_zooming) (view))
10226 supports_zooming, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->supports_zooming
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->supports_zooming) (view))
;
10227}
10228
10229static gboolean
10230real_supports_zooming (FMDirectoryView *view)
10231{
10232 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_321
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_321
= 1; else _g_boolean_var_321 = 0; _g_boolean_var_321; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10233
10234 return TRUE(!(0));
10235}
10236
10237gboolean
10238fm_directory_view_using_manual_layout (FMDirectoryView *view)
10239{
10240 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_322
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_322
= 1; else _g_boolean_var_322 = 0; _g_boolean_var_322; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10241
10242 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->using_manual_layout
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->using_manual_layout) (view))
10243 (FM_DIRECTORY_VIEW_CLASS, view,(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->using_manual_layout
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->using_manual_layout) (view))
10244 using_manual_layout, (view))(((((FMDirectoryViewClass*) (void *) ((((((GObjectClass*) (((
GTypeInstance*) ((view)))->g_class)))))))))->using_manual_layout
== ((void*)0)) ? 0 : ((* ((((FMDirectoryViewClass*) (void *)
((((((GObjectClass*) (((GTypeInstance*) ((view)))->g_class
)))))))))->using_manual_layout) (view))
;
10245}
10246
10247static gboolean
10248real_using_manual_layout (FMDirectoryView *view)
10249{
10250 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_323
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_323
= 1; else _g_boolean_var_323 = 0; _g_boolean_var_323; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10251
10252 return FALSE(0);
10253}
10254
10255/**
10256 * fm_directory_view_update_menus:
10257 *
10258 * Update the sensitivity and wording of dynamic menu items.
10259 * @view: FMDirectoryView in question.
10260 */
10261void
10262fm_directory_view_update_menus (FMDirectoryView *view)
10263{
10264 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_324
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_324
= 1; else _g_boolean_var_324 = 0; _g_boolean_var_324; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
10265
10266 if (!view->details->active) {
10267 return;
10268 }
10269
10270
10271 EEL_CALL_METHODdo { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->update_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->update_menus) (view); } } while (0)
10272 (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->update_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->update_menus) (view); } } while (0)
10273 update_menus, (view))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->update_menus
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->update_menus) (view); } } while (0)
;
10274
10275 view->details->menu_states_untrustworthy = FALSE(0);
10276}
10277
10278static void
10279schedule_update_menus_callback (gpointer callback_data)
10280{
10281 schedule_update_menus (FM_DIRECTORY_VIEW (callback_data)((((FMDirectoryView*) (void *) ((callback_data))))));
10282}
10283
10284void
10285fm_directory_view_ignore_hidden_file_preferences (FMDirectoryView *view)
10286{
10287 g_return_if_fail (view->details->model == NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_325
; if (view->details->model == ((void*)0)) _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__)), "view->details->model == NULL"); return
; } } while (0)
;
10288
10289 if (view->details->ignore_hidden_file_preferences) {
10290 return;
10291 }
10292
10293 view->details->show_hidden_files = FALSE(0);
10294 view->details->ignore_hidden_file_preferences = TRUE(!(0));
10295}
10296
10297void
10298fm_directory_view_set_show_foreign (FMDirectoryView *view,
10299 gboolean show_foreign)
10300{
10301 view->details->show_foreign_files = show_foreign;
10302}
10303
10304char *
10305fm_directory_view_get_uri (FMDirectoryView *view)
10306{
10307 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_326
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_326
= 1; else _g_boolean_var_326 = 0; _g_boolean_var_326; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
10308 if (view->details->model == NULL((void*)0)) {
10309 return NULL((void*)0);
10310 }
10311 return caja_directory_get_uri (view->details->model);
10312}
10313
10314/* Get the real directory where files will be stored and created */
10315char *
10316fm_directory_view_get_backing_uri (FMDirectoryView *view)
10317{
10318 CajaDirectory *directory;
10319 char *uri;
10320
10321 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_327
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_327
= 1; else _g_boolean_var_327 = 0; _g_boolean_var_327; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
((void*)0)); } } while (0)
;
10322
10323 if (view->details->model == NULL((void*)0)) {
10324 return NULL((void*)0);
10325 }
10326
10327 directory = view->details->model;
10328
10329 if (CAJA_IS_DESKTOP_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_desktop_directory_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; }
))))
) {
10330 directory = caja_desktop_directory_get_real_directory (CAJA_DESKTOP_DIRECTORY (directory)((((CajaDesktopDirectory*) (void *) ((directory))))));
10331 } else {
10332 caja_directory_ref (directory);
10333 }
10334
10335 uri = caja_directory_get_uri (directory);
10336
10337 caja_directory_unref (directory);
10338
10339 return uri;
10340}
10341
10342void
10343fm_directory_view_move_copy_items (const GList *item_uris,
10344 GArray *relative_item_points,
10345 const char *target_uri,
10346 int copy_action,
10347 int x, int y,
10348 FMDirectoryView *view)
10349{
10350 CajaFile *target_file;
10351
10352 g_assert (relative_item_points == NULLdo { if (__builtin_expect (__extension__ ({ int _g_boolean_var_328
; if (relative_item_points == ((void*)0) || relative_item_points
->len == 0 || g_list_length ((GList *)item_uris) == relative_item_points
->len) _g_boolean_var_328 = 1; else _g_boolean_var_328 = 0
; _g_boolean_var_328; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 10354, ((const char*) (
__func__)), "relative_item_points == NULL || relative_item_points->len == 0 || g_list_length ((GList *)item_uris) == relative_item_points->len"
); } while (0)
10353 || relative_item_points->len == 0do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_328
; if (relative_item_points == ((void*)0) || relative_item_points
->len == 0 || g_list_length ((GList *)item_uris) == relative_item_points
->len) _g_boolean_var_328 = 1; else _g_boolean_var_328 = 0
; _g_boolean_var_328; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 10354, ((const char*) (
__func__)), "relative_item_points == NULL || relative_item_points->len == 0 || g_list_length ((GList *)item_uris) == relative_item_points->len"
); } while (0)
10354 || g_list_length ((GList *)item_uris) == relative_item_points->len)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_328
; if (relative_item_points == ((void*)0) || relative_item_points
->len == 0 || g_list_length ((GList *)item_uris) == relative_item_points
->len) _g_boolean_var_328 = 1; else _g_boolean_var_328 = 0
; _g_boolean_var_328; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 10354, ((const char*) (
__func__)), "relative_item_points == NULL || relative_item_points->len == 0 || g_list_length ((GList *)item_uris) == relative_item_points->len"
); } while (0)
;
10355
10356 /* add the drop location to the icon offsets */
10357 offset_drop_points (relative_item_points, x, y);
10358
10359 target_file = caja_file_get_existing_by_uri (target_uri);
10360 /* special-case "command:" here instead of starting a move/copy */
10361 if (target_file != NULL((void*)0) && caja_file_is_launcher (target_file)) {
10362 caja_file_unref (target_file);
10363 caja_launch_desktop_file (
10364 gtk_widget_get_screen (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view)))))),
10365 target_uri, item_uris,
10366 fm_directory_view_get_containing_window (view));
10367 return;
10368 } else if (copy_action == GDK_ACTION_COPY &&
10369 caja_is_engrampa_installed () &&
10370 target_file != NULL((void*)0) &&
10371 caja_file_is_archive (target_file)) {
10372 char *command, *quoted_uri, *tmp;
10373 const GList *l;
10374 GdkScreen *screen;
10375
10376 /* Handle dropping onto a engrampa archiver file, instead of starting a move/copy */
10377
10378 caja_file_unref (target_file);
10379
10380 quoted_uri = g_shell_quote (target_uri);
10381 command = g_strconcat ("engrampa -a ", quoted_uri, NULL((void*)0));
10382 g_free (quoted_uri);
10383
10384 for (l = item_uris; l != NULL((void*)0); l = l->next) {
10385 quoted_uri = g_shell_quote ((char *) l->data);
10386
10387 tmp = g_strconcat (command, " ", quoted_uri, NULL((void*)0));
10388 g_free (command);
10389 command = tmp;
10390
10391 g_free (quoted_uri);
10392 }
10393
10394 screen = gtk_widget_get_screen (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
10395 if (screen == NULL((void*)0)) {
10396 screen = gdk_screen_get_default ();
10397 }
10398
10399 mate_gdk_spawn_command_line_on_screen(screen, command, NULL((void*)0));
10400 g_free (command);
10401
10402 return;
10403 }
10404 caja_file_unref (target_file);
10405
10406 caja_file_operations_copy_move
10407 (item_uris, relative_item_points,
10408 target_uri, copy_action, GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))),
10409 copy_move_done_callback, pre_copy_move (view));
10410}
10411
10412gboolean
10413fm_directory_view_can_accept_item (CajaFile *target_item,
10414 const char *item_uri,
10415 FMDirectoryView *view)
10416{
10417 g_return_val_if_fail (CAJA_IS_FILE (target_item), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_329
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_item)); GType __t = (caja_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_329
= 1; else _g_boolean_var_329 = 0; _g_boolean_var_329; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (target_item)"); return ((
0)); } } while (0)
;
10418 g_return_val_if_fail (item_uri != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_330
; if (item_uri != ((void*)0)) _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__)), "item_uri != NULL"
); return ((0)); } } while (0)
;
10419 g_return_val_if_fail (FM_IS_DIRECTORY_VIEW (view), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_331
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_331
= 1; else _g_boolean_var_331 = 0; _g_boolean_var_331; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return (
(0)); } } while (0)
;
10420
10421 return caja_drag_can_accept_item (target_item, item_uri);
10422}
10423
10424static void
10425fm_directory_view_trash_state_changed_callback (CajaTrashMonitor *trash_monitor,
10426 gboolean state, gpointer callback_data)
10427{
10428 FMDirectoryView *view;
10429
10430 view = (FMDirectoryView *) callback_data;
10431 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_332
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_332
= 1; else _g_boolean_var_332 = 0; _g_boolean_var_332; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 10431, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
10432
10433 schedule_update_menus (view);
10434}
10435
10436void
10437fm_directory_view_start_batching_selection_changes (FMDirectoryView *view)
10438{
10439 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_333
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_333
= 1; else _g_boolean_var_333 = 0; _g_boolean_var_333; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
10440
10441 ++view->details->batching_selection_level;
10442 view->details->selection_changed_while_batched = FALSE(0);
10443}
10444
10445void
10446fm_directory_view_stop_batching_selection_changes (FMDirectoryView *view)
10447{
10448 g_return_if_fail (FM_IS_DIRECTORY_VIEW (view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_334
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_334
= 1; else _g_boolean_var_334 = 0; _g_boolean_var_334; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"); return; }
} while (0)
;
10449 g_return_if_fail (view->details->batching_selection_level > 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_335
; if (view->details->batching_selection_level > 0) _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__)), "view->details->batching_selection_level > 0"
); return; } } while (0)
;
10450
10451 if (--view->details->batching_selection_level == 0) {
10452 if (view->details->selection_changed_while_batched) {
10453 fm_directory_view_notify_selection_changed (view);
10454 }
10455 }
10456}
10457
10458static void
10459revert_slashes (char *string)
10460{
10461 while (*string != 0) {
10462 if (*string == '/') {
10463 *string = '\\';
10464 }
10465 string++;
10466 }
10467}
10468
10469
10470static GdkDragAction
10471ask_link_action (FMDirectoryView *view)
10472{
10473 int button_pressed;
10474 GdkDragAction result;
10475 GtkWindow *parent_window;
10476 GtkWidget *dialog;
10477
10478 parent_window = NULL((void*)0);
10479
10480 /* Don't use desktop window as parent, since that means
10481 we show up an all desktops etc */
10482 if (! FM_IS_DESKTOP_ICON_VIEW (view)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view)); GType __t = (fm_desktop_icon_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; }))))
) {
10483 parent_window = GTK_WINDOW (fm_directory_view_get_containing_window (view))((((GtkWindow*) (void *) ((fm_directory_view_get_containing_window
(view))))))
;
10484 }
10485
10486 dialog = gtk_message_dialog_new (parent_window,
10487 GTK_DIALOG_DESTROY_WITH_PARENT,
10488 GTK_MESSAGE_QUESTION,
10489 GTK_BUTTONS_NONE,
10490 _("Download location?")dcgettext (((void*)0), "Download location?", 5));
10491
10492 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
10493 _("You can download it or make a link to it.")dcgettext (((void*)0), "You can download it or make a link to it."
, 5)
);
10494
10495 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
10496 _("Make a _Link")dcgettext (((void*)0), "Make a _Link", 5), 0);
10497
10498 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
10499 _("_Cancel")dcgettext (((void*)0), "_Cancel", 5),
10500 "process-stop", 1);
10501
10502 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
10503 _("_Download")dcgettext (((void*)0), "_Download", 5), 2);
10504
10505 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), ""); /* as per HIG */
10506 gtk_window_set_focus_on_map (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
10507 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), 2);
10508
10509 gtk_window_present (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))));
10510
10511 button_pressed = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
10512
10513 gtk_widget_destroy (dialog);
10514
10515 switch (button_pressed) {
10516 case 0:
10517 result = GDK_ACTION_LINK;
10518 break;
10519 case 1:
10520 case GTK_RESPONSE_DELETE_EVENT:
10521 result = 0;
10522 break;
10523 case 2:
10524 result = GDK_ACTION_COPY;
10525 break;
10526 default:
10527 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 10527, ((const char*) (__func__)), ((void*)0)); } while (0)
;
10528 result = 0;
10529 }
10530
10531 return result;
10532}
10533
10534typedef struct {
10535 FMDirectoryView *view;
10536 GCancellable *cancellable;
10537 char *encoded_url;
10538 char *target_uri;
10539 int x;
10540 int y;
10541 guint timeout;
10542} NetscapeUrlDropAsk;
10543
10544static void
10545handle_netscape_url_drop_ask_cb (GObject *source_object,
10546 GAsyncResult *res,
10547 gpointer user_data)
10548{
10549 NetscapeUrlDropAsk *data;
10550 GdkDragAction action;
10551 GFileInfo *info;
10552 GFile *f;
10553 const char *mime_type;
10554
10555 data = user_data;
10556 f = G_FILE (source_object)((((GFile*) (void *) ((source_object)))));
10557
10558 info = g_file_query_info_finish (f, res, NULL((void*)0));
10559 mime_type = NULL((void*)0);
10560
10561 if (info) {
10562 mime_type = g_file_info_get_content_type (info);
10563 }
10564
10565 if (mime_type != NULL((void*)0) &&
10566 (g_content_type_equals (mime_type, "text/html") ||
10567 g_content_type_equals (mime_type, "text/xml") ||
10568 g_content_type_equals (mime_type, "application/xhtml+xml"))) {
10569 action = GDK_ACTION_LINK;
10570 } else if (mime_type != NULL((void*)0) &&
10571 g_content_type_equals (mime_type, "text/plain")) {
10572 action = ask_link_action (data->view);
10573 } else {
10574 action = GDK_ACTION_COPY;
10575 }
10576 if (info) {
10577 g_object_unref (info);
10578 }
10579
10580 if (action != 0) {
10581 fm_directory_view_handle_netscape_url_drop (data->view,
10582 data->encoded_url,
10583 data->target_uri,
10584 action,
10585 data->x, data->y);
10586 }
10587
10588 g_object_unref (data->view);
10589 g_object_unref (data->cancellable);
10590 if (data->timeout != 0) {
10591 g_source_remove (data->timeout);
10592 }
10593 g_free (data->encoded_url);
10594 g_free (data->target_uri);
10595 g_free (data);
10596}
10597
10598static gboolean
10599handle_netscape_url_drop_timeout (gpointer user_data)
10600{
10601 NetscapeUrlDropAsk *data;
10602
10603 data = user_data;
10604
10605 g_cancellable_cancel (data->cancellable);
10606 data->timeout = 0;
10607
10608 return FALSE(0);
10609}
10610
10611static inline void
10612fm_directory_view_widget_to_file_operation_position (FMDirectoryView *view,
10613 GdkPoint *position)
10614{
10615 EEL_CALL_METHOD (FM_DIRECTORY_VIEW_CLASS, view,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->widget_to_file_operation_position
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->widget_to_file_operation_position) (view, position)
; } } while (0)
10616 widget_to_file_operation_position,do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->widget_to_file_operation_position
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->widget_to_file_operation_position) (view, position)
; } } while (0)
10617 (view, position))do { if (((((FMDirectoryViewClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((view)))->g_class)))))))))->widget_to_file_operation_position
!= ((void*)0)) { (* ((((FMDirectoryViewClass*) (void *) ((((
((GObjectClass*) (((GTypeInstance*) ((view)))->g_class))))
)))))->widget_to_file_operation_position) (view, position)
; } } while (0)
;
10618}
10619
10620static void
10621fm_directory_view_widget_to_file_operation_position_xy (FMDirectoryView *view,
10622 int *x, int *y)
10623{
10624 GdkPoint position;
10625
10626 position.x = *x;
10627 position.y = *y;
10628 fm_directory_view_widget_to_file_operation_position (view, &position);
10629 *x = position.x;
10630 *y = position.y;
10631}
10632
10633void
10634fm_directory_view_handle_netscape_url_drop (FMDirectoryView *view,
10635 const char *encoded_url,
10636 const char *target_uri,
10637 GdkDragAction action,
10638 int x,
10639 int y)
10640{
10641 GdkPoint point;
10642 char *url, *title;
10643 char *container_uri;
10644 char **bits;
10645 GList *uri_list = NULL((void*)0);
10646 GFile *f;
10647
10648 if (encoded_url == NULL((void*)0)) {
10649 return;
10650 }
10651
10652 container_uri = NULL((void*)0);
10653 if (target_uri == NULL((void*)0)) {
10654 container_uri = fm_directory_view_get_backing_uri (view);
10655 g_assert (container_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_336
; if (container_uri != ((void*)0)) _g_boolean_var_336 = 1; else
_g_boolean_var_336 = 0; _g_boolean_var_336; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 10655, ((const char*) (
__func__)), "container_uri != NULL"); } while (0)
;
10656 }
10657
10658 f = g_file_new_for_uri (target_uri != NULL((void*)0) ? target_uri : container_uri);
10659 if (!g_file_is_native (f)) {
10660 eel_show_warning_dialog (_("Drag and drop is not supported.")dcgettext (((void*)0), "Drag and drop is not supported.", 5),
10661 _("Drag and drop is only supported on local file systems.")dcgettext (((void*)0), "Drag and drop is only supported on local file systems."
, 5)
,
10662 fm_directory_view_get_containing_window (view));
10663 g_object_unref (f);
10664 g_free (container_uri);
10665 return;
10666 }
10667 g_object_unref (f);
10668
10669 /* _NETSCAPE_URL_ works like this: $URL\n$TITLE */
10670 bits = g_strsplit (encoded_url, "\n", 0);
10671 switch (g_strv_length (bits)) {
10672 case 0:
10673 g_strfreev (bits);
10674 g_free (container_uri);
10675 return;
10676 case 1:
10677 url = bits[0];
10678 title = NULL((void*)0);
10679 break;
10680 default:
10681 url = bits[0];
10682 title = bits[1];
10683 }
10684
10685 if (action == GDK_ACTION_ASK) {
10686 NetscapeUrlDropAsk *data;
10687
10688 f = g_file_new_for_uri (url);
10689 data = g_new0 (NetscapeUrlDropAsk, 1)(NetscapeUrlDropAsk *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (NetscapeUrlDropAsk); 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; }))
;
10690 data->view = g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view));
10691 data->cancellable = g_cancellable_new ();
10692 data->encoded_url = g_strdup (encoded_url)g_strdup_inline (encoded_url);
10693 data->target_uri = g_strdup (target_uri)g_strdup_inline (target_uri);
10694 data->x = x;
10695 data->y = y;
10696 /* Ensure we wait at most 1 second for mimetype */
10697 data->timeout = g_timeout_add (1000,
10698 handle_netscape_url_drop_timeout,
10699 data);
10700 g_file_query_info_async (f,
10701 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type", 0,
10702 0, data->cancellable,
10703 handle_netscape_url_drop_ask_cb,
10704 data);
10705
10706 g_strfreev (bits);
10707 g_free (container_uri);
10708 return;
10709 }
10710
10711 fm_directory_view_widget_to_file_operation_position_xy (view, &x, &y);
10712
10713 /* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE
10714 * and we don't support combinations either. */
10715 if ((action != GDK_ACTION_DEFAULT) &&
10716 (action != GDK_ACTION_COPY) &&
10717 (action != GDK_ACTION_MOVE) &&
10718 (action != GDK_ACTION_LINK)) {
10719 eel_show_warning_dialog (_("Drag and drop is not supported.")dcgettext (((void*)0), "Drag and drop is not supported.", 5),
10720 _("An invalid drag type was used.")dcgettext (((void*)0), "An invalid drag type was used.", 5),
10721 fm_directory_view_get_containing_window (view));
10722 g_strfreev (bits);
10723 g_free (container_uri);
10724 return;
10725 }
10726
10727 if (action == GDK_ACTION_LINK) {
10728 char *link_name;
10729
10730 if (eel_str_is_empty (title)) {
10731 GFile *f;
10732
10733 f = g_file_new_for_uri (url);
10734 link_name = g_file_get_basename (f);
10735 g_object_unref (f);
10736 } else {
10737 link_name = g_strdup (title)g_strdup_inline (title);
10738 }
10739
10740 if (!eel_str_is_empty (link_name)) {
10741 GdkScreen *screen;
10742 int screen_num;
10743 char *link_display_name;
10744 GError *error = NULL((void*)0);
10745 gboolean success;
10746
10747 link_display_name = g_strdup_printf (_("Link to %s")dcgettext (((void*)0), "Link to %s", 5), link_name);
10748
10749 /* The filename can't contain slashes, strip em.
10750 (the basename of http://foo/ is http://foo/) */
10751 revert_slashes (link_name);
10752
10753 point.x = x;
10754 point.y = y;
10755
10756 screen = gtk_widget_get_screen (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
10757 screen_num = gdk_x11_screen_get_screen_number (screen);
10758
10759 success = caja_link_local_create (target_uri != NULL((void*)0) ? target_uri : container_uri,
10760 link_name,
10761 link_display_name,
10762 "mate-fs-bookmark",
10763 url,
10764 &point,
10765 screen_num,
10766 TRUE(!(0)),
10767 &error);
10768 if (!success) {
10769 if (error) {
10770 eel_show_error_dialog (_("Link Creation Failed")dcgettext (((void*)0), "Link Creation Failed", 5),
10771 error->message, NULL((void*)0));
10772 g_error_free (error);
10773 } else {
10774 gchar *error_message = g_strdup_printf (_("Cannot create the link to %s")dcgettext (((void*)0), "Cannot create the link to %s", 5), url);
10775 eel_show_error_dialog (_("Link Creation Failed")dcgettext (((void*)0), "Link Creation Failed", 5),
10776 error_message, NULL((void*)0));
10777 g_free (error_message);
10778 }
10779 }
10780
10781 g_free (link_display_name);
10782 }
10783 g_free (link_name);
10784 } else {
10785 GArray *points;
10786
10787 GdkPoint tmp_point = { 0, 0 };
10788
10789 /* pass in a 1-item array of icon positions, relative to x, y */
10790 points = g_array_new (FALSE(0), TRUE(!(0)), sizeof (GdkPoint));
10791 g_array_append_val (points, tmp_point)g_array_append_vals (points, &(tmp_point), 1);
10792
10793 uri_list = g_list_append (uri_list, url);
10794
10795 fm_directory_view_move_copy_items (uri_list, points,
10796 target_uri != NULL((void*)0) ? target_uri : container_uri,
10797 action, x, y, view);
10798
10799 g_list_free (uri_list);
10800 g_array_free (points, TRUE(!(0)));
10801 }
10802
10803 g_strfreev (bits);
10804 g_free (container_uri);
10805}
10806
10807void
10808fm_directory_view_handle_uri_list_drop (FMDirectoryView *view,
10809 const char *item_uris,
10810 const char *target_uri,
10811 GdkDragAction action,
10812 int x,
10813 int y)
10814{
10815 gchar **uri_list;
10816 GList *real_uri_list = NULL((void*)0);
10817 char *container_uri;
10818 int n_uris, i;
10819 GArray *points;
10820
10821 if (item_uris == NULL((void*)0)) {
10822 return;
10823 }
10824
10825 container_uri = NULL((void*)0);
10826 if (target_uri == NULL((void*)0)) {
10827 container_uri = fm_directory_view_get_backing_uri (view);
10828 g_assert (container_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_337
; if (container_uri != ((void*)0)) _g_boolean_var_337 = 1; else
_g_boolean_var_337 = 0; _g_boolean_var_337; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 10828, ((const char*) (
__func__)), "container_uri != NULL"); } while (0)
;
10829 }
10830
10831 if (action == GDK_ACTION_ASK) {
10832 action = caja_drag_drop_action_ask
10833 (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))),
10834 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
10835 if (action == 0) {
10836 g_free (container_uri);
10837 return;
10838 }
10839 }
10840
10841 /* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE
10842 * and we don't support combinations either. */
10843 if ((action != GDK_ACTION_DEFAULT) &&
10844 (action != GDK_ACTION_COPY) &&
10845 (action != GDK_ACTION_MOVE) &&
10846 (action != GDK_ACTION_LINK)) {
10847 eel_show_warning_dialog (_("Drag and drop is not supported.")dcgettext (((void*)0), "Drag and drop is not supported.", 5),
10848 _("An invalid drag type was used.")dcgettext (((void*)0), "An invalid drag type was used.", 5),
10849 fm_directory_view_get_containing_window (view));
10850 g_free (container_uri);
10851 return;
10852 }
10853
10854 n_uris = 0;
10855 uri_list = g_uri_list_extract_uris (item_uris);
10856 for (i = 0; uri_list[i] != NULL((void*)0); i++) {
10857 real_uri_list = g_list_append (real_uri_list, uri_list[i]);
10858 n_uris++;
10859 }
10860 g_free (uri_list);
10861
10862 /* do nothing if no real uris are left */
10863 if (n_uris == 0) {
10864 g_free (container_uri);
10865 return;
10866 }
10867
10868 if (n_uris == 1) {
10869 GdkPoint tmp_point = { 0, 0 };
10870
10871 /* pass in a 1-item array of icon positions, relative to x, y */
10872 points = g_array_new (FALSE(0), TRUE(!(0)), sizeof (GdkPoint));
10873 g_array_append_val (points, tmp_point)g_array_append_vals (points, &(tmp_point), 1);
10874 } else {
10875 points = NULL((void*)0);
10876 }
10877
10878 fm_directory_view_widget_to_file_operation_position_xy (view, &x, &y);
10879
10880 fm_directory_view_move_copy_items (real_uri_list, points,
10881 target_uri != NULL((void*)0) ? target_uri : container_uri,
10882 action, x, y, view);
10883
10884 g_list_free_full (real_uri_list, g_free);
10885
10886 if (points != NULL((void*)0))
10887 g_array_free (points, TRUE(!(0)));
10888
10889 g_free (container_uri);
10890}
10891
10892void
10893fm_directory_view_handle_text_drop (FMDirectoryView *view,
10894 const char *text,
10895 const char *target_uri,
10896 GdkDragAction action,
10897 int x,
10898 int y)
10899{
10900 int length;
10901 char *container_uri;
10902 GdkPoint pos;
10903
10904 if (text == NULL((void*)0)) {
10905 return;
10906 }
10907
10908 g_return_if_fail (action == GDK_ACTION_COPY)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_338
; if (action == GDK_ACTION_COPY) _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__
)), "action == GDK_ACTION_COPY"); return; } } while (0)
;
10909
10910 container_uri = NULL((void*)0);
10911 if (target_uri == NULL((void*)0)) {
10912 container_uri = fm_directory_view_get_backing_uri (view);
10913 g_assert (container_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_339
; if (container_uri != ((void*)0)) _g_boolean_var_339 = 1; else
_g_boolean_var_339 = 0; _g_boolean_var_339; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 10913, ((const char*) (
__func__)), "container_uri != NULL"); } while (0)
;
10914 }
10915
10916 length = strlen (text);
10917
10918 pos.x = x;
10919 pos.y = y;
10920 fm_directory_view_widget_to_file_operation_position (view, &pos);
10921
10922 fm_directory_view_new_file_with_initial_contents (
10923 view, target_uri != NULL((void*)0) ? target_uri : container_uri,
10924 /* Translators: This is the filename used for when you dnd text to a directory */
10925 _("dropped text.txt")dcgettext (((void*)0), "dropped text.txt", 5),
10926 text, length, &pos);
10927
10928 g_free (container_uri);
10929}
10930
10931void
10932fm_directory_view_handle_raw_drop (FMDirectoryView *view,
10933 const char *raw_data,
10934 int length,
10935 const char *target_uri,
10936 const char *direct_save_uri,
10937 GdkDragAction action,
10938 int x,
10939 int y)
10940{
10941 char *container_uri, *filename;
10942 GdkPoint pos;
10943
10944 if (raw_data == NULL((void*)0)) {
10945 return;
10946 }
10947
10948 g_return_if_fail (action == GDK_ACTION_COPY)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_340
; if (action == GDK_ACTION_COPY) _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__
)), "action == GDK_ACTION_COPY"); return; } } while (0)
;
10949
10950 container_uri = NULL((void*)0);
10951 if (target_uri == NULL((void*)0)) {
10952 container_uri = fm_directory_view_get_backing_uri (view);
10953 g_assert (container_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_341
; if (container_uri != ((void*)0)) _g_boolean_var_341 = 1; else
_g_boolean_var_341 = 0; _g_boolean_var_341; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 10953, ((const char*) (
__func__)), "container_uri != NULL"); } while (0)
;
10954 }
10955
10956 pos.x = x;
10957 pos.y = y;
10958 fm_directory_view_widget_to_file_operation_position (view, &pos);
10959
10960 filename = NULL((void*)0);
10961 if (direct_save_uri != NULL((void*)0)) {
10962 GFile *direct_save_full;
10963
10964 direct_save_full = g_file_new_for_uri (direct_save_uri);
10965 filename = g_file_get_basename (direct_save_full);
10966 }
10967 if (filename == NULL((void*)0)) {
10968 /* Translators: This is the filename used for when you dnd raw
10969 * data to a directory, if the source didn't supply a name.
10970 */
10971 filename = _("dropped data")dcgettext (((void*)0), "dropped data", 5);
10972 }
10973
10974 fm_directory_view_new_file_with_initial_contents (
10975 view, target_uri != NULL((void*)0) ? target_uri : container_uri,
10976 filename, raw_data, length, &pos);
10977
10978 g_free (container_uri);
10979}
10980
10981gboolean
10982fm_directory_view_get_active (FMDirectoryView *view)
10983{
10984 g_assert (FM_IS_DIRECTORY_VIEW (view))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_342
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((view)); GType __t = (fm_directory_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_342
= 1; else _g_boolean_var_342 = 0; _g_boolean_var_342; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 10984, ((const char*) (__func__)), "FM_IS_DIRECTORY_VIEW (view)"
); } while (0)
;
10985 return view->details->active;
10986}
10987
10988static GArray *
10989real_get_selected_icon_locations (FMDirectoryView *view)
10990{
10991 /* By default, just return an empty list. */
10992 return g_array_new (FALSE(0), TRUE(!(0)), sizeof (GdkPoint));
10993}
10994
10995static void
10996fm_directory_view_set_property (GObject *object,
10997 guint prop_id,
10998 const GValue *value,
10999 GParamSpec *pspec)
11000{
11001 FMDirectoryView *directory_view;
11002 CajaWindowSlotInfo *slot;
11003 CajaWindowInfo *window;
11004
11005 directory_view = FM_DIRECTORY_VIEW (object)((((FMDirectoryView*) (void *) ((object)))));
11006
11007 switch (prop_id) {
11008 case PROP_WINDOW_SLOT:
11009 g_assert (directory_view->details->slot == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_343
; if (directory_view->details->slot == ((void*)0)) _g_boolean_var_343
= 1; else _g_boolean_var_343 = 0; _g_boolean_var_343; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 11009, ((const char*) (__func__)), "directory_view->details->slot == NULL"
); } while (0)
;
11010
11011 slot = CAJA_WINDOW_SLOT_INFO (g_value_get_object (value))((((CajaWindowSlotInfo*) (void *) ((g_value_get_object (value
))))))
;
11012 window = caja_window_slot_info_get_window (slot);
11013
11014 directory_view->details->slot = slot;
11015 directory_view->details->window = window;
11016
11017 g_signal_connect_object (directory_view->details->slot,
11018 "active", G_CALLBACK (slot_active)((GCallback) (slot_active)),
11019 directory_view, 0);
11020 g_signal_connect_object (directory_view->details->slot,
11021 "inactive", G_CALLBACK (slot_inactive)((GCallback) (slot_inactive)),
11022 directory_view, 0);
11023
11024 g_signal_connect_object (directory_view->details->window,
11025 "hidden-files-mode-changed", G_CALLBACK (hidden_files_mode_changed)((GCallback) (hidden_files_mode_changed)),
11026 directory_view, 0);
11027 fm_directory_view_init_show_hidden_files (directory_view);
11028
11029 g_signal_connect_object (directory_view->details->window,
11030 "backup-files-mode-changed", G_CALLBACK (backup_files_mode_changed)((GCallback) (backup_files_mode_changed)),
11031 directory_view, 0);
11032 fm_directory_view_init_show_backup_files (directory_view);
11033
11034 break;
11035 default:
11036 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'"
, "fm-directory-view.c", 11036, ("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)
;
11037 break;
11038 }
11039}
11040
11041
11042gboolean
11043fm_directory_view_handle_scroll_event (FMDirectoryView *directory_view,
11044 GdkEventScroll *event)
11045{
11046 static gdouble total_delta_y = 0;
11047 gdouble delta_x, delta_y;
11048
11049 if (event->state & GDK_CONTROL_MASK) {
11050 switch (event->direction) {
11051 case GDK_SCROLL_UP:
11052 /* Zoom In */
11053 fm_directory_view_bump_zoom_level (directory_view, 1);
11054 return TRUE(!(0));
11055
11056 case GDK_SCROLL_DOWN:
11057 /* Zoom Out */
11058 fm_directory_view_bump_zoom_level (directory_view, -1);
11059 return TRUE(!(0));
11060
11061 case GDK_SCROLL_SMOOTH:
11062 gdk_event_get_scroll_deltas ((const GdkEvent *) event,
11063 &delta_x, &delta_y);
11064
11065 /* try to emulate a normal scrolling event by summing deltas */
11066 total_delta_y += delta_y;
11067
11068 if (total_delta_y >= 1) {
11069 total_delta_y = 0;
11070 /* emulate scroll down */
11071 fm_directory_view_bump_zoom_level (directory_view, -1);
11072 return TRUE(!(0));
11073 } else if (total_delta_y <= - 1) {
11074 total_delta_y = 0;
11075 /* emulate scroll up */
11076 fm_directory_view_bump_zoom_level (directory_view, 1);
11077 return TRUE(!(0));
11078 } else {
11079 /* eat event */
11080 return TRUE(!(0));
11081 }
11082
11083 case GDK_SCROLL_LEFT:
11084 case GDK_SCROLL_RIGHT:
11085 break;
11086
11087 default:
11088 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 11088, ((const char*) (__func__)), ((void*)0)); } while (0)
;
11089 }
11090 }
11091
11092 return FALSE(0);
11093}
11094
11095/* handle Shift+Scroll, which will cause a zoom-in/out */
11096static gboolean
11097fm_directory_view_scroll_event (GtkWidget *widget,
11098 GdkEventScroll *event)
11099{
11100 FMDirectoryView *directory_view;
11101
11102 directory_view = FM_DIRECTORY_VIEW (widget)((((FMDirectoryView*) (void *) ((widget)))));
11103 if (fm_directory_view_handle_scroll_event (directory_view, event)) {
11104 return TRUE(!(0));
11105 }
11106
11107 return GTK_WIDGET_CLASS (parent_class)((((GtkWidgetClass*) (void *) ((parent_class)))))->scroll_event (widget, event);
11108}
11109
11110
11111static void
11112fm_directory_view_parent_set (GtkWidget *widget,
11113 GtkWidget *old_parent)
11114{
11115 FMDirectoryView *view;
11116 GtkWidget *parent;
11117
11118 view = FM_DIRECTORY_VIEW (widget)((((FMDirectoryView*) (void *) ((widget)))));
11119
11120 parent = gtk_widget_get_parent (widget);
11121 g_assert (parent == NULL || old_parent == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_344
; if (parent == ((void*)0) || old_parent == ((void*)0)) _g_boolean_var_344
= 1; else _g_boolean_var_344 = 0; _g_boolean_var_344; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-directory-view.c"
, 11121, ((const char*) (__func__)), "parent == NULL || old_parent == NULL"
); } while (0)
;
11122
11123 if (GTK_WIDGET_CLASS (parent_class)((((GtkWidgetClass*) (void *) ((parent_class)))))->parent_set != NULL((void*)0)) {
11124 GTK_WIDGET_CLASS (parent_class)((((GtkWidgetClass*) (void *) ((parent_class)))))->parent_set (widget, old_parent);
11125 }
11126
11127 if (parent != NULL((void*)0)) {
11128 g_assert (old_parent == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_345
; if (old_parent == ((void*)0)) _g_boolean_var_345 = 1; else _g_boolean_var_345
= 0; _g_boolean_var_345; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-directory-view.c", 11128, ((const char*) (
__func__)), "old_parent == NULL"); } while (0)
;
11129
11130 if (view->details->slot ==
11131 caja_window_info_get_active_slot (view->details->window)) {
11132 view->details->active = TRUE(!(0));
11133
11134 fm_directory_view_merge_menus (view);
11135 schedule_update_menus (view);
11136 }
11137 } else {
11138 fm_directory_view_unmerge_menus (view);
11139 remove_update_menus_timeout_callback (view);
11140 }
11141}
11142
11143static void
11144fm_directory_view_class_init (FMDirectoryViewClass *klass)
11145{
11146 GtkWidgetClass *widget_class;
11147 GtkScrolledWindowClass *scrolled_window_class;
11148 GtkBindingSet *binding_set;
11149
11150 widget_class = GTK_WIDGET_CLASS (klass)((((GtkWidgetClass*) (void *) ((klass)))));
11151 scrolled_window_class = GTK_SCROLLED_WINDOW_CLASS (klass)((((GtkScrolledWindowClass*) (void *) ((klass)))));
11152
11153 G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))))->set_property = fm_directory_view_set_property;
11154 G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))))->finalize = fm_directory_view_finalize;
11155
11156 widget_class->destroy = fm_directory_view_destroy;
11157
11158 widget_class->scroll_event = fm_directory_view_scroll_event;
11159 widget_class->parent_set = fm_directory_view_parent_set;
11160
11161 /* Get rid of the strange 3-pixel gap that GtkScrolledWindow
11162 * uses by default. It does us no good.
11163 */
11164 scrolled_window_class->scrollbar_spacing = 0;
11165
11166 signals[ADD_FILE] =
11167 g_signal_new ("add_file",
11168 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11169 G_SIGNAL_RUN_LAST,
11170 G_STRUCT_OFFSET (FMDirectoryViewClass, add_file)((glong) __builtin_offsetof(FMDirectoryViewClass, add_file)),
11171 NULL((void*)0), NULL((void*)0),
11172 fm_marshal_VOID__OBJECT_OBJECT,
11173 G_TYPE_NONE((GType) ((1) << (2))), 2, CAJA_TYPE_FILEcaja_file_get_type(), CAJA_TYPE_DIRECTORYcaja_directory_get_type());
11174 signals[BEGIN_FILE_CHANGES] =
11175 g_signal_new ("begin_file_changes",
11176 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11177 G_SIGNAL_RUN_LAST,
11178 G_STRUCT_OFFSET (FMDirectoryViewClass, begin_file_changes)((glong) __builtin_offsetof(FMDirectoryViewClass, begin_file_changes
))
,
11179 NULL((void*)0), NULL((void*)0),
11180 g_cclosure_marshal_VOID__VOID,
11181 G_TYPE_NONE((GType) ((1) << (2))), 0);
11182 signals[BEGIN_LOADING] =
11183 g_signal_new ("begin_loading",
11184 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11185 G_SIGNAL_RUN_LAST,
11186 G_STRUCT_OFFSET (FMDirectoryViewClass, begin_loading)((glong) __builtin_offsetof(FMDirectoryViewClass, begin_loading
))
,
11187 NULL((void*)0), NULL((void*)0),
11188 g_cclosure_marshal_VOID__VOID,
11189 G_TYPE_NONE((GType) ((1) << (2))), 0);
11190 signals[CLEAR] =
11191 g_signal_new ("clear",
11192 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11193 G_SIGNAL_RUN_LAST,
11194 G_STRUCT_OFFSET (FMDirectoryViewClass, clear)((glong) __builtin_offsetof(FMDirectoryViewClass, clear)),
11195 NULL((void*)0), NULL((void*)0),
11196 g_cclosure_marshal_VOID__VOID,
11197 G_TYPE_NONE((GType) ((1) << (2))), 0);
11198 signals[END_FILE_CHANGES] =
11199 g_signal_new ("end_file_changes",
11200 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11201 G_SIGNAL_RUN_LAST,
11202 G_STRUCT_OFFSET (FMDirectoryViewClass, end_file_changes)((glong) __builtin_offsetof(FMDirectoryViewClass, end_file_changes
))
,
11203 NULL((void*)0), NULL((void*)0),
11204 g_cclosure_marshal_VOID__VOID,
11205 G_TYPE_NONE((GType) ((1) << (2))), 0);
11206 signals[FLUSH_ADDED_FILES] =
11207 g_signal_new ("flush_added_files",
11208 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11209 G_SIGNAL_RUN_LAST,
11210 G_STRUCT_OFFSET (FMDirectoryViewClass, flush_added_files)((glong) __builtin_offsetof(FMDirectoryViewClass, flush_added_files
))
,
11211 NULL((void*)0), NULL((void*)0),
11212 g_cclosure_marshal_VOID__VOID,
11213 G_TYPE_NONE((GType) ((1) << (2))), 0);
11214 signals[END_LOADING] =
11215 g_signal_new ("end_loading",
11216 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11217 G_SIGNAL_RUN_LAST,
11218 G_STRUCT_OFFSET (FMDirectoryViewClass, end_loading)((glong) __builtin_offsetof(FMDirectoryViewClass, end_loading
))
,
11219 NULL((void*)0), NULL((void*)0),
11220 g_cclosure_marshal_VOID__BOOLEAN,
11221 G_TYPE_NONE((GType) ((1) << (2))), 1, G_TYPE_BOOLEAN((GType) ((5) << (2))));
11222 signals[FILE_CHANGED] =
11223 g_signal_new ("file_changed",
11224 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11225 G_SIGNAL_RUN_LAST,
11226 G_STRUCT_OFFSET (FMDirectoryViewClass, file_changed)((glong) __builtin_offsetof(FMDirectoryViewClass, file_changed
))
,
11227 NULL((void*)0), NULL((void*)0),
11228 fm_marshal_VOID__OBJECT_OBJECT,
11229 G_TYPE_NONE((GType) ((1) << (2))), 2, CAJA_TYPE_FILEcaja_file_get_type(), CAJA_TYPE_DIRECTORYcaja_directory_get_type());
11230 signals[LOAD_ERROR] =
11231 g_signal_new ("load_error",
11232 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11233 G_SIGNAL_RUN_LAST,
11234 G_STRUCT_OFFSET (FMDirectoryViewClass, load_error)((glong) __builtin_offsetof(FMDirectoryViewClass, load_error)
)
,
11235 NULL((void*)0), NULL((void*)0),
11236 g_cclosure_marshal_VOID__POINTER,
11237 G_TYPE_NONE((GType) ((1) << (2))), 1, G_TYPE_POINTER((GType) ((17) << (2))));
11238 signals[REMOVE_FILE] =
11239 g_signal_new ("remove_file",
11240 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11241 G_SIGNAL_RUN_LAST,
11242 G_STRUCT_OFFSET (FMDirectoryViewClass, remove_file)((glong) __builtin_offsetof(FMDirectoryViewClass, remove_file
))
,
11243 NULL((void*)0), NULL((void*)0),
11244 fm_marshal_VOID__OBJECT_OBJECT,
11245 G_TYPE_NONE((GType) ((1) << (2))), 2, CAJA_TYPE_FILEcaja_file_get_type(), CAJA_TYPE_DIRECTORYcaja_directory_get_type());
11246
11247 klass->accepts_dragged_files = real_accepts_dragged_files;
11248 klass->file_still_belongs = real_file_still_belongs;
11249 klass->get_emblem_names_to_exclude = real_get_emblem_names_to_exclude;
11250 klass->get_selected_icon_locations = real_get_selected_icon_locations;
11251 klass->is_read_only = real_is_read_only;
11252 klass->load_error = real_load_error;
11253 klass->can_rename_file = can_rename_file;
11254 klass->start_renaming_file = start_renaming_file;
11255 klass->supports_creating_files = real_supports_creating_files;
11256 klass->supports_properties = real_supports_properties;
11257 klass->supports_zooming = real_supports_zooming;
11258 klass->using_manual_layout = real_using_manual_layout;
11259 klass->merge_menus = real_merge_menus;
11260 klass->unmerge_menus = real_unmerge_menus;
11261 klass->update_menus = real_update_menus;
11262 klass->set_is_active = real_set_is_active;
11263 /* Function pointers that subclasses must override */
11264 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, add_file)* (void (**)(void)) & (klass)->add_file = fm_directory_view_unimplemented_add_file;
11265 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, bump_zoom_level)* (void (**)(void)) & (klass)->bump_zoom_level = fm_directory_view_unimplemented_bump_zoom_level;
11266 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, can_zoom_in)* (void (**)(void)) & (klass)->can_zoom_in = fm_directory_view_unimplemented_can_zoom_in;
11267 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, can_zoom_out)* (void (**)(void)) & (klass)->can_zoom_out = fm_directory_view_unimplemented_can_zoom_out;
11268 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, clear)* (void (**)(void)) & (klass)->clear = fm_directory_view_unimplemented_clear;
11269 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, file_changed)* (void (**)(void)) & (klass)->file_changed = fm_directory_view_unimplemented_file_changed;
11270 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_background_widget)* (void (**)(void)) & (klass)->get_background_widget =
fm_directory_view_unimplemented_get_background_widget
;
11271 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_selection)* (void (**)(void)) & (klass)->get_selection = fm_directory_view_unimplemented_get_selection;
11272 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_selection_for_file_transfer)* (void (**)(void)) & (klass)->get_selection_for_file_transfer
= fm_directory_view_unimplemented_get_selection_for_file_transfer
;
11273 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_item_count)* (void (**)(void)) & (klass)->get_item_count = fm_directory_view_unimplemented_get_item_count;
11274 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, is_empty)* (void (**)(void)) & (klass)->is_empty = fm_directory_view_unimplemented_is_empty;
11275 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, reset_to_defaults)* (void (**)(void)) & (klass)->reset_to_defaults = fm_directory_view_unimplemented_reset_to_defaults;
11276 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, restore_default_zoom_level)* (void (**)(void)) & (klass)->restore_default_zoom_level
= fm_directory_view_unimplemented_restore_default_zoom_level
;
11277 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, select_all)* (void (**)(void)) & (klass)->select_all = fm_directory_view_unimplemented_select_all;
11278 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, set_selection)* (void (**)(void)) & (klass)->set_selection = fm_directory_view_unimplemented_set_selection;
11279 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, invert_selection)* (void (**)(void)) & (klass)->invert_selection = fm_directory_view_unimplemented_invert_selection;
11280 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, zoom_to_level)* (void (**)(void)) & (klass)->zoom_to_level = fm_directory_view_unimplemented_zoom_to_level;
11281 EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass, fm_directory_view, get_zoom_level)* (void (**)(void)) & (klass)->get_zoom_level = fm_directory_view_unimplemented_get_zoom_level;
11282
11283 copied_files_atom = gdk_atom_intern ("x-special/mate-copied-files", FALSE(0));
11284
11285 g_object_class_install_property (G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass))))),
11286 PROP_WINDOW_SLOT,
11287 g_param_spec_object ("window-slot",
11288 "Window Slot",
11289 "The parent window slot reference",
11290 CAJA_TYPE_WINDOW_SLOT_INFO(caja_window_slot_info_get_type ()),
11291 G_PARAM_WRITABLE |
11292 G_PARAM_CONSTRUCT_ONLY));
11293
11294 signals[TRASH] =
11295 g_signal_new ("trash",
11296 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11297 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
11298 G_STRUCT_OFFSET (FMDirectoryViewClass, trash)((glong) __builtin_offsetof(FMDirectoryViewClass, trash)),
11299 g_signal_accumulator_true_handled, NULL((void*)0),
11300 fm_marshal_BOOLEAN__VOID,
11301 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
11302 signals[DELETE] =
11303 g_signal_new ("delete",
11304 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
11305 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
11306 G_STRUCT_OFFSET (FMDirectoryViewClass, delete)((glong) __builtin_offsetof(FMDirectoryViewClass, delete)),
11307 g_signal_accumulator_true_handled, NULL((void*)0),
11308 fm_marshal_BOOLEAN__VOID,
11309 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
11310
11311 binding_set = gtk_binding_set_by_class (klass);
11312 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete0xffff, 0,
11313 "trash", 0);
11314 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete0xff9f, 0,
11315 "trash", 0);
11316 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete0xffff, GDK_SHIFT_MASK,
11317 "delete", 0);
11318 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete0xff9f, GDK_SHIFT_MASK,
11319 "delete", 0);
11320
11321 klass->trash = real_trash;
11322 klass->delete = real_delete;
11323}
11324
11325static void
11326undo_redo_menu_update_callback (CajaUndoStackManager* manager, gpointer arg, gpointer data)
11327{
11328 FMDirectoryView *view;
11329 view = FM_DIRECTORY_VIEW (data)((((FMDirectoryView*) (void *) ((data)))));
11330
11331 CajaUndoStackMenuData* menudata = (CajaUndoStackMenuData*) arg;
11332
11333 g_free(view->details->undo_action_label);
11334 g_free(view->details->undo_action_description);
11335 g_free(view->details->redo_action_label);
11336 g_free(view->details->redo_action_description);
11337
11338 view->details->undo_active = menudata->undo_label ? TRUE(!(0)) : FALSE(0);
11339 view->details->redo_active = menudata->redo_label ? TRUE(!(0)) : FALSE(0);
11340
11341 view->details->undo_action_label = g_strdup (menudata->undo_label)g_strdup_inline (menudata->undo_label);
11342 view->details->undo_action_description = g_strdup (menudata->undo_description)g_strdup_inline (menudata->undo_description);
11343 view->details->redo_action_label = g_strdup (menudata->redo_label)g_strdup_inline (menudata->redo_label);
11344 view->details->redo_action_description = g_strdup (menudata->redo_description)g_strdup_inline (menudata->redo_description);
11345
11346 schedule_update_menus (view);
11347}
11348
11349static void
11350undo_update_menu (FMDirectoryView *view)
11351{
11352 GtkAction *action;
11353 gboolean available = FALSE(0);
11354 gchar* label;
11355 gchar* tooltip;
11356
11357 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
11358 /* Update undo entry */
11359 action = gtk_action_group_get_action (view->details->dir_action_group,
11360 FM_ACTION_UNDO"Undo");
11361 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
11362 available = view->details->undo_active;
11363 if (available) {
11364 label = view->details->undo_action_label;
11365 tooltip = view->details->undo_action_description;
11366 } else {
11367 /* Reset to default info */
11368 label = _("Undo")dcgettext (((void*)0), "Undo", 5);
11369 tooltip = _("Undo the last action")dcgettext (((void*)0), "Undo the last action", 5);
11370 }
11371 g_object_set (action,
11372 "label", label,
11373 "tooltip", tooltip,
11374 NULL((void*)0));
11375 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
11376 gtk_action_set_sensitive (action, available);
11377
11378 /* Update redo entry */
11379 action = gtk_action_group_get_action (view->details->dir_action_group,
11380 FM_ACTION_REDO"Redo");
11381 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
11382 available = view->details->redo_active;
11383 if (available) {
11384 label = view->details->redo_action_label;
11385 tooltip = view->details->redo_action_description;
11386 } else {
11387 /* Reset to default info */
11388 label = _("Redo")dcgettext (((void*)0), "Redo", 5);
11389 tooltip = _("Redo the last undone action")dcgettext (((void*)0), "Redo the last undone action", 5);
11390 }
11391 g_object_set (action,
11392 "label", label,
11393 "tooltip", tooltip,
11394 NULL((void*)0));
11395 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
11396 gtk_action_set_sensitive (action, available);
11397 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
11398}
diff --git a/2024-07-29-023715-6438-1/report-4a2949.html b/2024-07-29-023715-6438-1/report-4a2949.html new file mode 100644 index 000000000..22f306e7c --- /dev/null +++ b/2024-07-29-023715-6438-1/report-4a2949.html @@ -0,0 +1,933 @@ + + + +caja-extensions.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-extensions.c
Warning:line 234, column 46
Access to field 'filename' results in a dereference of a null pointer (loaded from variable 'ext')
+ +

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 caja-extensions.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-extensions.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * caja-extension.c - extension management functions
3 *
4 * Copyright (C) 2012-2021 The MATE developers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * Author: Alexander van der Meij <alexandervdm@gliese.me>
22 */
23
24#include "caja-extensions.h"
25
26#include "caja-global-preferences.h"
27#include "caja-module.h"
28#include "caja-debug-log.h"
29
30#include <string.h>
31
32#define CAJA_EXTENSION_GROUP"Caja Extension" "Caja Extension"
33
34static GList *caja_extensions = NULL((void*)0);
35
36
37static Extension *
38extension_new (gchar *filename, gboolean state, gboolean python, GObject *module)
39{
40 GError *error = NULL((void*)0);
41 Extension *ext;
42 GKeyFile *extension_file;
43 gchar *extension_filename;
44
45 ext = g_new0 (Extension, 1)(Extension *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Extension); 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
; }))
;
46 ext->filename = filename;
47 ext->name = NULL((void*)0);
48 ext->description = NULL((void*)0);
49 ext->author = NULL((void*)0);
50 ext->copyright = NULL((void*)0);
51 ext->version = NULL((void*)0);
52 ext->website = NULL((void*)0);
53 ext->state = state;
54 ext->module = module;
55
56 extension_file = g_key_file_new ();
57 extension_filename = g_strdup_printf(CAJA_DATADIR"/usr/local/share/caja" "/extensions/%s.caja-extension", filename);
58 if (g_key_file_load_from_file (extension_file, extension_filename, G_KEY_FILE_NONE, &error))
59 {
60 ext->name = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Name", NULL((void*)0), NULL((void*)0));
61 ext->description = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Description", NULL((void*)0), NULL((void*)0));
62 ext->icon = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Icon", NULL((void*)0));
63 ext->author = g_key_file_get_string_list (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Author", NULL((void*)0), NULL((void*)0));
64 ext->copyright = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Copyright", NULL((void*)0), NULL((void*)0));
65 ext->version = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Version", NULL((void*)0));
66 ext->website = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Website", NULL((void*)0));
67 g_key_file_free (extension_file);
68 }
69 else
70 {
71 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER", "Error loading keys from file: %s\n", error->message);
72 g_error_free (error);
73 }
74 g_free (extension_filename);
75
76 if (python)
77 {
78 ext->name = g_strconcat("Python: ", filename, NULL((void*)0));
79 ext->description = "Python-caja extension";
80 }
81
82 return ext;
83}
84
85/* functions related to persistent configuration through gsettings: */
86
87static gboolean
88gsettings_key_has_value (const gchar *value)
89{
90 gchar **list;
91 gint i;
92
93 list = g_settings_get_strv (caja_extension_preferences,
94 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions");
95
96 if (list != NULL((void*)0))
97 {
98 for (i = 0; list[i]; i++)
99 {
100 if (g_ascii_strcasecmp (value, list[i]) == 0)
101 {
102 g_strfreev (list);
103 return TRUE(!(0));
104 }
105 }
106 }
107 g_strfreev (list);
108 return FALSE(0);
109}
110
111static gboolean
112gsettings_append_to_list (const char *value)
113{
114 gchar **current;
115 gchar **new;
116 gint size;
117 gboolean retval;
118
119 current = g_settings_get_strv (caja_extension_preferences,
120 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions");
121
122 for (size = 0; current[size] != NULL((void*)0); size++);
123
124 size += 1;
125 size += 1;
126
127 new = g_realloc_n (current, size, sizeof (gchar *));
128
129 new[size - 2] = g_strdup (value)g_strdup_inline (value);
130 new[size - 1] = NULL((void*)0);
131
132 retval = g_settings_set_strv (caja_extension_preferences,
133 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions",
134 (const gchar **) new);
135
136 g_strfreev (new);
137 return retval;
138}
139
140static gboolean
141gsettings_remove_from_list (const char *value)
142{
143 gchar **current;
144 GArray *array;
145 gint i;
146 gboolean retval;
147
148 current = g_settings_get_strv (caja_extension_preferences,
149 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions");
150
151 array = g_array_new (TRUE(!(0)), TRUE(!(0)), sizeof (gchar *));
152
153 for (i = 0; current[i] != NULL((void*)0); i++)
154 {
155 if (g_strcmp0 (current[i], value) != 0)
156 array = g_array_append_val (array, current[i])g_array_append_vals (array, &(current[i]), 1);
157 }
158
159 retval = g_settings_set_strv (caja_extension_preferences,
160 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions",
161 (const gchar **) array->data);
162
163 g_strfreev (current);
164 g_array_free (array, TRUE(!(0)));
165 return retval;
166}
167
168/* functions related to the extension management */
169
170static gboolean
171caja_extension_get_state (const gchar *extname)
172{
173 return !gsettings_key_has_value (extname);
174}
175
176GList *
177caja_extensions_get_for_type (GType type)
178{
179 GList *l;
180 GList *ret = NULL((void*)0);
181
182 for (l = caja_extensions; l != NULL((void*)0); l = l->next)
183 {
184 Extension *ext = l->data;
185 ext->state = caja_extension_get_state (ext->filename);
186 if (ext->state) // only load enabled extensions
187 {
188 if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (ext->module), type)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
((((GObject*) (void *) ((ext->module)))))); GType __t = (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; })))
)
189 {
190 g_object_ref (ext->module)((__typeof__ (ext->module)) (g_object_ref) (ext->module
))
;
191 ret = g_list_prepend (ret, ext->module);
192 }
193 }
194 }
195
196 return ret;
197}
198
199GList *
200caja_extensions_get_list (void)
201{
202 return caja_extensions;
203}
204
205void
206caja_extension_register (gchar *filename, GObject *module)
207{
208 gboolean ext_state = TRUE(!(0)); // new extensions are enabled by default.
209 gboolean ext_python = FALSE(0);
210 gchar *ext_filename;
211
212 ext_filename = g_strndup (filename, strlen(filename) - 3);
213 ext_state = caja_extension_get_state (ext_filename);
214
215 if (g_str_has_suffix (filename, ".py")(__builtin_constant_p (".py")? __extension__ ({ const char * const
__str = (filename); const char * const __suffix = (".py"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_13
; if (__str == ((void*)0) || __suffix == ((void*)0)) _g_boolean_var_13
= 1; else _g_boolean_var_13 = 0; _g_boolean_var_13; }), 0)) __result
= (g_str_has_suffix) (__str, __suffix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __suffix_len =
strlen (((__suffix) + !(__suffix))); if (__str_len >= __suffix_len
) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix
) + !(__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".py") )
) {
216 ext_python = TRUE(!(0));
217 }
218
219 Extension *ext = extension_new (ext_filename, ext_state, ext_python, module);
220 caja_extensions = g_list_append (caja_extensions, ext);
221}
222
223gboolean
224caja_extension_set_state (Extension *ext, gboolean new_state)
225{
226 if (ext)
1
Assuming 'ext' is null
2
Taking false branch
227 {
228 g_return_val_if_fail (ext->state != new_state, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (ext->state != new_state) _g_boolean_var_14 = 1; else
_g_boolean_var_14 = 0; _g_boolean_var_14; }), 1))) { } else {
g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "ext->state != new_state"); return ((0)); } } while (0
)
;
229 ext->state = new_state;
230 }
231
232 gboolean retval;
233 if (new_state) {
3
Assuming 'new_state' is not equal to 0
4
Taking true branch
234 retval = gsettings_remove_from_list (ext->filename);
5
Access to field 'filename' results in a dereference of a null pointer (loaded from variable 'ext')
235 }
236 else {
237 retval = gsettings_append_to_list (ext->filename);
238 }
239
240 g_return_val_if_fail (retval == TRUE, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if (retval == (!(0))) _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__)), "retval == TRUE")
; return ((0)); } } while (0)
;
241 return TRUE(!(0));
242}
243
diff --git a/2024-07-29-023715-6438-1/report-50b9d2.html b/2024-07-29-023715-6438-1/report-50b9d2.html new file mode 100644 index 000000000..2203b9610 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-50b9d2.html @@ -0,0 +1,2583 @@ + + + +caja-query-editor.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-query-editor.c
Warning:line 1158, column 5
Value stored to 'datetime' 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 caja-query-editor.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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-query-editor.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/*
3 * Copyright (C) 2005 Red Hat, Inc.
4 *
5 * Caja is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * Caja 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 GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; see the file COPYING. If not,
17 * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 * Author: Alexander Larsson <alexl@redhat.com>
21 *
22 */
23
24#include <config.h>
25#include <string.h>
26
27#include <glib/gi18n.h>
28#include <gio/gio.h>
29#include <gdk/gdkkeysyms.h>
30#include <gtk/gtk.h>
31
32#include <eel/eel-gtk-macros.h>
33#include <eel/eel-glib-extensions.h>
34#include <eel/eel-stock-dialogs.h>
35
36#include <libcaja-private/caja-global-preferences.h>
37
38#include "caja-query-editor.h"
39#include "caja-src-marshal.h"
40#include "caja-window-slot.h"
41
42enum
43{
44 DURATION_INVALID,
45 DURATION_ONE_HOUR,
46 DURATION_ONE_DAY,
47 DURATION_ONE_WEEK,
48 DURATION_ONE_MONTH,
49 DURATION_SIX_MONTHS,
50 DURATION_ONE_YEAR,
51};
52
53typedef enum
54{
55 CAJA_QUERY_EDITOR_ROW_LOCATION,
56 CAJA_QUERY_EDITOR_ROW_TYPE,
57 CAJA_QUERY_EDITOR_ROW_TAGS,
58 CAJA_QUERY_EDITOR_ROW_TIME_MODIFIED,
59 CAJA_QUERY_EDITOR_ROW_SIZE,
60 CAJA_QUERY_EDITOR_ROW_CONTAINED_TEXT,
61
62 CAJA_QUERY_EDITOR_ROW_LAST
63} CajaQueryEditorRowType;
64
65typedef struct
66{
67 CajaQueryEditorRowType type;
68 CajaQueryEditor *editor;
69 GtkWidget *hbox;
70 GtkWidget *combo;
71
72 GtkWidget *type_widget;
73
74 void *data;
75} CajaQueryEditorRow;
76
77
78typedef struct
79{
80 const char *name;
81 GtkWidget * (*create_widgets) (CajaQueryEditorRow *row);
82 void (*add_to_query) (CajaQueryEditorRow *row,
83 CajaQuery *query);
84 void (*free_data) (CajaQueryEditorRow *row);
85 void (*add_rows_from_query) (CajaQueryEditor *editor,
86 CajaQuery *query);
87} CajaQueryEditorRowOps;
88
89struct CajaQueryEditorDetails
90{
91 gboolean is_indexed;
92 GtkWidget *entry;
93 gboolean change_frozen;
94 guint typing_timeout_id;
95 gboolean is_visible;
96 GtkWidget *invisible_vbox;
97 GtkWidget *visible_vbox;
98
99 GList *rows;
100 char *last_set_query_text;
101
102 CajaSearchBar *bar;
103 CajaWindowSlot *slot;
104};
105
106enum
107{
108 CHANGED,
109 CANCEL,
110 LAST_SIGNAL
111};
112
113static guint signals[LAST_SIGNAL] = { 0 };
114
115static void caja_query_editor_class_init (CajaQueryEditorClass *class);
116static void caja_query_editor_init (CajaQueryEditor *editor);
117
118static void go_search_cb (GtkButton *clicked_button, CajaQueryEditor *editor);
119
120static void entry_activate_cb (GtkWidget *entry, CajaQueryEditor *editor);
121static void entry_changed_cb (GtkWidget *entry, CajaQueryEditor *editor);
122static void caja_query_editor_changed_force (CajaQueryEditor *editor,
123 gboolean force);
124static void caja_query_editor_changed (CajaQueryEditor *editor);
125static CajaQueryEditorRow * caja_query_editor_add_row (CajaQueryEditor *editor,
126 CajaQueryEditorRowType type);
127
128static GtkWidget *location_row_create_widgets (CajaQueryEditorRow *row);
129static void location_row_add_to_query (CajaQueryEditorRow *row,
130 CajaQuery *query);
131static void location_row_free_data (CajaQueryEditorRow *row);
132static void location_add_rows_from_query (CajaQueryEditor *editor,
133 CajaQuery *query);
134
135static GtkWidget *tags_row_create_widgets (CajaQueryEditorRow *row);
136static void tags_row_add_to_query (CajaQueryEditorRow *row,
137 CajaQuery *query);
138static void tags_row_free_data (CajaQueryEditorRow *row);
139static void tags_add_rows_from_query (CajaQueryEditor *editor,
140 CajaQuery *query);
141
142static GtkWidget *type_row_create_widgets (CajaQueryEditorRow *row);
143static void type_row_add_to_query (CajaQueryEditorRow *row,
144 CajaQuery *query);
145static void type_row_free_data (CajaQueryEditorRow *row);
146static void type_add_rows_from_query (CajaQueryEditor *editor,
147 CajaQuery *query);
148static GtkWidget *modtime_row_create_widgets(CajaQueryEditorRow *row);
149static void modtime_row_add_to_query(CajaQueryEditorRow *row,
150 CajaQuery *query);
151static void modtime_row_free_data(CajaQueryEditorRow *row);
152static void modtime_add_rows_from_query(CajaQueryEditor *editor,
153 CajaQuery *query);
154static GtkWidget *size_row_create_widgets(CajaQueryEditorRow *row);
155static void size_row_add_to_query(CajaQueryEditorRow *row,
156 CajaQuery *query);
157static void size_row_free_data(CajaQueryEditorRow *row);
158static void size_add_rows_from_query(CajaQueryEditor *editor,
159 CajaQuery *query);
160
161static GtkWidget *contained_text_row_create_widgets(CajaQueryEditorRow *row);
162static void contained_text_row_add_to_query(CajaQueryEditorRow *row,
163 CajaQuery *query);
164static void contained_text_row_free_data(CajaQueryEditorRow *row);
165static void contained_text_add_rows_from_query(CajaQueryEditor *editor,
166 CajaQuery *query);
167
168static CajaQueryEditorRowOps row_type[] =
169{
170 {
171 N_("Location")("Location"),
172 location_row_create_widgets,
173 location_row_add_to_query,
174 location_row_free_data,
175 location_add_rows_from_query
176 },
177 {
178 N_("File Type")("File Type"),
179 type_row_create_widgets,
180 type_row_add_to_query,
181 type_row_free_data,
182 type_add_rows_from_query
183 },
184 {
185 N_("Tags")("Tags"),
186 tags_row_create_widgets,
187 tags_row_add_to_query,
188 tags_row_free_data,
189 tags_add_rows_from_query
190 },
191 {
192 N_("Modification Time")("Modification Time"),
193 modtime_row_create_widgets,
194 modtime_row_add_to_query,
195 modtime_row_free_data,
196 modtime_add_rows_from_query
197 },
198 {
199 N_("Size")("Size"),
200 size_row_create_widgets,
201 size_row_add_to_query,
202 size_row_free_data,
203 size_add_rows_from_query
204 },
205 {
206 N_("Contained text")("Contained text"),
207 contained_text_row_create_widgets,
208 contained_text_row_add_to_query,
209 contained_text_row_free_data,
210 contained_text_add_rows_from_query
211 }
212};
213
214EEL_CLASS_BOILERPLATE (CajaQueryEditor,static gpointer parent_class; GType caja_query_editor_get_type
(void) { GType parent_type; static GType type; if (type == 0
) { static GTypeInfo info = { sizeof (CajaQueryEditorClass), (
(void*)0), ((void*)0), (GClassInitFunc) caja_query_editor_class_init
, ((void*)0), ((void*)0), sizeof (CajaQueryEditor), 0, (GInstanceInitFunc
) caja_query_editor_init, ((void*)0) }; parent_type = ((gtk_box_get_type
())); type = g_type_register_static (parent_type, "CajaQueryEditor"
, &info, 0); parent_class = g_type_class_ref (parent_type
); } return type; }
215 caja_query_editor,static gpointer parent_class; GType caja_query_editor_get_type
(void) { GType parent_type; static GType type; if (type == 0
) { static GTypeInfo info = { sizeof (CajaQueryEditorClass), (
(void*)0), ((void*)0), (GClassInitFunc) caja_query_editor_class_init
, ((void*)0), ((void*)0), sizeof (CajaQueryEditor), 0, (GInstanceInitFunc
) caja_query_editor_init, ((void*)0) }; parent_type = ((gtk_box_get_type
())); type = g_type_register_static (parent_type, "CajaQueryEditor"
, &info, 0); parent_class = g_type_class_ref (parent_type
); } return type; }
216 GTK_TYPE_BOX)static gpointer parent_class; GType caja_query_editor_get_type
(void) { GType parent_type; static GType type; if (type == 0
) { static GTypeInfo info = { sizeof (CajaQueryEditorClass), (
(void*)0), ((void*)0), (GClassInitFunc) caja_query_editor_class_init
, ((void*)0), ((void*)0), sizeof (CajaQueryEditor), 0, (GInstanceInitFunc
) caja_query_editor_init, ((void*)0) }; parent_type = ((gtk_box_get_type
())); type = g_type_register_static (parent_type, "CajaQueryEditor"
, &info, 0); parent_class = g_type_class_ref (parent_type
); } return type; }
217
218static void
219caja_query_editor_finalize (GObject *object)
220{
221 CajaQueryEditor *editor;
222
223 editor = CAJA_QUERY_EDITOR (object)((((CajaQueryEditor*) (void *) ((object)))));
224
225 g_free (editor->details);
226
227 EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object))do { if (((((GObjectClass*) (void *) ((parent_class)))))->
finalize != ((void*)0)) { (* ((((GObjectClass*) (void *) ((parent_class
)))))->finalize) (object); } } while (0)
;
228}
229
230static void
231caja_query_editor_dispose (GObject *object)
232{
233 CajaQueryEditor *editor;
234
235 editor = CAJA_QUERY_EDITOR (object)((((CajaQueryEditor*) (void *) ((object)))));
236
237 if (editor->details->typing_timeout_id)
238 {
239 g_source_remove (editor->details->typing_timeout_id);
240 editor->details->typing_timeout_id = 0;
241 }
242
243 if (editor->details->bar != NULL((void*)0))
244 {
245 g_signal_handlers_disconnect_by_func (editor->details->entry,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
246 entry_activate_cb,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
247 editor)g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
;
248 g_signal_handlers_disconnect_by_func (editor->details->entry,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
249 entry_changed_cb,g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
250 editor)g_signal_handlers_disconnect_matched ((editor->details->
entry), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
;
251
252 caja_search_bar_return_entry (editor->details->bar);
253 eel_remove_weak_pointer (&editor->details->bar);
254 }
255
256 EEL_CALL_PARENT (G_OBJECT_CLASS, dispose, (object))do { if (((((GObjectClass*) (void *) ((parent_class)))))->
dispose != ((void*)0)) { (* ((((GObjectClass*) (void *) ((parent_class
)))))->dispose) (object); } } while (0)
;
257}
258
259static void
260caja_query_editor_class_init (CajaQueryEditorClass *class)
261{
262 GObjectClass *gobject_class;
263 GtkBindingSet *binding_set;
264
265 gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))));
266 gobject_class->finalize = caja_query_editor_finalize;
267 gobject_class->dispose = caja_query_editor_dispose;
268
269 signals[CHANGED] =
270 g_signal_new ("changed",
271 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
272 G_SIGNAL_RUN_LAST,
273 G_STRUCT_OFFSET (CajaQueryEditorClass, changed)((glong) __builtin_offsetof(CajaQueryEditorClass, changed)),
274 NULL((void*)0), NULL((void*)0),
275 caja_src_marshal_VOID__OBJECT_BOOLEAN,
276 G_TYPE_NONE((GType) ((1) << (2))), 2, CAJA_TYPE_QUERY(caja_query_get_type ()), G_TYPE_BOOLEAN((GType) ((5) << (2))));
277
278 signals[CANCEL] =
279 g_signal_new ("cancel",
280 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
281 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
282 G_STRUCT_OFFSET (CajaQueryEditorClass, cancel)((glong) __builtin_offsetof(CajaQueryEditorClass, cancel)),
283 NULL((void*)0), NULL((void*)0),
284 g_cclosure_marshal_VOID__VOID,
285 G_TYPE_NONE((GType) ((1) << (2))), 0);
286
287 binding_set = gtk_binding_set_by_class (class);
288 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape0xff1b, 0, "cancel", 0);
289}
290
291static void
292entry_activate_cb (GtkWidget *entry, CajaQueryEditor *editor)
293{
294 if (editor->details->typing_timeout_id)
295 {
296 g_source_remove (editor->details->typing_timeout_id);
297 editor->details->typing_timeout_id = 0;
298 }
299
300 caja_query_editor_changed_force (editor, TRUE(!(0)));
301}
302
303static gboolean
304typing_timeout_cb (gpointer user_data)
305{
306 CajaQueryEditor *editor;
307
308 editor = CAJA_QUERY_EDITOR (user_data)((((CajaQueryEditor*) (void *) ((user_data)))));
309
310 caja_query_editor_changed (editor);
311
312 editor->details->typing_timeout_id = 0;
313
314 return FALSE(0);
315}
316
317#define TYPING_TIMEOUT750 750
318
319static void
320entry_changed_cb (GtkWidget *entry, CajaQueryEditor *editor)
321{
322 if (editor->details->change_frozen)
323 {
324 return;
325 }
326
327 if (editor->details->typing_timeout_id)
328 {
329 g_source_remove (editor->details->typing_timeout_id);
330 }
331
332 editor->details->typing_timeout_id =
333 g_timeout_add (TYPING_TIMEOUT750,
334 typing_timeout_cb,
335 editor);
336}
337
338static void
339edit_clicked (GtkButton *button, CajaQueryEditor *editor)
340{
341 caja_query_editor_set_visible (editor, TRUE(!(0)));
342 caja_query_editor_grab_focus (editor);
343}
344
345/* Location */
346
347static GtkWidget *
348location_row_create_widgets (CajaQueryEditorRow *row)
349{
350 GtkWidget *chooser;
351
352 chooser = gtk_file_chooser_button_new (_("Select folder to search in")dcgettext (((void*)0), "Select folder to search in", 5),
353 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
354 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser)((((GtkFileChooser*) (void *) ((chooser))))), TRUE(!(0)));
355 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser)((((GtkFileChooser*) (void *) ((chooser))))),
356 g_get_home_dir ());
357 gtk_widget_show (chooser);
358
359 g_signal_connect_swapped (chooser, "current-folder-changed",g_signal_connect_data ((chooser), ("current-folder-changed"),
(((GCallback) (caja_query_editor_changed))), (row->editor
), ((void*)0), G_CONNECT_SWAPPED)
360 G_CALLBACK (caja_query_editor_changed),g_signal_connect_data ((chooser), ("current-folder-changed"),
(((GCallback) (caja_query_editor_changed))), (row->editor
), ((void*)0), G_CONNECT_SWAPPED)
361 row->editor)g_signal_connect_data ((chooser), ("current-folder-changed"),
(((GCallback) (caja_query_editor_changed))), (row->editor
), ((void*)0), G_CONNECT_SWAPPED)
;
362
363 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), chooser, FALSE(0), FALSE(0), 0);
364
365 return chooser;
366}
367
368static void
369location_row_add_to_query (CajaQueryEditorRow *row,
370 CajaQuery *query)
371{
372 char *folder, *uri;
373
374 folder = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (row->type_widget)((((GtkFileChooser*) (void *) ((row->type_widget))))));
375 if (folder == NULL((void*)0))
376 {
377 /* I don't know why, but i got NULL here on initial search in browser mode
378 even with the location set to the homedir in create_widgets... */
379 folder = g_strdup (g_get_home_dir ())g_strdup_inline (g_get_home_dir ());
380 }
381
382 uri = g_filename_to_uri (folder, NULL((void*)0), NULL((void*)0));
383 g_free (folder);
384
385 caja_query_set_location (query, uri);
386 g_free (uri);
387}
388
389static void
390location_row_free_data (CajaQueryEditorRow *row)
391{
392}
393
394static void
395location_add_rows_from_query (CajaQueryEditor *editor,
396 CajaQuery *query)
397{
398 CajaQueryEditorRow *row;
399 char *uri, *folder;
400
401 uri = caja_query_get_location (query);
402
403 if (uri == NULL((void*)0))
404 {
405 return;
406 }
407 folder = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
408 g_free (uri);
409 if (folder == NULL((void*)0))
410 {
411 return;
412 }
413
414 row = caja_query_editor_add_row (editor,
415 CAJA_QUERY_EDITOR_ROW_LOCATION);
416 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (row->type_widget)((((GtkFileChooser*) (void *) ((row->type_widget))))),
417 folder);
418
419 g_free (folder);
420}
421
422/* Tags */
423static void
424tags_entry_changed_cb (GtkWidget *entry, gpointer *data)
425{
426 /* remove commas from string */
427 const gchar *text = gtk_entry_get_text ( GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))));
428 if (g_strrstr (text, ",") == NULL((void*)0)) {
429 return;
430 }
431
432 gchar **words = g_strsplit (text, ",", -1);
433 gchar *sanitized = g_strjoinv ("", words);
434 g_strfreev (words);
435
436 gtk_entry_set_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))), sanitized);
437 g_free(sanitized);
438}
439
440#define MAX_TAGS_ENTRY_LEN4096 4096 // arbitrary value.
441
442static GtkWidget *
443tags_row_create_widgets (CajaQueryEditorRow *row)
444{
445 GtkWidget *entry = gtk_entry_new();
446 gtk_entry_set_max_length (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))), MAX_TAGS_ENTRY_LEN4096);
447 gtk_widget_set_tooltip_text (entry,
448 _("Tags separated by spaces. "dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
449 "Matches files that contains ALL specified tags.")dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
);
450
451 gtk_entry_set_placeholder_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))),
452 _("Tags separated by spaces. "dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
453 "Matches files that contains ALL specified tags.")dcgettext (((void*)0), "Tags separated by spaces. " "Matches files that contains ALL specified tags."
, 5)
);
454
455 gtk_widget_show (entry);
456 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), entry, TRUE(!(0)), TRUE(!(0)), 0);
457 g_signal_connect (entry, "changed", G_CALLBACK (tags_entry_changed_cb), entry)g_signal_connect_data ((entry), ("changed"), (((GCallback) (tags_entry_changed_cb
))), (entry), ((void*)0), (GConnectFlags) 0)
;
458 g_signal_connect (entry, "activate", G_CALLBACK (go_search_cb), row->editor)g_signal_connect_data ((entry), ("activate"), (((GCallback) (
go_search_cb))), (row->editor), ((void*)0), (GConnectFlags
) 0)
;
459
460 return entry;
461}
462
463static void
464tags_row_add_to_query (CajaQueryEditorRow *row,
465 CajaQuery *query)
466{
467 GtkEntry *entry = GTK_ENTRY (row->type_widget)((((GtkEntry*) (void *) ((row->type_widget)))));
468 const gchar *tags = gtk_entry_get_text (entry);
469
470 char **strv = g_strsplit (tags, " ", -1);
471 guint len = g_strv_length (strv);
472 int i;
473
474 for (i = 0; i < len; ++i) {
475 strv[i] = g_strstrip (strv[i])g_strchomp (g_strchug (strv[i]));
476 if (strlen (strv[i]) > 0) {
477 caja_query_add_tag (query, strv[i]);
478 }
479 }
480 g_strfreev (strv);
481}
482
483static void
484tags_row_free_data (CajaQueryEditorRow *row)
485{
486}
487
488static gchar *
489xattr_tags_list_to_str (const GList *tags)
490{
491 gchar *result = NULL((void*)0);
492
493 const GList *tags_iter = NULL((void*)0);
494 for (tags_iter = tags; tags_iter; tags_iter = tags_iter->next) {
495 gchar *tmp;
496
497 if (result != NULL((void*)0)) {
498 tmp = g_strconcat (result, ",", tags_iter->data, NULL((void*)0));
499 g_free (result);
500 } else {
501 tmp = g_strdup (tags_iter->data)g_strdup_inline (tags_iter->data);
502 }
503
504 result = tmp;
505 }
506
507 return result;
508}
509
510static void
511tags_add_rows_from_query (CajaQueryEditor *editor,
512 CajaQuery *query)
513{
514 GList *tags = caja_query_get_tags (query);
515 if (tags == NULL((void*)0)) {
516 return;
517 }
518
519 CajaQueryEditorRow *row;
520 row = caja_query_editor_add_row (editor, CAJA_QUERY_EDITOR_ROW_TAGS);
521
522 gchar *tags_str = xattr_tags_list_to_str (tags);
523 g_list_free_full (tags, g_free);
524
525 gtk_entry_set_text (GTK_ENTRY (row->type_widget)((((GtkEntry*) (void *) ((row->type_widget))))), tags_str);
526 g_free (tags_str);
527}
528
529
530/* Type */
531
532static gboolean
533type_separator_func (GtkTreeModel *model,
534 GtkTreeIter *iter,
535 gpointer data)
536{
537 char *text;
538 gboolean res;
539
540 gtk_tree_model_get (model, iter, 0, &text, -1);
541
542 res = text != NULL((void*)0) && strcmp (text, "---") == 0;
543
544 g_free (text);
545 return res;
546}
547
548struct
549{
550 char *name;
551 char *mimetypes[20];
552} mime_type_groups[] =
553{
554 {
555 N_("Documents")("Documents"),
556 {
557 "application/rtf",
558 "application/msword",
559 "application/vnd.sun.xml.writer",
560 "application/vnd.sun.xml.writer.global",
561 "application/vnd.sun.xml.writer.template",
562 "application/vnd.oasis.opendocument.text",
563 "application/vnd.oasis.opendocument.text-template",
564 "application/x-abiword",
565 "application/x-applix-word",
566 "application/x-mswrite",
567 "application/docbook+xml",
568 "application/x-kword",
569 "application/x-kword-crypt",
570 "application/x-lyx",
571 NULL((void*)0)
572 }
573 },
574 {
575 N_("Music")("Music"),
576 {
577 "application/ogg",
578 "audio/ac3",
579 "audio/basic",
580 "audio/midi",
581 "audio/x-flac",
582 "audio/mp4",
583 "audio/mpeg",
584 "audio/x-mpeg",
585 "audio/x-ms-asx",
586 "audio/x-pn-realaudio",
587 NULL((void*)0)
588 }
589 },
590 {
591 N_("Video")("Video"),
592 {
593 "video/mp4",
594 "video/3gpp",
595 "video/mpeg",
596 "video/quicktime",
597 "video/vivo",
598 "video/x-avi",
599 "video/x-mng",
600 "video/x-ms-asf",
601 "video/x-ms-wmv",
602 "video/x-msvideo",
603 "video/x-nsv",
604 "video/x-real-video",
605 NULL((void*)0)
606 }
607 },
608 {
609 N_("Picture")("Picture"),
610 {
611 "application/vnd.oasis.opendocument.image",
612 "application/x-krita",
613 "image/bmp",
614 "image/cgm",
615 "image/gif",
616 "image/jpeg",
617 "image/jpeg2000",
618 "image/png",
619 "image/svg+xml",
620 "image/tiff",
621 "image/x-compressed-xcf",
622 "image/x-pcx",
623 "image/x-photo-cd",
624 "image/x-psd",
625 "image/x-tga",
626 "image/x-xcf",
627 NULL((void*)0)
628 }
629 },
630 {
631 N_("Illustration")("Illustration"),
632 {
633 "application/illustrator",
634 "application/vnd.corel-draw",
635 "application/vnd.stardivision.draw",
636 "application/vnd.oasis.opendocument.graphics",
637 "application/x-dia-diagram",
638 "application/x-karbon",
639 "application/x-killustrator",
640 "application/x-kivio",
641 "application/x-kontour",
642 "application/x-wpg",
643 NULL((void*)0)
644 }
645 },
646 {
647 N_("Spreadsheet")("Spreadsheet"),
648 {
649 "application/vnd.lotus-1-2-3",
650 "application/vnd.ms-excel",
651 "application/vnd.stardivision.calc",
652 "application/vnd.sun.xml.calc",
653 "application/vnd.oasis.opendocument.spreadsheet",
654 "application/x-applix-spreadsheet",
655 "application/x-gnumeric",
656 "application/x-kspread",
657 "application/x-kspread-crypt",
658 "application/x-quattropro",
659 "application/x-sc",
660 "application/x-siag",
661 NULL((void*)0)
662 }
663 },
664 {
665 N_("Presentation")("Presentation"),
666 {
667 "application/vnd.ms-powerpoint",
668 "application/vnd.sun.xml.impress",
669 "application/vnd.oasis.opendocument.presentation",
670 "application/x-magicpoint",
671 "application/x-kpresenter",
672 NULL((void*)0)
673 }
674 },
675 {
676 N_("Pdf / Postscript")("Pdf / Postscript"),
677 {
678 "application/pdf",
679 "application/postscript",
680 "application/x-dvi",
681 "image/x-eps",
682 NULL((void*)0)
683 }
684 },
685 {
686 N_("Text File")("Text File"),
687 {
688 "text/plain",
689 NULL((void*)0)
690 }
691 }
692};
693
694static void
695type_add_custom_type (CajaQueryEditorRow *row,
696 const char *mime_type,
697 const char *description,
698 GtkTreeIter *iter)
699{
700 GtkTreeModel *model;
701 GtkListStore *store;
702
703 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
704 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
705
706 gtk_list_store_append (store, iter);
707 gtk_list_store_set (store, iter,
708 0, description,
709 2, mime_type,
710 -1);
711}
712
713
714static void
715type_combo_changed (GtkComboBox *combo_box, CajaQueryEditorRow *row)
716{
717 GtkTreeIter iter;
718 gboolean other;
719 GtkTreeModel *model;
720
721 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
722 &iter))
723 {
724 return;
725 }
726
727 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
728 gtk_tree_model_get (model, &iter, 3, &other, -1);
729
730 if (other)
731 {
732 GList *mime_infos, *l;
733 GtkWidget *dialog;
734 GtkWidget *scrolled, *treeview;
735 GtkListStore *store;
736 GtkTreeViewColumn *column;
737 GtkCellRenderer *renderer;
738 GtkWidget *toplevel;
739 GtkTreeSelection *selection;
740
741 mime_infos = g_content_types_get_registered ();
742
743 store = gtk_list_store_new (2, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
744 for (l = mime_infos; l != NULL((void*)0); l = l->next)
745 {
746 GtkTreeIter iter;
747 char *mime_type = l->data;
748 char *description;
749
750 description = g_content_type_get_description (mime_type);
751 if (description == NULL((void*)0))
752 {
753 description = g_strdup (mime_type)g_strdup_inline (mime_type);
754 }
755
756 gtk_list_store_append (store, &iter);
757 gtk_list_store_set (store, &iter,
758 0, description,
759 1, mime_type,
760 -1);
761
762 g_free (mime_type);
763 g_free (description);
764 }
765 g_list_free (mime_infos);
766
767
768
769 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (combo_box)((((GtkWidget*) (void *) ((combo_box))))));
770
771 dialog = gtk_dialog_new ();
772 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), _("Select type")dcgettext (((void*)0), "Select type", 5));
773 gtk_window_set_transient_for (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), GTK_WINDOW (toplevel)((((GtkWindow*) (void *) ((toplevel))))));
774
775 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
776 _("_OK")dcgettext (((void*)0), "_OK", 5),
777 "gtk-ok",
778 GTK_RESPONSE_OK);
779
780 gtk_window_set_default_size (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), 400, 600);
781
782 scrolled = gtk_scrolled_window_new (NULL((void*)0), NULL((void*)0));
783 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
784 GTK_POLICY_AUTOMATIC,
785 GTK_POLICY_AUTOMATIC);
786 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
787 GTK_SHADOW_IN);
788 gtk_scrolled_window_set_overlay_scrolling (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
789 FALSE(0));
790
791 gtk_widget_show (scrolled);
792 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dialog)))))))))))
, scrolled, TRUE(!(0)), TRUE(!(0)), 6);
793
794 treeview = gtk_tree_view_new ();
795 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))),
796 GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))));
797 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store)((((GtkTreeSortable*) (void *) ((store))))), 0,
798 GTK_SORT_ASCENDING);
799
800 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))));
801 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
802
803
804 renderer = gtk_cell_renderer_text_new ();
805 column = gtk_tree_view_column_new_with_attributes ("Name",
806 renderer,
807 "text",
808 0,
809 NULL((void*)0));
810 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))), column);
811 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview)((((GtkTreeView*) (void *) ((treeview))))), FALSE(0));
812
813 gtk_widget_show (treeview);
814 gtk_container_add (GTK_CONTAINER (scrolled)((((GtkContainer*) (void *) ((scrolled))))), treeview);
815
816 if (gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog)))))) == GTK_RESPONSE_OK)
817 {
818 char *mimetype, *description;
819
820 gtk_tree_selection_get_selected (selection, NULL((void*)0), &iter);
821 gtk_tree_model_get (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))), &iter,
822 0, &description,
823 1, &mimetype,
824 -1);
825
826 type_add_custom_type (row, mimetype, description, &iter);
827 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
828 &iter);
829 }
830 else
831 {
832 gtk_combo_box_set_active (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))), 0);
833 }
834
835 gtk_widget_destroy (dialog);
836 }
837
838 caja_query_editor_changed (row->editor);
839}
840
841static GtkWidget *
842type_row_create_widgets (CajaQueryEditorRow *row)
843{
844 GtkWidget *combo;
845 GtkCellRenderer *cell;
846 GtkListStore *store;
847 GtkTreeIter iter;
848 int i;
849
850 store = gtk_list_store_new (4, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_POINTER((GType) ((17) << (2))), G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_BOOLEAN((GType) ((5) << (2))));
851 combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))));
852 g_object_unref (store);
853
854 cell = gtk_cell_renderer_text_new ();
855 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
856 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell,
857 "text", 0,
858 NULL((void*)0));
859 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))),
860 type_separator_func,
861 NULL((void*)0), NULL((void*)0));
862
863 gtk_list_store_append (store, &iter);
864 gtk_list_store_set (store, &iter, 0, _("Any")dcgettext (((void*)0), "Any", 5), -1);
865 gtk_list_store_append (store, &iter);
866 gtk_list_store_set (store, &iter, 0, "---", -1);
867
868 for (i = 0; i < G_N_ELEMENTS (mime_type_groups)(sizeof (mime_type_groups) / sizeof ((mime_type_groups)[0])); i++)
869 {
870 gtk_list_store_append (store, &iter);
871 gtk_list_store_set (store, &iter,
872 0, gettext (mime_type_groups[i].name)dcgettext (((void*)0), mime_type_groups[i].name, 5),
873 1, mime_type_groups[i].mimetypes,
874 -1);
875 }
876
877 gtk_list_store_append (store, &iter);
878 gtk_list_store_set (store, &iter, 0, "---", -1);
879 gtk_list_store_append (store, &iter);
880 gtk_list_store_set (store, &iter, 0, _("Other Type...")dcgettext (((void*)0), "Other Type...", 5), 3, TRUE(!(0)), -1);
881
882 gtk_combo_box_set_active (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), 0);
883
884 g_signal_connect (combo, "changed",g_signal_connect_data ((combo), ("changed"), (((GCallback) (type_combo_changed
))), (row), ((void*)0), (GConnectFlags) 0)
885 G_CALLBACK (type_combo_changed),g_signal_connect_data ((combo), ("changed"), (((GCallback) (type_combo_changed
))), (row), ((void*)0), (GConnectFlags) 0)
886 row)g_signal_connect_data ((combo), ("changed"), (((GCallback) (type_combo_changed
))), (row), ((void*)0), (GConnectFlags) 0)
;
887
888 gtk_widget_show (combo);
889
890 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), combo, FALSE(0), FALSE(0), 0);
891
892 return combo;
893}
894
895static void
896type_row_add_to_query (CajaQueryEditorRow *row,
897 CajaQuery *query)
898{
899 GtkTreeIter iter;
900 char **mimetypes;
901 char *mimetype;
902 GtkTreeModel *model;
903
904 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
905 &iter))
906 {
907 return;
908 }
909
910 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
911 gtk_tree_model_get (model, &iter, 1, &mimetypes, 2, &mimetype, -1);
912
913 if (mimetypes != NULL((void*)0))
914 {
915 while (*mimetypes != NULL((void*)0))
916 {
917 caja_query_add_mime_type (query, *mimetypes);
918 mimetypes++;
919 }
920 }
921 if (mimetype)
922 {
923 caja_query_add_mime_type (query, mimetype);
924 g_free (mimetype);
925 }
926}
927
928static void
929type_row_free_data (CajaQueryEditorRow *row)
930{
931}
932
933static gboolean
934all_group_types_in_list (char **group_types, GList *mime_types)
935{
936 GList *l;
937 char **group_type;
938 char *mime_type;
939 gboolean found;
940
941 group_type = group_types;
942 while (*group_type != NULL((void*)0))
943 {
944 found = FALSE(0);
945
946 for (l = mime_types; l != NULL((void*)0); l = l->next)
947 {
948 mime_type = l->data;
949
950 if (strcmp (mime_type, *group_type) == 0)
951 {
952 found = TRUE(!(0));
953 break;
954 }
955 }
956
957 if (!found)
958 {
959 return FALSE(0);
960 }
961 group_type++;
962 }
963 return TRUE(!(0));
964}
965
966static GList *
967remove_group_types_from_list (char **group_types, GList *mime_types)
968{
969 GList *l, *next;
970 char **group_type;
971 char *mime_type;
972
973 group_type = group_types;
974 while (*group_type != NULL((void*)0))
975 {
976 for (l = mime_types; l != NULL((void*)0); l = next)
977 {
978 mime_type = l->data;
979 next = l->next;
980
981 if (strcmp (mime_type, *group_type) == 0)
982 {
983 mime_types = g_list_remove_link (mime_types, l);
984 g_free (mime_type);
985 break;
986 }
987 }
988
989 group_type++;
990 }
991 return mime_types;
992}
993
994
995static void
996type_add_rows_from_query (CajaQueryEditor *editor,
997 CajaQuery *query)
998{
999 GList *mime_types;
1000 char *mime_type;
1001 CajaQueryEditorRow *row;
1002 GtkTreeIter iter;
1003 int i;
1004 GtkTreeModel *model;
1005 GList *l;
1006
1007 mime_types = caja_query_get_mime_types (query);
1008
1009 if (mime_types == NULL((void*)0))
1010 {
1011 return;
1012 }
1013
1014 for (i = 0; i < G_N_ELEMENTS (mime_type_groups)(sizeof (mime_type_groups) / sizeof ((mime_type_groups)[0])); i++)
1015 {
1016 if (all_group_types_in_list (mime_type_groups[i].mimetypes,
1017 mime_types))
1018 {
1019 mime_types = remove_group_types_from_list (mime_type_groups[i].mimetypes,
1020 mime_types);
1021
1022 row = caja_query_editor_add_row (editor,
1023 CAJA_QUERY_EDITOR_ROW_TYPE);
1024
1025 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
1026
1027 gtk_tree_model_iter_nth_child (model, &iter, NULL((void*)0), i + 2);
1028 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
1029 &iter);
1030 }
1031 }
1032
1033 for (l = mime_types; l != NULL((void*)0); l = l->next)
1034 {
1035 const char *desc;
1036
1037 mime_type = l->data;
1038
1039 desc = g_content_type_get_description (mime_type);
1040 if (desc == NULL((void*)0))
1041 {
1042 desc = mime_type;
1043 }
1044
1045 row = caja_query_editor_add_row (editor,
1046 CAJA_QUERY_EDITOR_ROW_TYPE);
1047 model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))));
1048
1049 type_add_custom_type (row, mime_type, desc, &iter);
1050 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget)((((GtkComboBox*) (void *) ((row->type_widget))))),
1051 &iter);
1052 }
1053
1054 g_list_free_full (mime_types, g_free);
1055}
1056
1057/* End of row types */
1058
1059
1060static GtkWidget *modtime_row_create_widgets(CajaQueryEditorRow *row)
1061{
1062 GtkWidget *hbox = NULL((void*)0);
1063 GtkWidget *combo = NULL((void*)0);
1064 GtkWidget *duration_combo = NULL((void*)0);
1065 GtkCellRenderer *cell = NULL((void*)0);
1066 GtkListStore *store = NULL((void*)0);
1067 GtkListStore *duration_store = NULL((void*)0);
1068 GtkTreeIter iter;
1069
1070 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7);
1071
1072 store = gtk_list_store_new(2, G_TYPE_BOOLEAN((GType) ((5) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1073 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)((((GtkTreeModel*) (void *) ((store))))));
1074 g_object_unref(store);
1075
1076 cell = gtk_cell_renderer_text_new();
1077 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
1078 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, "text", 1,
1079 NULL((void*)0));
1080
1081 gtk_list_store_append(store, &iter);
1082 gtk_list_store_set(store, &iter, 0, FALSE(0), 1, _("Less than or equal to")dcgettext (((void*)0), "Less than or equal to", 5), -1);
1083 gtk_list_store_append(store, &iter);
1084 gtk_list_store_set(store, &iter, 0, TRUE(!(0)), 1, _("Greater than or equal to")dcgettext (((void*)0), "Greater than or equal to", 5), -1);
1085
1086 gtk_combo_box_set_active(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), 0);
1087
1088 duration_store = gtk_list_store_new(2, G_TYPE_INT((GType) ((6) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1089 duration_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(duration_store)((((GtkTreeModel*) (void *) ((duration_store))))));
1090 g_object_unref(duration_store);
1091
1092 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(duration_combo)((((GtkCellLayout*) (void *) ((duration_combo))))), cell, TRUE(!(0)));
1093 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(duration_combo)((((GtkCellLayout*) (void *) ((duration_combo))))), cell,
1094 "text", 1, NULL((void*)0));
1095
1096 gtk_list_store_append(duration_store, &iter);
1097 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_HOUR, 1, _("1 Hour")dcgettext (((void*)0), "1 Hour", 5), -1);
1098 gtk_list_store_append(duration_store, &iter);
1099 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_DAY, 1, _("1 Day")dcgettext (((void*)0), "1 Day", 5), -1);
1100 gtk_list_store_append(duration_store, &iter);
1101 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_WEEK, 1, _("1 Week")dcgettext (((void*)0), "1 Week", 5), -1);
1102 gtk_list_store_append(duration_store, &iter);
1103 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_MONTH, 1, _("1 Month")dcgettext (((void*)0), "1 Month", 5), -1);
1104 gtk_list_store_append(duration_store, &iter);
1105 gtk_list_store_set(duration_store, &iter, 0, DURATION_SIX_MONTHS, 1, _("6 Months")dcgettext (((void*)0), "6 Months", 5), -1);
1106 gtk_list_store_append(duration_store, &iter);
1107 gtk_list_store_set(duration_store, &iter, 0, DURATION_ONE_YEAR, 1, _("1 Year")dcgettext (((void*)0), "1 Year", 5), -1);
1108
1109 gtk_combo_box_set_active(GTK_COMBO_BOX(duration_combo)((((GtkComboBox*) (void *) ((duration_combo))))), 0);
1110
1111 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), combo, FALSE(0), FALSE(0), 0);
1112 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), duration_combo, FALSE(0), FALSE(0), 0);
1113 gtk_widget_show_all(hbox);
1114
1115 gtk_box_pack_start(GTK_BOX(row->hbox)((((GtkBox*) (void *) ((row->hbox))))), hbox, FALSE(0), FALSE(0), 0);
1116
1117 return hbox;
1118}
1119
1120static void modtime_row_add_to_query(CajaQueryEditorRow *row, CajaQuery *query)
1121{
1122 GList *children = NULL((void*)0);
1123 GtkWidget *combo = NULL((void*)0);
1124 GtkWidget *duration_combo = NULL((void*)0);
1125 GtkTreeModel *model = NULL((void*)0);
1126 GtkTreeModel *duration_model = NULL((void*)0);
1127 GtkTreeIter iter;
1128 GtkTreeIter duration_iter;
1129 gboolean is_greater = FALSE(0);
1130 GDateTime *now, *datetime;
1131 gint duration;
1132 gint64 timestamp;
1133
1134 if (!GTK_IS_CONTAINER(row->type_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(row->type_widget)); GType __t = ((gtk_container_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; }))))
)
1135 return;
1136
1137 children = gtk_container_get_children(GTK_CONTAINER(row->type_widget)((((GtkContainer*) (void *) ((row->type_widget))))));
1138 if (g_list_length(children) != 2)
1139 return;
1140
1141 combo = GTK_WIDGET(g_list_nth(children, 0)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 0)->data))
)))
;
1142 duration_combo = GTK_WIDGET(g_list_nth(children, 1)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 1)->data))
)))
;
1143 if (!combo || !duration_combo)
1144 return;
1145
1146 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter) ||
1147 !gtk_combo_box_get_active_iter(GTK_COMBO_BOX(duration_combo)((((GtkComboBox*) (void *) ((duration_combo))))), &duration_iter)) {
1148 return;
1149 }
1150
1151 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
1152 gtk_tree_model_get(model, &iter, 0, &is_greater, -1);
1153
1154 duration_model = gtk_combo_box_get_model(GTK_COMBO_BOX(duration_combo)((((GtkComboBox*) (void *) ((duration_combo))))));
1155 gtk_tree_model_get(duration_model, &duration_iter, 0, &duration, -1);
1156
1157 now = g_date_time_new_now_local ();
1158 datetime = now;
Value stored to 'datetime' is never read
1159 switch (duration)
1160 {
1161 case DURATION_ONE_HOUR:
1162 datetime = g_date_time_add_hours (now, -1);
1163 break;
1164 case DURATION_ONE_DAY:
1165 datetime = g_date_time_add_days (now, -1);
1166 break;
1167 case DURATION_ONE_WEEK:
1168 datetime = g_date_time_add_weeks (now, -1);
1169 break;
1170 case DURATION_ONE_MONTH:
1171 datetime = g_date_time_add_months (now, -1);
1172 break;
1173 case DURATION_SIX_MONTHS:
1174 datetime = g_date_time_add_months (now, -6);
1175 break;
1176 case DURATION_ONE_YEAR:
1177 datetime = g_date_time_add_years (now, -1);
1178 break;
1179 default:
1180 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-query-editor.c"
, 1180, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1181 }
1182
1183 g_date_time_unref (now);
1184 timestamp = g_date_time_to_unix (datetime);
1185 g_date_time_unref (datetime);
1186
1187 caja_query_set_timestamp(query, is_greater ? timestamp: -timestamp);
1188}
1189
1190static void modtime_row_free_data(CajaQueryEditorRow *row)
1191{
1192}
1193
1194static void modtime_add_rows_from_query(CajaQueryEditor *editor, CajaQuery *query)
1195{
1196}
1197
1198
1199static GtkWidget *size_row_create_widgets(CajaQueryEditorRow *row)
1200{
1201 GtkWidget *hbox = NULL((void*)0);
1202 GtkWidget *combo = NULL((void*)0);
1203 GtkWidget *size_combo = NULL((void*)0);
1204 GtkCellRenderer *cell = NULL((void*)0);
1205 GtkListStore *store = NULL((void*)0);
1206 GtkListStore *size_store = NULL((void*)0);
1207 GtkTreeIter iter;
1208
1209 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7);
1210
1211 store = gtk_list_store_new(2, G_TYPE_BOOLEAN((GType) ((5) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1212 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)((((GtkTreeModel*) (void *) ((store))))));
1213 g_object_unref(store);
1214
1215 cell = gtk_cell_renderer_text_new();
1216 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
1217 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo)((((GtkCellLayout*) (void *) ((combo))))), cell, "text", 1,
1218 NULL((void*)0));
1219
1220 gtk_list_store_append(store, &iter);
1221 gtk_list_store_set(store, &iter, 0, FALSE(0), 1, _("Less than or equal to")dcgettext (((void*)0), "Less than or equal to", 5), -1);
1222 gtk_list_store_append(store, &iter);
1223 gtk_list_store_set(store, &iter, 0, TRUE(!(0)), 1, _("Greater than or equal to")dcgettext (((void*)0), "Greater than or equal to", 5), -1);
1224
1225 gtk_combo_box_set_active(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), 0);
1226
1227 size_store = gtk_list_store_new(2, G_TYPE_INT64((GType) ((10) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
1228 size_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(size_store)((((GtkTreeModel*) (void *) ((size_store))))));
1229 g_object_unref(size_store);
1230
1231 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(size_combo)((((GtkCellLayout*) (void *) ((size_combo))))), cell, TRUE(!(0)));
1232 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(size_combo)((((GtkCellLayout*) (void *) ((size_combo))))), cell, "text",
1233 1, NULL((void*)0));
1234
1235 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
1236 {
1237 gtk_list_store_append(size_store, &iter);
1238 gtk_list_store_set(size_store, &iter, 0, 10240, 1, _("10 KiB")dcgettext (((void*)0), "10 KiB", 5), -1);
1239 gtk_list_store_append(size_store, &iter);
1240 gtk_list_store_set(size_store, &iter, 0, 102400, 1, _("100 KiB")dcgettext (((void*)0), "100 KiB", 5), -1);
1241 gtk_list_store_append(size_store, &iter);
1242 gtk_list_store_set(size_store, &iter, 0, 512000, 1, _("500 KiB")dcgettext (((void*)0), "500 KiB", 5), -1);
1243 gtk_list_store_append(size_store, &iter);
1244 gtk_list_store_set(size_store, &iter, 0, 1048576, 1, _("1 MiB")dcgettext (((void*)0), "1 MiB", 5), -1);
1245 gtk_list_store_append(size_store, &iter);
1246 gtk_list_store_set(size_store, &iter, 0, 5242880, 1, _("5 MiB")dcgettext (((void*)0), "5 MiB", 5), -1);
1247 gtk_list_store_append(size_store, &iter);
1248 gtk_list_store_set(size_store, &iter, 0, 10485760, 1, _("10 MiB")dcgettext (((void*)0), "10 MiB", 5), -1);
1249 gtk_list_store_append(size_store, &iter);
1250 gtk_list_store_set(size_store, &iter, 0, 104857600, 1, _("100 MiB")dcgettext (((void*)0), "100 MiB", 5), -1);
1251 gtk_list_store_append(size_store, &iter);
1252 gtk_list_store_set(size_store, &iter, 0, 524288000, 1, _("500 MiB")dcgettext (((void*)0), "500 MiB", 5), -1);
1253 gtk_list_store_append(size_store, &iter);
1254 gtk_list_store_set(size_store, &iter, 0, 1073741824, 1, _("1 GiB")dcgettext (((void*)0), "1 GiB", 5), -1);
1255 gtk_list_store_append(size_store, &iter);
1256 gtk_list_store_set(size_store, &iter, 0, 2147483648, 1, _("2 GiB")dcgettext (((void*)0), "2 GiB", 5), -1);
1257 gtk_list_store_append(size_store, &iter);
1258 gtk_list_store_set(size_store, &iter, 0, 4294967296, 1, _("4 GiB")dcgettext (((void*)0), "4 GiB", 5), -1);
1259 } else {
1260 gtk_list_store_append(size_store, &iter);
1261 gtk_list_store_set(size_store, &iter, 0, 10000, 1, _("10 KB")dcgettext (((void*)0), "10 KB", 5), -1);
1262 gtk_list_store_append(size_store, &iter);
1263 gtk_list_store_set(size_store, &iter, 0, 100000, 1, _("100 KB")dcgettext (((void*)0), "100 KB", 5), -1);
1264 gtk_list_store_append(size_store, &iter);
1265 gtk_list_store_set(size_store, &iter, 0, 500000, 1, _("500 KB")dcgettext (((void*)0), "500 KB", 5), -1);
1266 gtk_list_store_append(size_store, &iter);
1267 gtk_list_store_set(size_store, &iter, 0, 1000000, 1, _("1 MB")dcgettext (((void*)0), "1 MB", 5), -1);
1268 gtk_list_store_append(size_store, &iter);
1269 gtk_list_store_set(size_store, &iter, 0, 5000000, 1, _("5 MB")dcgettext (((void*)0), "5 MB", 5), -1);
1270 gtk_list_store_append(size_store, &iter);
1271 gtk_list_store_set(size_store, &iter, 0, 10000000, 1, _("10 MB")dcgettext (((void*)0), "10 MB", 5), -1);
1272 gtk_list_store_append(size_store, &iter);
1273 gtk_list_store_set(size_store, &iter, 0, 100000000, 1, _("100 MB")dcgettext (((void*)0), "100 MB", 5), -1);
1274 gtk_list_store_append(size_store, &iter);
1275 gtk_list_store_set(size_store, &iter, 0, 500000000, 1, _("500 MB")dcgettext (((void*)0), "500 MB", 5), -1);
1276 gtk_list_store_append(size_store, &iter);
1277 gtk_list_store_set(size_store, &iter, 0, 1000000000, 1, _("1 GB")dcgettext (((void*)0), "1 GB", 5), -1);
1278 gtk_list_store_append(size_store, &iter);
1279 gtk_list_store_set(size_store, &iter, 0, 2000000000, 1, _("2 GB")dcgettext (((void*)0), "2 GB", 5), -1);
1280 gtk_list_store_append(size_store, &iter);
1281 gtk_list_store_set(size_store, &iter, 0, 4000000000, 1, _("4 GB")dcgettext (((void*)0), "4 GB", 5), -1);
1282 }
1283
1284 gtk_combo_box_set_active(GTK_COMBO_BOX(size_combo)((((GtkComboBox*) (void *) ((size_combo))))), 0);
1285
1286 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), combo, FALSE(0), FALSE(0), 0);
1287 gtk_box_pack_start(GTK_BOX(hbox)((((GtkBox*) (void *) ((hbox))))), size_combo, FALSE(0), FALSE(0), 0);
1288 gtk_widget_show_all(hbox);
1289
1290 gtk_box_pack_start(GTK_BOX(row->hbox)((((GtkBox*) (void *) ((row->hbox))))), hbox, FALSE(0), FALSE(0), 0);
1291
1292 return hbox;
1293}
1294
1295static void size_row_add_to_query(CajaQueryEditorRow *row, CajaQuery *query)
1296{
1297 GList *children = NULL((void*)0);
1298 GtkWidget *combo = NULL((void*)0);
1299 GtkWidget *size_combo = NULL((void*)0);
1300 GtkTreeModel *model = NULL((void*)0);
1301 GtkTreeModel *size_model = NULL((void*)0);
1302 GtkTreeIter iter;
1303 GtkTreeIter size_iter;
1304 gboolean is_greater = FALSE(0);
1305 gint64 size;
1306
1307 if (!GTK_IS_CONTAINER(row->type_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(row->type_widget)); GType __t = ((gtk_container_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; }))))
)
1308 return;
1309
1310 children = gtk_container_get_children(GTK_CONTAINER(row->type_widget)((((GtkContainer*) (void *) ((row->type_widget))))));
1311 if (g_list_length(children) != 2)
1312 return;
1313
1314 combo = GTK_WIDGET(g_list_nth(children, 0)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 0)->data))
)))
;
1315 size_combo = GTK_WIDGET(g_list_nth(children, 1)->data)((((GtkWidget*) (void *) ((g_list_nth(children, 1)->data))
)))
;
1316 if (!combo || !size_combo)
1317 return;
1318
1319 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter) ||
1320 !gtk_combo_box_get_active_iter(GTK_COMBO_BOX(size_combo)((((GtkComboBox*) (void *) ((size_combo))))), &size_iter)) {
1321 return;
1322 }
1323
1324 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
1325 gtk_tree_model_get(model, &iter, 0, &is_greater, -1);
1326
1327 size_model = gtk_combo_box_get_model(GTK_COMBO_BOX(size_combo)((((GtkComboBox*) (void *) ((size_combo))))));
1328 gtk_tree_model_get(size_model, &size_iter, 0, &size, -1);
1329
1330 caja_query_set_size(query, is_greater ? size : -size);
1331}
1332
1333static void size_row_free_data(CajaQueryEditorRow *row)
1334{
1335}
1336
1337static void size_add_rows_from_query(CajaQueryEditor *editor, CajaQuery *query)
1338{
1339}
1340
1341static GtkWidget *
1342contained_text_row_create_widgets (CajaQueryEditorRow *row)
1343{
1344 GtkWidget *entry = gtk_entry_new();
1345 gtk_widget_set_tooltip_text (entry,
1346 _("Matches files that contains specified text.")dcgettext (((void*)0), "Matches files that contains specified text."
, 5)
);
1347
1348 gtk_entry_set_placeholder_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))),
1349 _("Matches files that contains specified text.")dcgettext (((void*)0), "Matches files that contains specified text."
, 5)
);
1350
1351 gtk_widget_show (entry);
1352 gtk_box_pack_start (GTK_BOX (row->hbox)((((GtkBox*) (void *) ((row->hbox))))), entry, TRUE(!(0)), TRUE(!(0)), 0);
1353 g_signal_connect (entry, "activate", G_CALLBACK (go_search_cb), row->editor)g_signal_connect_data ((entry), ("activate"), (((GCallback) (
go_search_cb))), (row->editor), ((void*)0), (GConnectFlags
) 0)
;
1354
1355 return entry;
1356}
1357
1358static void
1359contained_text_row_add_to_query (CajaQueryEditorRow *row, CajaQuery *query)
1360{
1361 GtkEntry *entry = GTK_ENTRY (row->type_widget)((((GtkEntry*) (void *) ((row->type_widget)))));
1362 const gchar *text = gtk_entry_get_text (entry);
1363
1364 caja_query_set_contained_text (query, text);
1365}
1366
1367static void
1368contained_text_row_free_data (CajaQueryEditorRow *row)
1369{
1370}
1371
1372static void
1373contained_text_add_rows_from_query (CajaQueryEditor *editor, CajaQuery *query)
1374{
1375}
1376
1377static CajaQueryEditorRowType
1378get_next_free_type (CajaQueryEditor *editor)
1379{
1380 CajaQueryEditorRow *row;
1381 CajaQueryEditorRowType type;
1382 gboolean found;
1383 GList *l;
1384
1385
1386 for (type = 0; type < CAJA_QUERY_EDITOR_ROW_LAST; type++)
1387 {
1388 found = FALSE(0);
1389 for (l = editor->details->rows; l != NULL((void*)0); l = l->next)
1390 {
1391 row = l->data;
1392 if (row->type == type)
1393 {
1394 found = TRUE(!(0));
1395 break;
1396 }
1397 }
1398 if (!found)
1399 {
1400 return type;
1401 }
1402 }
1403 return CAJA_QUERY_EDITOR_ROW_TYPE;
1404}
1405
1406static void
1407remove_row_cb (GtkButton *clicked_button, CajaQueryEditorRow *row)
1408{
1409 CajaQueryEditor *editor;
1410
1411 editor = row->editor;
1412 gtk_container_remove (GTK_CONTAINER (editor->details->visible_vbox)((((GtkContainer*) (void *) ((editor->details->visible_vbox
)))))
,
1413 row->hbox);
1414
1415 editor->details->rows = g_list_remove (editor->details->rows, row);
1416
1417 row_type[row->type].free_data (row);
1418 g_free (row);
1419
1420 caja_query_editor_changed (editor);
1421}
1422
1423static void
1424create_type_widgets (CajaQueryEditorRow *row)
1425{
1426 row->type_widget = row_type[row->type].create_widgets (row);
1427}
1428
1429static void
1430row_type_combo_changed_cb (GtkComboBox *combo_box, CajaQueryEditorRow *row)
1431{
1432 CajaQueryEditorRowType type;
1433
1434 type = gtk_combo_box_get_active (combo_box);
1435
1436 if (type == row->type)
1437 {
1438 return;
1439 }
1440
1441 if (row->type_widget != NULL((void*)0))
1442 {
1443 gtk_widget_destroy (row->type_widget);
1444 row->type_widget = NULL((void*)0);
1445 }
1446
1447 row_type[row->type].free_data (row);
1448 row->data = NULL((void*)0);
1449
1450 row->type = type;
1451
1452 create_type_widgets (row);
1453
1454 caja_query_editor_changed (row->editor);
1455}
1456
1457static CajaQueryEditorRow *
1458caja_query_editor_add_row (CajaQueryEditor *editor,
1459 CajaQueryEditorRowType type)
1460{
1461 GtkWidget *hbox, *button, *image, *combo;
1462 CajaQueryEditorRow *row;
1463 int i;
1464
1465 row = g_new0 (CajaQueryEditorRow, 1)(CajaQueryEditorRow *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (CajaQueryEditorRow); 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; }))
;
1466 row->editor = editor;
1467 row->type = type;
1468
1469 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1470 row->hbox = hbox;
1471 gtk_widget_show (hbox);
1472 gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox)((((GtkBox*) (void *) ((editor->details->visible_vbox))
)))
, hbox, FALSE(0), FALSE(0), 0);
1473
1474 combo = gtk_combo_box_text_new ();
1475 row->combo = combo;
1476 for (i = 0; i < CAJA_QUERY_EDITOR_ROW_LAST; i++)
1477 {
1478 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo)((((GtkComboBoxText*) (void *) ((combo))))), gettext (row_type[i].name)dcgettext (((void*)0), row_type[i].name, 5));
1479 }
1480 gtk_widget_show (combo);
1481 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), combo, FALSE(0), FALSE(0), 0);
1482
1483 gtk_combo_box_set_active (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), row->type);
1484
1485 editor->details->rows = g_list_append (editor->details->rows, row);
1486
1487 g_signal_connect (combo, "changed",g_signal_connect_data ((combo), ("changed"), (((GCallback) (row_type_combo_changed_cb
))), (row), ((void*)0), (GConnectFlags) 0)
1488 G_CALLBACK (row_type_combo_changed_cb), row)g_signal_connect_data ((combo), ("changed"), (((GCallback) (row_type_combo_changed_cb
))), (row), ((void*)0), (GConnectFlags) 0)
;
1489
1490 create_type_widgets (row);
1491
1492 button = gtk_button_new ();
1493 image = gtk_image_new_from_icon_name ("remove",
1494 GTK_ICON_SIZE_SMALL_TOOLBAR);
1495 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), image);
1496 gtk_widget_show (image);
1497 gtk_button_set_relief (GTK_BUTTON (button)((((GtkButton*) (void *) ((button))))), GTK_RELIEF_NONE);
1498 gtk_widget_show (button);
1499
1500 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
remove_row_cb))), (row), ((void*)0), (GConnectFlags) 0)
1501 G_CALLBACK (remove_row_cb), row)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
remove_row_cb))), (row), ((void*)0), (GConnectFlags) 0)
;
1502 gtk_widget_set_tooltip_text (button,
1503 _("Remove this criterion from the search")dcgettext (((void*)0), "Remove this criterion from the search"
, 5)
);
1504
1505 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1506
1507 return row;
1508}
1509
1510static void
1511go_search_cb (GtkButton *clicked_button, CajaQueryEditor *editor)
1512{
1513 caja_query_editor_changed_force (editor, TRUE(!(0)));
1514}
1515
1516static void
1517add_new_row_cb (GtkButton *clicked_button, CajaQueryEditor *editor)
1518{
1519 caja_query_editor_add_row (editor, get_next_free_type (editor));
1520 caja_query_editor_changed (editor);
1521}
1522
1523static void
1524caja_query_editor_init (CajaQueryEditor *editor)
1525{
1526 GtkWidget *hbox, *label, *button;
1527 char *label_markup;
1528
1529 editor->details = g_new0 (CajaQueryEditorDetails, 1)(CajaQueryEditorDetails *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (CajaQueryEditorDetails); 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; }))
;
1530 editor->details->is_visible = TRUE(!(0));
1531
1532 editor->details->invisible_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1533 gtk_orientable_set_orientation (GTK_ORIENTABLE (editor)((((GtkOrientable*) (void *) ((editor))))), GTK_ORIENTATION_VERTICAL);
1534 gtk_box_pack_start (GTK_BOX (editor)((((GtkBox*) (void *) ((editor))))), editor->details->invisible_vbox,
1535 FALSE(0), FALSE(0), 0);
1536 editor->details->visible_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1537 gtk_orientable_set_orientation (GTK_ORIENTABLE (editor)((((GtkOrientable*) (void *) ((editor))))), GTK_ORIENTATION_VERTICAL);
1538 gtk_box_pack_start (GTK_BOX (editor)((((GtkBox*) (void *) ((editor))))), editor->details->visible_vbox,
1539 FALSE(0), FALSE(0), 0);
1540 /* Only show visible vbox */
1541 gtk_widget_show (editor->details->visible_vbox);
1542
1543 /* Create invisible part: */
1544 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1545 gtk_box_pack_start (GTK_BOX (editor->details->invisible_vbox)((((GtkBox*) (void *) ((editor->details->invisible_vbox
)))))
,
1546 hbox, FALSE(0), FALSE(0), 0);
1547 gtk_widget_show (hbox);
1548
1549 label = gtk_label_new ("");
1550 label_markup = g_strconcat ("<b>", _("Search Folder")dcgettext (((void*)0), "Search Folder", 5), "</b>", NULL((void*)0));
1551 gtk_label_set_markup (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), label_markup);
1552 g_free (label_markup);
1553 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), label, FALSE(0), FALSE(0), 0);
1554 gtk_widget_show (label);
1555
1556 button = gtk_button_new_with_label (_("Edit")dcgettext (((void*)0), "Edit", 5));
1557 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1558 gtk_widget_show (button);
1559
1560 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
edit_clicked))), (editor), ((void*)0), (GConnectFlags) 0)
1561 G_CALLBACK (edit_clicked), editor)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
edit_clicked))), (editor), ((void*)0), (GConnectFlags) 0)
;
1562
1563 gtk_widget_set_tooltip_text (button,
1564 _("Edit the saved search")dcgettext (((void*)0), "Edit the saved search", 5));
1565}
1566
1567void
1568caja_query_editor_set_default_query (CajaQueryEditor *editor)
1569{
1570 if (!editor->details->is_indexed)
1571 {
1572 caja_query_editor_add_row (editor, CAJA_QUERY_EDITOR_ROW_LOCATION);
1573 caja_query_editor_changed (editor);
1574 }
1575}
1576
1577static void
1578finish_first_line (CajaQueryEditor *editor, GtkWidget *hbox, gboolean use_go)
1579{
1580 GtkWidget *button, *image;
1581
1582 button = gtk_button_new ();
1583 image = gtk_image_new_from_icon_name ("add",
1584 GTK_ICON_SIZE_SMALL_TOOLBAR);
1585 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), image);
1586 gtk_widget_show (image);
1587 gtk_button_set_relief (GTK_BUTTON (button)((((GtkButton*) (void *) ((button))))), GTK_RELIEF_NONE);
1588 gtk_widget_show (button);
1589
1590 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
add_new_row_cb))), (editor), ((void*)0), (GConnectFlags) 0)
1591 G_CALLBACK (add_new_row_cb), editor)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
add_new_row_cb))), (editor), ((void*)0), (GConnectFlags) 0)
;
1592
1593 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1594
1595 gtk_widget_set_tooltip_text (button,
1596 _("Add a new criterion to this search")dcgettext (((void*)0), "Add a new criterion to this search", 5
)
);
1597
1598 if (!editor->details->is_indexed)
1599 {
1600 if (use_go)
1601 {
1602 button = gtk_button_new_with_label (_("Go")dcgettext (((void*)0), "Go", 5));
1603 }
1604 else
1605 {
1606 button = gtk_button_new_with_label (_("Reload")dcgettext (((void*)0), "Reload", 5));
1607 }
1608 gtk_widget_show (button);
1609
1610 gtk_widget_set_tooltip_text (button,
1611 _("Perform or update the search")dcgettext (((void*)0), "Perform or update the search", 5));
1612
1613 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
go_search_cb))), (editor), ((void*)0), (GConnectFlags) 0)
1614 G_CALLBACK (go_search_cb), editor)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
go_search_cb))), (editor), ((void*)0), (GConnectFlags) 0)
;
1615
1616 gtk_box_pack_end (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
1617 }
1618}
1619
1620static void
1621setup_internal_entry (CajaQueryEditor *editor)
1622{
1623 GtkWidget *hbox, *label;
1624 char *label_markup;
1625
1626 /* Create visible part: */
1627 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1628 gtk_widget_show (hbox);
1629 gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox)((((GtkBox*) (void *) ((editor->details->visible_vbox))
)))
, hbox, FALSE(0), FALSE(0), 0);
1630
1631 label = gtk_label_new ("");
1632 label_markup = g_strconcat ("<b>", _("_Search for:")dcgettext (((void*)0), "_Search for:", 5), "</b>", NULL((void*)0));
1633 gtk_label_set_markup_with_mnemonic (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), label_markup);
1634 g_free (label_markup);
1635 gtk_widget_show (label);
1636 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), label, FALSE(0), FALSE(0), 0);
1637
1638 editor->details->entry = gtk_entry_new ();
1639 gtk_label_set_mnemonic_widget (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), editor->details->entry);
1640 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), editor->details->entry, TRUE(!(0)), TRUE(!(0)), 0);
1641
1642 g_signal_connect (editor->details->entry, "activate",g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
1643 G_CALLBACK (entry_activate_cb), editor)g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
;
1644 g_signal_connect (editor->details->entry, "changed",g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
1645 G_CALLBACK (entry_changed_cb), editor)g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
;
1646 gtk_widget_show (editor->details->entry);
1647
1648 finish_first_line (editor, hbox, TRUE(!(0)));
1649}
1650
1651static void
1652setup_external_entry (CajaQueryEditor *editor, GtkWidget *entry)
1653{
1654 GtkWidget *hbox, *label;
1655
1656 /* Create visible part: */
1657 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1658 gtk_widget_show (hbox);
1659 gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox)((((GtkBox*) (void *) ((editor->details->visible_vbox))
)))
, hbox, FALSE(0), FALSE(0), 0);
1660
1661 label = gtk_label_new (_("Search results")dcgettext (((void*)0), "Search results", 5));
1662 gtk_widget_show (label);
1663 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), label, FALSE(0), FALSE(0), 0);
1664
1665 editor->details->entry = entry;
1666 g_signal_connect (editor->details->entry, "activate",g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
1667 G_CALLBACK (entry_activate_cb), editor)g_signal_connect_data ((editor->details->entry), ("activate"
), (((GCallback) (entry_activate_cb))), (editor), ((void*)0),
(GConnectFlags) 0)
;
1668 g_signal_connect (editor->details->entry, "changed",g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
1669 G_CALLBACK (entry_changed_cb), editor)g_signal_connect_data ((editor->details->entry), ("changed"
), (((GCallback) (entry_changed_cb))), (editor), ((void*)0), (
GConnectFlags) 0)
;
1670
1671 finish_first_line (editor, hbox, FALSE(0));
1672
1673}
1674
1675void
1676caja_query_editor_set_visible (CajaQueryEditor *editor,
1677 gboolean visible)
1678{
1679 editor->details->is_visible = visible;
1680 if (visible)
1681 {
1682 gtk_widget_show (editor->details->visible_vbox);
1683 gtk_widget_hide (editor->details->invisible_vbox);
1684 }
1685 else
1686 {
1687 gtk_widget_hide (editor->details->visible_vbox);
1688 gtk_widget_show (editor->details->invisible_vbox);
1689 }
1690}
1691
1692static gboolean
1693query_is_valid (CajaQueryEditor *editor)
1694{
1695 const char *text;
1696
1697 text = gtk_entry_get_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))));
1698
1699 return text != NULL((void*)0) && text[0] != '\0';
1700}
1701
1702static void
1703caja_query_editor_changed_force (CajaQueryEditor *editor, gboolean force_reload)
1704{
1705 if (editor->details->change_frozen)
1706 {
1707 return;
1708 }
1709
1710 if (query_is_valid (editor))
1711 {
1712 CajaQuery *query;
1713
1714 query = caja_query_editor_get_query (editor);
1715 g_signal_emit (editor, signals[CHANGED], 0,
1716 query, editor->details->is_indexed || force_reload);
1717 g_object_unref (query);
1718 }
1719}
1720
1721static void
1722caja_query_editor_changed (CajaQueryEditor *editor)
1723{
1724 caja_query_editor_changed_force (editor, FALSE(0));
1725}
1726
1727void
1728caja_query_editor_grab_focus (CajaQueryEditor *editor)
1729{
1730 if (editor->details->is_visible)
1731 {
1732 gtk_widget_grab_focus (editor->details->entry);
1733 }
1734}
1735
1736CajaQuery *
1737caja_query_editor_get_query (CajaQueryEditor *editor)
1738{
1739 const char *query_text;
1740 CajaQuery *query;
1741 GList *l;
1742 CajaQueryEditorRow *row = NULL((void*)0);
1743
1744 if (editor == NULL((void*)0) || editor->details == NULL((void*)0) || editor->details->entry == NULL((void*)0))
1745 {
1746 return NULL((void*)0);
1747 }
1748
1749 query_text = gtk_entry_get_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))));
1750
1751 /* Empty string is a NULL query */
1752 if (query_text && query_text[0] == '\0')
1753 {
1754 return NULL((void*)0);
1755 }
1756
1757 query = caja_query_new ();
1758 caja_query_set_text (query, query_text);
1759
1760 for (l = editor->details->rows; l != NULL((void*)0); l = l->next)
1761 {
1762 row = l->data;
1763
1764 row_type[row->type].add_to_query (row, query);
1765 }
1766
1767 return query;
1768}
1769
1770void
1771caja_query_editor_clear_query (CajaQueryEditor *editor)
1772{
1773 editor->details->change_frozen = TRUE(!(0));
1774 gtk_entry_set_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))), "");
1775
1776 g_free (editor->details->last_set_query_text);
1777 editor->details->last_set_query_text = g_strdup ("")g_strdup_inline ("");
1778
1779 editor->details->change_frozen = FALSE(0);
1780}
1781
1782GtkWidget *
1783caja_query_editor_new (gboolean start_hidden,
1784 gboolean is_indexed)
1785{
1786 GtkWidget *editor;
1787
1788 editor = g_object_new (CAJA_TYPE_QUERY_EDITORcaja_query_editor_get_type(), NULL((void*)0));
1789
1790 CAJA_QUERY_EDITOR (editor)((((CajaQueryEditor*) (void *) ((editor)))))->details->is_indexed = is_indexed;
1791
1792 caja_query_editor_set_visible (CAJA_QUERY_EDITOR (editor)((((CajaQueryEditor*) (void *) ((editor))))),
1793 !start_hidden);
1794
1795 setup_internal_entry (CAJA_QUERY_EDITOR (editor)((((CajaQueryEditor*) (void *) ((editor))))));
1796
1797 return editor;
1798}
1799
1800static void
1801detach_from_external_entry (CajaQueryEditor *editor)
1802{
1803 if (editor->details->bar != NULL((void*)0))
1804 {
1805 caja_search_bar_return_entry (editor->details->bar);
1806 g_signal_handlers_block_by_func (editor->details->entry,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1807 entry_activate_cb,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1808 editor)g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
;
1809 g_signal_handlers_block_by_func (editor->details->entry,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1810 entry_changed_cb,g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1811 editor)g_signal_handlers_block_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
;
1812 }
1813}
1814
1815static void
1816attach_to_external_entry (CajaQueryEditor *editor)
1817{
1818 if (editor->details->bar != NULL((void*)0))
1819 {
1820 caja_search_bar_borrow_entry (editor->details->bar);
1821 g_signal_handlers_unblock_by_func (editor->details->entry,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1822 entry_activate_cb,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
1823 editor)g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_activate_cb), (editor))
;
1824 g_signal_handlers_unblock_by_func (editor->details->entry,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1825 entry_changed_cb,g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
1826 editor)g_signal_handlers_unblock_matched ((editor->details->entry
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (entry_changed_cb), (editor))
;
1827
1828 editor->details->change_frozen = TRUE(!(0));
1829 gtk_entry_set_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))),
1830 editor->details->last_set_query_text);
1831 editor->details->change_frozen = FALSE(0);
1832 }
1833}
1834
1835GtkWidget*
1836caja_query_editor_new_with_bar (gboolean start_hidden,
1837 gboolean is_indexed,
1838 gboolean start_attached,
1839 CajaSearchBar *bar,
1840 CajaWindowSlot *slot)
1841{
1842 GtkWidget *entry;
1843 CajaQueryEditor *editor;
1844
1845 editor = CAJA_QUERY_EDITOR (g_object_new (CAJA_TYPE_QUERY_EDITOR, NULL))((((CajaQueryEditor*) (void *) ((g_object_new (caja_query_editor_get_type
(), ((void*)0)))))))
;
1846 editor->details->is_indexed = is_indexed;
1847
1848 caja_query_editor_set_visible (editor, !start_hidden);
1849
1850 editor->details->bar = bar;
1851 eel_add_weak_pointer (&editor->details->bar);
1852
1853 editor->details->slot = slot;
1854
1855 entry = caja_search_bar_borrow_entry (bar);
1856 setup_external_entry (editor, entry);
1857 if (!start_attached)
1858 {
1859 detach_from_external_entry (editor);
1860 }
1861
1862 g_signal_connect_object (slot, "active",
1863 G_CALLBACK (attach_to_external_entry)((GCallback) (attach_to_external_entry)),
1864 editor, G_CONNECT_SWAPPED);
1865 g_signal_connect_object (slot, "inactive",
1866 G_CALLBACK (detach_from_external_entry)((GCallback) (detach_from_external_entry)),
1867 editor, G_CONNECT_SWAPPED);
1868
1869 return GTK_WIDGET (editor)((((GtkWidget*) (void *) ((editor)))));
1870}
1871
1872void
1873caja_query_editor_set_query (CajaQueryEditor *editor, CajaQuery *query)
1874{
1875 CajaQueryEditorRowType type;
1876 char *text;
1877
1878 if (!query)
1879 {
1880 caja_query_editor_clear_query (editor);
1881 return;
1882 }
1883
1884 text = caja_query_get_text (query);
1885
1886 if (!text)
1887 {
1888 text = g_strdup ("")g_strdup_inline ("");
1889 }
1890
1891 editor->details->change_frozen = TRUE(!(0));
1892 gtk_entry_set_text (GTK_ENTRY (editor->details->entry)((((GtkEntry*) (void *) ((editor->details->entry))))), text);
1893
1894 for (type = 0; type < CAJA_QUERY_EDITOR_ROW_LAST; type++)
1895 {
1896 row_type[type].add_rows_from_query (editor, query);
1897 }
1898
1899 editor->details->change_frozen = FALSE(0);
1900
1901 g_free (editor->details->last_set_query_text);
1902 editor->details->last_set_query_text = text;
1903}
diff --git a/2024-07-29-023715-6438-1/report-535ee1.html b/2024-07-29-023715-6438-1/report-535ee1.html new file mode 100644 index 000000000..157892a40 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-535ee1.html @@ -0,0 +1,10862 @@ + + + +caja-icon-container.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-icon-container.c
Warning:line 1512, column 9
Value stored to 'y' 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 caja-icon-container.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-icon-container.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* caja-icon-container.c - Icon container widget.
4
5 Copyright (C) 1999, 2000 Free Software Foundation
6 Copyright (C) 2000, 2001 Eazel, Inc.
7 Copyright (C) 2002, 2003 Red Hat, Inc.
8
9 The Mate Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 The Mate Library 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 GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public
20 License along with the Mate Library; see the file COPYING.LIB. If not,
21 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24 Authors: Ettore Perazzoli <ettore@gnu.org>,
25 Darin Adler <darin@bentspoon.com>
26*/
27
28#include <config.h>
29#include <math.h>
30#include <atk/atkaction.h>
31#include <gdk/gdkkeysyms.h>
32#include <gtk/gtk.h>
33#include <gdk/gdkx.h>
34#include <glib/gi18n.h>
35#include <stdio.h>
36#include <string.h>
37
38#include <eel/eel-accessibility.h>
39#include <eel/eel-background.h>
40#include <eel/eel-vfs-extensions.h>
41#include <eel/eel-gdk-pixbuf-extensions.h>
42#include <eel/eel-mate-extensions.h>
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-art-extensions.h>
45#include <eel/eel-editable-label.h>
46#include <eel/eel-string.h>
47#include <eel/eel-canvas.h>
48#include <eel/eel-canvas-rect-ellipse.h>
49
50#include "caja-icon-container.h"
51#include "caja-debug-log.h"
52#include "caja-global-preferences.h"
53#include "caja-icon-private.h"
54#include "caja-lib-self-check-functions.h"
55#include "caja-marshal.h"
56
57#define TAB_NAVIGATION_DISABLED
58
59/* Interval for updating the rubberband selection, in milliseconds. */
60#define RUBBERBAND_TIMEOUT_INTERVAL10 10
61
62/* Initial unpositioned icon value */
63#define ICON_UNPOSITIONED_VALUE-1 -1
64
65/* Timeout for making the icon currently selected for keyboard operation visible.
66 * If this is 0, you can get into trouble with extra scrolling after holding
67 * down the arrow key for awhile when there are many items.
68 */
69#define KEYBOARD_ICON_REVEAL_TIMEOUT10 10
70
71/* Maximum amount of milliseconds the mouse button is allowed to stay down
72 * and still be considered a click.
73 */
74#define MAX_CLICK_TIME1500 1500
75
76/* Button assignments. */
77#define DRAG_BUTTON1 1
78#define RUBBERBAND_BUTTON1 1
79#define MIDDLE_BUTTON2 2
80#define CONTEXTUAL_MENU_BUTTON3 3
81#define DRAG_MENU_BUTTON2 2
82
83/* Maximum size (pixels) allowed for icons at the standard zoom level. */
84#define MINIMUM_IMAGE_SIZE24 24
85#define MAXIMUM_IMAGE_SIZE96 96
86
87#define ICON_PAD_LEFT4 4
88#define ICON_PAD_RIGHT4 4
89
90#define ICON_PAD_TOP4 4
91#define ICON_PAD_BOTTOM4 4
92
93#define CONTAINER_PAD_LEFT4 4
94#define CONTAINER_PAD_RIGHT4 4
95#define CONTAINER_PAD_TOP4 4
96#define CONTAINER_PAD_BOTTOM4 4
97
98#define STANDARD_ICON_GRID_WIDTH155 155
99
100/* Desktop layout mode defines */
101#define DESKTOP_PAD_HORIZONTAL10 10
102#define DESKTOP_PAD_VERTICAL10 10
103#define SNAP_SIZE_X78 78
104#define SNAP_SIZE_Y20 20
105
106/* If icon size is bigger than this, request large embedded text.
107 * Its selected so that the non-large text should fit in "normal" icon sizes
108 */
109#define ICON_SIZE_FOR_LARGE_EMBEDDED_TEXT55 55
110
111#define SNAP_HORIZONTAL(func,x)((func ((double)((x) - 10) / 78) * 78) + 10) ((func ((double)((x) - DESKTOP_PAD_HORIZONTAL10) / SNAP_SIZE_X78) * SNAP_SIZE_X78) + DESKTOP_PAD_HORIZONTAL10)
112#define SNAP_VERTICAL(func, y)((func ((double)((y) - 10) / 20) * 20) + 10) ((func ((double)((y) - DESKTOP_PAD_VERTICAL10) / SNAP_SIZE_Y20) * SNAP_SIZE_Y20) + DESKTOP_PAD_VERTICAL10)
113
114#define SNAP_NEAREST_HORIZONTAL(x)((eel_round ((double)((x) - 10) / 78) * 78) + 10) SNAP_HORIZONTAL (eel_round, x)((eel_round ((double)((x) - 10) / 78) * 78) + 10)
115#define SNAP_NEAREST_VERTICAL(y)((eel_round ((double)((y) - 10) / 20) * 20) + 10) SNAP_VERTICAL (eel_round, y)((eel_round ((double)((y) - 10) / 20) * 20) + 10)
116
117#define SNAP_CEIL_HORIZONTAL(x)((ceil ((double)((x) - 10) / 78) * 78) + 10) SNAP_HORIZONTAL (ceil, x)((ceil ((double)((x) - 10) / 78) * 78) + 10)
118#define SNAP_CEIL_VERTICAL(y)((ceil ((double)((y) - 10) / 20) * 20) + 10) SNAP_VERTICAL (ceil, y)((ceil ((double)((y) - 10) / 20) * 20) + 10)
119
120/* Copied from CajaIconContainer */
121#define CAJA_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT5 5
122
123/* Copied from CajaFile */
124#define UNDEFINED_TIME((time_t) (-1)) ((time_t) (-1))
125
126enum
127{
128 ACTION_ACTIVATE,
129 ACTION_MENU,
130 LAST_ACTION
131};
132
133typedef struct
134{
135 GList *selection;
136 char *action_descriptions[LAST_ACTION];
137} CajaIconContainerAccessiblePrivate;
138
139static GType caja_icon_container_accessible_get_type (void);
140
141typedef struct _CajaIconContainerAccessible CajaIconContainerAccessible;
142typedef struct _CajaIconContainerAccessibleClass CajaIconContainerAccessibleClass;
143
144struct _CajaIconContainerAccessible
145{
146 EelCanvasAccessible parent;
147};
148
149struct _CajaIconContainerAccessibleClass
150{
151 EelCanvasAccessibleClass parent_class;
152};
153
154static void activate_selected_items (CajaIconContainer *container);
155static void activate_selected_items_alternate (CajaIconContainer *container,
156 CajaIcon *icon);
157static void compute_stretch (StretchState *start,
158 StretchState *current);
159static CajaIcon *get_first_selected_icon (CajaIconContainer *container);
160static CajaIcon *get_nth_selected_icon (CajaIconContainer *container,
161 int index);
162static gboolean has_multiple_selection (CajaIconContainer *container);
163static gboolean all_selected (CajaIconContainer *container);
164static gboolean has_selection (CajaIconContainer *container);
165static void icon_destroy (CajaIconContainer *container,
166 CajaIcon *icon);
167static void end_renaming_mode (CajaIconContainer *container,
168 gboolean commit);
169static CajaIcon *get_icon_being_renamed (CajaIconContainer *container);
170static void finish_adding_new_icons (CajaIconContainer *container);
171static inline void icon_get_bounding_box (CajaIcon *icon,
172 int *x1_return,
173 int *y1_return,
174 int *x2_return,
175 int *y2_return,
176 CajaIconCanvasItemBoundsUsage usage);
177static gboolean is_renaming (CajaIconContainer *container);
178static gboolean is_renaming_pending (CajaIconContainer *container);
179static void process_pending_icon_to_rename (CajaIconContainer *container);
180static void caja_icon_container_stop_monitor_top_left (CajaIconContainer *container,
181 CajaIconData *data,
182 gconstpointer client);
183static void caja_icon_container_start_monitor_top_left (CajaIconContainer *container,
184 CajaIconData *data,
185 gconstpointer client,
186 gboolean large_text);
187static void handle_hadjustment_changed (GtkAdjustment *adjustment,
188 CajaIconContainer *container);
189static void handle_vadjustment_changed (GtkAdjustment *adjustment,
190 CajaIconContainer *container);
191static GList * caja_icon_container_get_selected_icons (CajaIconContainer *container);
192static void caja_icon_container_update_visible_icons (CajaIconContainer *container);
193static void reveal_icon (CajaIconContainer *container,
194 CajaIcon *icon);
195
196static void caja_icon_container_set_rtl_positions (CajaIconContainer *container);
197static double get_mirror_x_position (CajaIconContainer *container,
198 CajaIcon *icon,
199 double x);
200static void text_ellipsis_limit_changed_container_callback (gpointer callback_data);
201
202static int compare_icons_horizontal (CajaIconContainer *container,
203 CajaIcon *icon_a,
204 CajaIcon *icon_b);
205
206static int compare_icons_vertical (CajaIconContainer *container,
207 CajaIcon *icon_a,
208 CajaIcon *icon_b);
209
210static void store_layout_timestamps_now (CajaIconContainer *container);
211
212static gpointer accessible_parent_class;
213
214static GQuark accessible_private_data_quark = 0;
215
216static const char *caja_icon_container_accessible_action_names[] =
217{
218 "activate",
219 "menu",
220 NULL((void*)0)
221};
222
223static const char *caja_icon_container_accessible_action_descriptions[] =
224{
225 "Activate selected items",
226 "Popup context menu",
227 NULL((void*)0)
228};
229
230G_DEFINE_TYPE (CajaIconContainer, caja_icon_container, EEL_TYPE_CANVAS)static void caja_icon_container_init (CajaIconContainer *self
); static void caja_icon_container_class_init (CajaIconContainerClass
*klass); static GType caja_icon_container_get_type_once (void
); static gpointer caja_icon_container_parent_class = ((void*
)0); static gint CajaIconContainer_private_offset; static void
caja_icon_container_class_intern_init (gpointer klass) { caja_icon_container_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainer_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainer_private_offset
); caja_icon_container_class_init ((CajaIconContainerClass*) klass
); } __attribute__ ((__unused__)) static inline gpointer caja_icon_container_get_instance_private
(CajaIconContainer *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CajaIconContainer_private_offset)))); } GType
caja_icon_container_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_icon_container_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((eel_canvas_get_type ()), g_intern_static_string ("CajaIconContainer"
), sizeof (CajaIconContainerClass), (GClassInitFunc)(void (*)
(void)) caja_icon_container_class_intern_init, sizeof (CajaIconContainer
), (GInstanceInitFunc)(void (*)(void)) caja_icon_container_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
;
231
232/* The CajaIconContainer signals. */
233enum
234{
235 ACTIVATE,
236 ACTIVATE_ALTERNATE,
237 BAND_SELECT_STARTED,
238 BAND_SELECT_ENDED,
239 BUTTON_PRESS,
240 CAN_ACCEPT_ITEM,
241 CONTEXT_CLICK_BACKGROUND,
242 CONTEXT_CLICK_SELECTION,
243 MIDDLE_CLICK,
244 GET_CONTAINER_URI,
245 GET_ICON_URI,
246 GET_ICON_DROP_TARGET_URI,
247 GET_STORED_ICON_POSITION,
248 ICON_POSITION_CHANGED,
249 GET_STORED_LAYOUT_TIMESTAMP,
250 STORE_LAYOUT_TIMESTAMP,
251 ICON_TEXT_CHANGED,
252 ICON_STRETCH_STARTED,
253 ICON_STRETCH_ENDED,
254 RENAMING_ICON,
255 LAYOUT_CHANGED,
256 MOVE_COPY_ITEMS,
257 HANDLE_NETSCAPE_URL,
258 HANDLE_URI_LIST,
259 HANDLE_TEXT,
260 HANDLE_RAW,
261 PREVIEW,
262 SELECTION_CHANGED,
263 ICON_ADDED,
264 ICON_REMOVED,
265 CLEARED,
266 START_INTERACTIVE_SEARCH,
267 LAST_SIGNAL
268};
269
270typedef struct
271{
272 int **icon_grid;
273 int *grid_memory;
274 int num_rows;
275 int num_columns;
276 gboolean tight;
277} PlacementGrid;
278
279static guint signals[LAST_SIGNAL] = { 0 };
280
281/* Functions dealing with CajaIcons. */
282
283static void
284icon_free (CajaIcon *icon)
285{
286 /* Destroy this canvas item; the parent will unref it. */
287 eel_canvas_item_destroy (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))));
288 g_free (icon);
289}
290
291static gboolean
292icon_is_positioned (const CajaIcon *icon)
293{
294 return icon->x != ICON_UNPOSITIONED_VALUE-1 && icon->y != ICON_UNPOSITIONED_VALUE-1;
295}
296
297
298/* x, y are the top-left coordinates of the icon. */
299static void
300icon_set_position (CajaIcon *icon,
301 double x, double y)
302{
303 CajaIconContainer *container;
304 int x1, x2, y1, y2;
305 EelDRect icon_bounds;
306
307 if (icon->x == x && icon->y == y)
308 {
309 return;
310 }
311
312 container = CAJA_ICON_CONTAINER (EEL_CANVAS_ITEM (icon->item)->canvas)((((CajaIconContainer*) (void *) ((((((EelCanvasItem*) (void *
) ((icon->item)))))->canvas)))))
;
313
314 if (icon == get_icon_being_renamed (container))
315 {
316 end_renaming_mode (container, TRUE(!(0)));
317 }
318
319 if (caja_icon_container_get_is_fixed_size (container))
320 {
321 double pixels_per_unit;
322 int container_left, container_top, container_right, container_bottom;
323 int container_x, container_y, container_width, container_height;
324 int item_width, item_height;
325 int height_above, width_left;
326 int min_x, max_x, min_y, max_y;
327 int scale;
328
329 /* FIXME: This should be:
330
331 container_x = GTK_WIDGET (container)->allocation.x;
332 container_y = GTK_WIDGET (container)->allocation.y;
333 container_width = GTK_WIDGET (container)->allocation.width;
334 container_height = GTK_WIDGET (container)->allocation.height;
335
336 But for some reason the widget allocation is sometimes not done
337 at startup, and the allocation is then only 45x60. which is
338 really bad.
339
340 For now, we have a cheesy workaround:
341 */
342 scale = gtk_widget_get_scale_factor (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
343 container_x = 0;
344 container_y = 0;
345 container_width = WidthOfScreen (gdk_x11_screen_get_xscreen (gdk_screen_get_default ()))((gdk_x11_screen_get_xscreen (gdk_screen_get_default ()))->
width)
/ scale - container_x
346 - container->details->left_margin
347 - container->details->right_margin;
348 container_height = HeightOfScreen (gdk_x11_screen_get_xscreen (gdk_screen_get_default ()))((gdk_x11_screen_get_xscreen (gdk_screen_get_default ()))->
height)
/ scale - container_y
349 - container->details->top_margin
350 - container->details->bottom_margin;
351 pixels_per_unit = EEL_CANVAS (container)((((EelCanvas*) (void *) ((container)))))->pixels_per_unit;
352 /* Clip the position of the icon within our desktop bounds */
353 container_left = container_x / pixels_per_unit;
354 container_top = container_y / pixels_per_unit;
355 container_right = container_left + container_width / pixels_per_unit;
356 container_bottom = container_top + container_height / pixels_per_unit;
357
358 icon_get_bounding_box (icon, &x1, &y1, &x2, &y2,
359 BOUNDS_USAGE_FOR_ENTIRE_ITEM);
360 item_width = x2 - x1;
361 item_height = y2 - y1;
362
363 icon_bounds = caja_icon_canvas_item_get_icon_rectangle (icon->item);
364
365 /* determine icon rectangle relative to item rectangle */
366 height_above = icon_bounds.y0 - y1;
367 width_left = icon_bounds.x0 - x1;
368
369 min_x = container_left + DESKTOP_PAD_HORIZONTAL10 + width_left;
370 max_x = container_right - DESKTOP_PAD_HORIZONTAL10 - item_width + width_left;
371 x = CLAMP (x, min_x, max_x)(((x) > (max_x)) ? (max_x) : (((x) < (min_x)) ? (min_x)
: (x)))
;
372
373 min_y = container_top + height_above + DESKTOP_PAD_VERTICAL10;
374 max_y = container_bottom - DESKTOP_PAD_VERTICAL10 - item_height + height_above;
375 y = CLAMP (y, min_y, max_y)(((y) > (max_y)) ? (max_y) : (((y) < (min_y)) ? (min_y)
: (y)))
;
376 }
377
378 if (icon->x == ICON_UNPOSITIONED_VALUE-1)
379 {
380 icon->x = 0;
381 }
382 if (icon->y == ICON_UNPOSITIONED_VALUE-1)
383 {
384 icon->y = 0;
385 }
386
387 eel_canvas_item_move (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
388 x - icon->x,
389 y - icon->y);
390
391 icon->x = x;
392 icon->y = y;
393}
394
395static void
396icon_get_size (CajaIconContainer *container,
397 CajaIcon *icon,
398 guint *size)
399{
400 if (size != NULL((void*)0))
401 {
402 *size = MAX (caja_get_icon_size_for_zoom_level (container->details->zoom_level)(((caja_get_icon_size_for_zoom_level (container->details->
zoom_level) * icon->scale) > (16)) ? (caja_get_icon_size_for_zoom_level
(container->details->zoom_level) * icon->scale) : (
16))
403 * icon->scale, CAJA_ICON_SIZE_SMALLEST)(((caja_get_icon_size_for_zoom_level (container->details->
zoom_level) * icon->scale) > (16)) ? (caja_get_icon_size_for_zoom_level
(container->details->zoom_level) * icon->scale) : (
16))
;
404 }
405}
406
407/* The icon_set_size function is used by the stretching user
408 * interface, which currently stretches in a way that keeps the aspect
409 * ratio. Later we might have a stretching interface that stretches Y
410 * separate from X and we will change this around.
411 */
412static void
413icon_set_size (CajaIconContainer *container,
414 CajaIcon *icon,
415 guint icon_size,
416 gboolean snap,
417 gboolean update_position)
418{
419 guint old_size;
420 double scale;
421
422 icon_get_size (container, icon, &old_size);
423 if (icon_size == old_size)
424 {
425 return;
426 }
427
428 scale = (double) icon_size /
429 caja_get_icon_size_for_zoom_level
430 (container->details->zoom_level);
431 caja_icon_container_move_icon (container, icon,
432 icon->x, icon->y,
433 scale, FALSE(0),
434 snap, update_position);
435}
436
437static void
438icon_raise (CajaIcon *icon)
439{
440 EelCanvasItem *item, *band;
441
442 item = EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))));
443 band = CAJA_ICON_CONTAINER (item->canvas)((((CajaIconContainer*) (void *) ((item->canvas)))))->details->rubberband_info.selection_rectangle;
444
445 eel_canvas_item_send_behind (item, band);
446}
447
448static void
449emit_stretch_started (CajaIconContainer *container, CajaIcon *icon)
450{
451 g_signal_emit (container,
452 signals[ICON_STRETCH_STARTED], 0,
453 icon->data);
454}
455
456static void
457emit_stretch_ended (CajaIconContainer *container, CajaIcon *icon)
458{
459 g_signal_emit (container,
460 signals[ICON_STRETCH_ENDED], 0,
461 icon->data);
462}
463
464static void
465icon_toggle_selected (CajaIconContainer *container,
466 CajaIcon *icon)
467{
468 end_renaming_mode (container, TRUE(!(0)));
469
470 icon->is_selected = !icon->is_selected;
471 eel_canvas_item_set (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
472 "highlighted_for_selection", (gboolean) icon->is_selected,
473 NULL((void*)0));
474
475 /* If the icon is deselected, then get rid of the stretch handles.
476 * No harm in doing the same if the item is newly selected.
477 */
478 if (icon == container->details->stretch_icon)
479 {
480 container->details->stretch_icon = NULL((void*)0);
481 caja_icon_canvas_item_set_show_stretch_handles (icon->item, FALSE(0));
482 /* snap the icon if necessary */
483 if (container->details->keep_aligned)
484 {
485 caja_icon_container_move_icon (container,
486 icon,
487 icon->x, icon->y,
488 icon->scale,
489 FALSE(0), TRUE(!(0)), TRUE(!(0)));
490 }
491
492 emit_stretch_ended (container, icon);
493 }
494
495 /* Raise each newly-selected icon to the front as it is selected. */
496 if (icon->is_selected)
497 {
498 icon_raise (icon);
499 }
500}
501
502/* Select an icon. Return TRUE if selection has changed. */
503static gboolean
504icon_set_selected (CajaIconContainer *container,
505 CajaIcon *icon,
506 gboolean select)
507{
508 g_assert (select == FALSE || select == TRUE)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if (select == (0) || select == (!(0))) _g_boolean_var_119 =
1; else _g_boolean_var_119 = 0; _g_boolean_var_119; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 508, ((const char*) (__func__)), "select == FALSE || select == TRUE"
); } while (0)
;
509 g_assert (icon->is_selected == FALSE || icon->is_selected == TRUE)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (icon->is_selected == (0) || icon->is_selected == (
!(0))) _g_boolean_var_120 = 1; else _g_boolean_var_120 = 0; _g_boolean_var_120
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 509, ((const char*) (__func__)), "icon->is_selected == FALSE || icon->is_selected == TRUE"
); } while (0)
;
510
511 if (select == icon->is_selected)
512 {
513 return FALSE(0);
514 }
515
516 icon_toggle_selected (container, icon);
517 g_assert (select == icon->is_selected)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if (select == icon->is_selected) _g_boolean_var_121 = 1;
else _g_boolean_var_121 = 0; _g_boolean_var_121; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 517, ((const char*) (__func__)), "select == icon->is_selected"
); } while (0)
;
518 return TRUE(!(0));
519}
520
521static inline void
522icon_get_bounding_box (CajaIcon *icon,
523 int *x1_return, int *y1_return,
524 int *x2_return, int *y2_return,
525 CajaIconCanvasItemBoundsUsage usage)
526{
527 double x1, y1, x2, y2;
528
529 if (usage == BOUNDS_USAGE_FOR_DISPLAY)
530 {
531 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
532 &x1, &y1, &x2, &y2);
533 }
534 else if (usage == BOUNDS_USAGE_FOR_LAYOUT)
535 {
536 caja_icon_canvas_item_get_bounds_for_layout (icon->item,
537 &x1, &y1, &x2, &y2);
538 }
539 else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM)
540 {
541 caja_icon_canvas_item_get_bounds_for_entire_item (icon->item,
542 &x1, &y1, &x2, &y2);
543 }
544 else
545 {
546 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 546, ((const char*) (__func__)), ((void*)0)); } while (0)
;
547 }
548
549 if (x1_return != NULL((void*)0))
550 {
551 *x1_return = x1;
552 }
553
554 if (y1_return != NULL((void*)0))
555 {
556 *y1_return = y1;
557 }
558
559 if (x2_return != NULL((void*)0))
560 {
561 *x2_return = x2;
562 }
563
564 if (y2_return != NULL((void*)0))
565 {
566 *y2_return = y2;
567 }
568}
569
570/* Utility functions for CajaIconContainer. */
571
572gboolean
573caja_icon_container_scroll (CajaIconContainer *container,
574 int delta_x, int delta_y)
575{
576 GtkAdjustment *hadj, *vadj;
577 int old_h_value, old_v_value;
578
579 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
580 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
581
582 /* Store the old ajustment values so we can tell if we
583 * ended up actually scrolling. We may not have in a case
584 * where the resulting value got pinned to the adjustment
585 * min or max.
586 */
587 old_h_value = gtk_adjustment_get_value (hadj);
588 old_v_value = gtk_adjustment_get_value (vadj);
589
590 gtk_adjustment_set_value (hadj, gtk_adjustment_get_value (hadj) + delta_x);
591 gtk_adjustment_set_value (vadj, gtk_adjustment_get_value (vadj) + delta_y);
592
593 /* return TRUE if we did scroll */
594 return gtk_adjustment_get_value (hadj) != old_h_value || gtk_adjustment_get_value (vadj) != old_v_value;
595}
596
597static void
598pending_icon_to_reveal_destroy_callback (CajaIconCanvasItem *item,
599 CajaIconContainer *container)
600{
601 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 601, ((const char*) (
__func__)), "CAJA_IS_ICON_CONTAINER (container)"); } while (0
)
;
602 g_assert (container->details->pending_icon_to_reveal != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if (container->details->pending_icon_to_reveal != ((void
*)0)) _g_boolean_var_123 = 1; else _g_boolean_var_123 = 0; _g_boolean_var_123
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 602, ((const char*) (__func__)), "container->details->pending_icon_to_reveal != NULL"
); } while (0)
;
603 g_assert (container->details->pending_icon_to_reveal->item == item)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (container->details->pending_icon_to_reveal->item
== item) _g_boolean_var_124 = 1; else _g_boolean_var_124 = 0
; _g_boolean_var_124; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 603, ((const char*) (
__func__)), "container->details->pending_icon_to_reveal->item == item"
); } while (0)
;
604
605 container->details->pending_icon_to_reveal = NULL((void*)0);
606}
607
608static CajaIcon*
609get_pending_icon_to_reveal (CajaIconContainer *container)
610{
611 return container->details->pending_icon_to_reveal;
612}
613
614static void
615set_pending_icon_to_reveal (CajaIconContainer *container, CajaIcon *icon)
616{
617 CajaIcon *old_icon;
618
619 old_icon = container->details->pending_icon_to_reveal;
620
621 if (icon == old_icon)
622 {
623 return;
624 }
625
626 if (old_icon != NULL((void*)0))
627 {
628 g_signal_handlers_disconnect_by_funcg_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_reveal_destroy_callback)))
, (container))
629 (old_icon->item,g_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_reveal_destroy_callback)))
, (container))
630 G_CALLBACK (pending_icon_to_reveal_destroy_callback),g_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_reveal_destroy_callback)))
, (container))
631 container)g_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_reveal_destroy_callback)))
, (container))
;
632 }
633
634 if (icon != NULL((void*)0))
635 {
636 g_signal_connect (icon->item, "destroy",g_signal_connect_data ((icon->item), ("destroy"), (((GCallback
) (pending_icon_to_reveal_destroy_callback))), (container), (
(void*)0), (GConnectFlags) 0)
637 G_CALLBACK (pending_icon_to_reveal_destroy_callback),g_signal_connect_data ((icon->item), ("destroy"), (((GCallback
) (pending_icon_to_reveal_destroy_callback))), (container), (
(void*)0), (GConnectFlags) 0)
638 container)g_signal_connect_data ((icon->item), ("destroy"), (((GCallback
) (pending_icon_to_reveal_destroy_callback))), (container), (
(void*)0), (GConnectFlags) 0)
;
639 }
640
641 container->details->pending_icon_to_reveal = icon;
642}
643
644static void
645item_get_canvas_bounds (EelCanvasItem *item,
646 EelIRect *bounds,
647 gboolean safety_pad)
648{
649 EelDRect world_rect;
650
651 eel_canvas_item_get_bounds (item,
652 &world_rect.x0,
653 &world_rect.y0,
654 &world_rect.x1,
655 &world_rect.y1);
656 eel_canvas_item_i2w (item->parent,
657 &world_rect.x0,
658 &world_rect.y0);
659 eel_canvas_item_i2w (item->parent,
660 &world_rect.x1,
661 &world_rect.y1);
662 if (safety_pad)
663 {
664 world_rect.x0 -= ICON_PAD_LEFT4 + ICON_PAD_RIGHT4;
665 world_rect.x1 += ICON_PAD_LEFT4 + ICON_PAD_RIGHT4;
666
667 world_rect.y0 -= ICON_PAD_TOP4 + ICON_PAD_BOTTOM4;
668 world_rect.y1 += ICON_PAD_TOP4 + ICON_PAD_BOTTOM4;
669 }
670
671 eel_canvas_w2c (item->canvas,
672 world_rect.x0,
673 world_rect.y0,
674 &bounds->x0,
675 &bounds->y0);
676 eel_canvas_w2c (item->canvas,
677 world_rect.x1,
678 world_rect.y1,
679 &bounds->x1,
680 &bounds->y1);
681}
682
683static void
684icon_get_row_and_column_bounds (CajaIconContainer *container,
685 CajaIcon *icon,
686 EelIRect *bounds,
687 gboolean safety_pad)
688{
689 GList *p;
690 EelIRect one_bounds;
691 CajaIcon *one_icon = NULL((void*)0);
692
693 item_get_canvas_bounds (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))), bounds, safety_pad);
694
695 for (p = container->details->icons; p != NULL((void*)0); p = p->next) {
696 one_icon = p->data;
697
698 if (icon == one_icon) {
699 continue;
700 }
701
702 if (compare_icons_horizontal (container, icon, one_icon) == 0) {
703 item_get_canvas_bounds (EEL_CANVAS_ITEM (one_icon->item)((((EelCanvasItem*) (void *) ((one_icon->item))))), &one_bounds, safety_pad);
704 bounds->x0 = MIN (bounds->x0, one_bounds.x0)(((bounds->x0) < (one_bounds.x0)) ? (bounds->x0) : (
one_bounds.x0))
;
705 bounds->x1 = MAX (bounds->x1, one_bounds.x1)(((bounds->x1) > (one_bounds.x1)) ? (bounds->x1) : (
one_bounds.x1))
;
706 }
707
708 if (compare_icons_vertical (container, icon, one_icon) == 0) {
709 item_get_canvas_bounds (EEL_CANVAS_ITEM (one_icon->item)((((EelCanvasItem*) (void *) ((one_icon->item))))), &one_bounds, safety_pad);
710 bounds->y0 = MIN (bounds->y0, one_bounds.y0)(((bounds->y0) < (one_bounds.y0)) ? (bounds->y0) : (
one_bounds.y0))
;
711 bounds->y1 = MAX (bounds->y1, one_bounds.y1)(((bounds->y1) > (one_bounds.y1)) ? (bounds->y1) : (
one_bounds.y1))
;
712 }
713 }
714
715
716}
717
718static void
719reveal_icon (CajaIconContainer *container,
720 CajaIcon *icon)
721{
722 GtkAllocation allocation;
723 GtkAdjustment *hadj, *vadj;
724 EelIRect bounds;
725
726 if (!icon_is_positioned (icon)) {
727 set_pending_icon_to_reveal (container, icon);
728 return;
729 }
730
731 set_pending_icon_to_reveal (container, NULL((void*)0));
732
733 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
734
735 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
736 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
737
738 if (caja_icon_container_is_auto_layout (container)) {
739 /* ensure that we reveal the entire row/column */
740 icon_get_row_and_column_bounds (container, icon, &bounds, TRUE(!(0)));
741 } else {
742 item_get_canvas_bounds (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))), &bounds, TRUE(!(0)));
743 }
744 if (bounds.y0 < gtk_adjustment_get_value (vadj)) {
745 gtk_adjustment_set_value (vadj, bounds.y0);
746 } else if (bounds.y1 > gtk_adjustment_get_value (vadj) + allocation.height) {
747 gtk_adjustment_set_value (vadj, bounds.y1 - allocation.height);
748 }
749
750 if (bounds.x0 < gtk_adjustment_get_value (hadj)) {
751 gtk_adjustment_set_value (hadj, bounds.x0);
752 } else if (bounds.x1 > gtk_adjustment_get_value (hadj) + allocation.width) {
753 if (bounds.x1 - allocation.width > bounds.x0) {
754 gtk_adjustment_set_value (hadj, bounds.x0);
755 } else {
756 gtk_adjustment_set_value (hadj, bounds.x1 - allocation.width);
757 }
758 }
759}
760
761static void
762process_pending_icon_to_reveal (CajaIconContainer *container)
763{
764 CajaIcon *pending_icon_to_reveal;
765
766 pending_icon_to_reveal = get_pending_icon_to_reveal (container);
767
768 if (pending_icon_to_reveal != NULL((void*)0)) {
769 reveal_icon (container, pending_icon_to_reveal);
770 }
771}
772
773static gboolean
774keyboard_icon_reveal_timeout_callback (gpointer data)
775{
776 CajaIconContainer *container;
777 CajaIcon *icon;
778
779 container = CAJA_ICON_CONTAINER (data)((((CajaIconContainer*) (void *) ((data)))));
780 icon = container->details->keyboard_icon_to_reveal;
781
782 g_assert (icon != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if (icon != ((void*)0)) _g_boolean_var_125 = 1; else _g_boolean_var_125
= 0; _g_boolean_var_125; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 782, ((const char*) (
__func__)), "icon != NULL"); } while (0)
;
783
784 /* Only reveal the icon if it's still the keyboard focus or if
785 * it's still selected. Someone originally thought we should
786 * cancel this reveal if the user manages to sneak a direct
787 * scroll in before the timeout fires, but we later realized
788 * this wouldn't actually be an improvement
789 * (see bugzilla.gnome.org 40612).
790 */
791 if (icon == container->details->keyboard_focus
792 || icon->is_selected) {
793 reveal_icon (container, icon);
794 }
795 container->details->keyboard_icon_reveal_timer_id = 0;
796
797 return FALSE(0);
798}
799
800static void
801unschedule_keyboard_icon_reveal (CajaIconContainer *container)
802{
803 CajaIconContainerDetails *details;
804
805 details = container->details;
806
807 if (details->keyboard_icon_reveal_timer_id != 0) {
808 g_source_remove (details->keyboard_icon_reveal_timer_id);
809 }
810}
811
812static void
813schedule_keyboard_icon_reveal (CajaIconContainer *container,
814 CajaIcon *icon)
815{
816 CajaIconContainerDetails *details;
817
818 details = container->details;
819
820 unschedule_keyboard_icon_reveal (container);
821
822 details->keyboard_icon_to_reveal = icon;
823 details->keyboard_icon_reveal_timer_id
824 = g_timeout_add (KEYBOARD_ICON_REVEAL_TIMEOUT10,
825 keyboard_icon_reveal_timeout_callback,
826 container);
827}
828
829static void
830clear_keyboard_focus (CajaIconContainer *container)
831{
832 if (container->details->keyboard_focus != NULL((void*)0))
833 {
834 eel_canvas_item_set (EEL_CANVAS_ITEM (container->details->keyboard_focus->item)((((EelCanvasItem*) (void *) ((container->details->keyboard_focus
->item)))))
,
835 "highlighted_as_keyboard_focus", 0,
836 NULL((void*)0));
837 }
838
839 container->details->keyboard_focus = NULL((void*)0);
840}
841
842static inline void
843emit_atk_focus_state_change (CajaIcon *icon, gboolean focused)
844{
845 AtkObject *atk_object = atk_gobject_accessible_for_object (G_OBJECT (icon->item)((((GObject*) (void *) ((icon->item))))));
846 atk_object_notify_state_change (atk_object, ATK_STATE_FOCUSED, focused);
847}
848
849/* Set @icon as the icon currently selected for keyboard operations. */
850static void
851set_keyboard_focus (CajaIconContainer *container,
852 CajaIcon *icon)
853{
854 g_assert (icon != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if (icon != ((void*)0)) _g_boolean_var_126 = 1; else _g_boolean_var_126
= 0; _g_boolean_var_126; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 854, ((const char*) (
__func__)), "icon != NULL"); } while (0)
;
855
856 if (icon == container->details->keyboard_focus)
857 {
858 return;
859 }
860
861 clear_keyboard_focus (container);
862
863 container->details->keyboard_focus = icon;
864
865 eel_canvas_item_set (EEL_CANVAS_ITEM (container->details->keyboard_focus->item)((((EelCanvasItem*) (void *) ((container->details->keyboard_focus
->item)))))
,
866 "highlighted_as_keyboard_focus", 1,
867 NULL((void*)0));
868
869 emit_atk_focus_state_change (icon, TRUE(!(0)));
870}
871
872static void
873set_keyboard_rubberband_start (CajaIconContainer *container,
874 CajaIcon *icon)
875{
876 container->details->keyboard_rubberband_start = icon;
877}
878
879static void
880clear_keyboard_rubberband_start (CajaIconContainer *container)
881{
882 container->details->keyboard_rubberband_start = NULL((void*)0);
883}
884
885/* carbon-copy of eel_canvas_group_bounds(), but
886 * for CajaIconContainerItems it returns the
887 * bounds for the “entire item”.
888 */
889static void
890get_icon_bounds_for_canvas_bounds (EelCanvasGroup *group,
891 double *x1, double *y1,
892 double *x2, double *y2,
893 CajaIconCanvasItemBoundsUsage usage)
894{
895 EelCanvasItem *child;
896 GList *list;
897 double tx1, ty1, tx2, ty2;
898 double minx, miny, maxx, maxy;
899 int set;
900
901 /* Get the bounds of the first visible item */
902
903 child = NULL((void*)0); /* Unnecessary but eliminates a warning. */
904
905 set = FALSE(0);
906
907 for (list = group->item_list; list; list = list->next)
908 {
909 child = list->data;
910
911 if (child->flags & EEL_CANVAS_ITEM_VISIBLE)
912 {
913 set = TRUE(!(0));
914 if (!CAJA_IS_ICON_CANVAS_ITEM (child)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(child)); GType __t = (caja_icon_canvas_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; }))))
||
915 usage == BOUNDS_USAGE_FOR_DISPLAY)
916 {
917 eel_canvas_item_get_bounds (child, &minx, &miny, &maxx, &maxy);
918 }
919 else if (usage == BOUNDS_USAGE_FOR_LAYOUT)
920 {
921 caja_icon_canvas_item_get_bounds_for_layout (CAJA_ICON_CANVAS_ITEM (child)((((CajaIconCanvasItem*) (void *) ((child))))),
922 &minx, &miny, &maxx, &maxy);
923 }
924 else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM)
925 {
926 caja_icon_canvas_item_get_bounds_for_entire_item (CAJA_ICON_CANVAS_ITEM (child)((((CajaIconCanvasItem*) (void *) ((child))))),
927 &minx, &miny, &maxx, &maxy);
928 }
929 else
930 {
931 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 931, ((const char*) (__func__)), ((void*)0)); } while (0)
;
932 }
933 break;
934 }
935 }
936
937 /* If there were no visible items, return an empty bounding box */
938
939 if (!set)
940 {
941 *x1 = *y1 = *x2 = *y2 = 0.0;
942 return;
943 }
944
945 /* Now we can grow the bounds using the rest of the items */
946
947 list = list->next;
948
949 for (; list; list = list->next)
950 {
951 child = list->data;
952
953 if (!(child->flags & EEL_CANVAS_ITEM_VISIBLE))
954 continue;
955
956 if (!CAJA_IS_ICON_CANVAS_ITEM (child)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(child)); GType __t = (caja_icon_canvas_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; }))))
||
957 usage == BOUNDS_USAGE_FOR_DISPLAY)
958 {
959 eel_canvas_item_get_bounds (child, &tx1, &ty1, &tx2, &ty2);
960 }
961 else if (usage == BOUNDS_USAGE_FOR_LAYOUT)
962 {
963 caja_icon_canvas_item_get_bounds_for_layout (CAJA_ICON_CANVAS_ITEM (child)((((CajaIconCanvasItem*) (void *) ((child))))),
964 &tx1, &ty1, &tx2, &ty2);
965 }
966 else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM)
967 {
968 caja_icon_canvas_item_get_bounds_for_entire_item (CAJA_ICON_CANVAS_ITEM (child)((((CajaIconCanvasItem*) (void *) ((child))))),
969 &tx1, &ty1, &tx2, &ty2);
970 }
971 else
972 {
973 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 973, ((const char*) (__func__)), ((void*)0)); } while (0)
;
974 }
975
976 if (tx1 < minx)
977 minx = tx1;
978
979 if (ty1 < miny)
980 miny = ty1;
981
982 if (tx2 > maxx)
983 maxx = tx2;
984
985 if (ty2 > maxy)
986 maxy = ty2;
987 }
988
989 /* Make the bounds be relative to our parent's coordinate system */
990
991 if (EEL_CANVAS_ITEM (group)((((EelCanvasItem*) (void *) ((group)))))->parent)
992 {
993 minx += group->xpos;
994 miny += group->ypos;
995 maxx += group->xpos;
996 maxy += group->ypos;
997 }
998
999 if (x1 != NULL((void*)0))
1000 {
1001 *x1 = minx;
1002 }
1003
1004 if (y1 != NULL((void*)0))
1005 {
1006 *y1 = miny;
1007 }
1008
1009 if (x2 != NULL((void*)0))
1010 {
1011 *x2 = maxx;
1012 }
1013
1014 if (y2 != NULL((void*)0))
1015 {
1016 *y2 = maxy;
1017 }
1018}
1019
1020static void
1021get_all_icon_bounds (CajaIconContainer *container,
1022 double *x1, double *y1,
1023 double *x2, double *y2,
1024 CajaIconCanvasItemBoundsUsage usage)
1025{
1026 /* FIXME bugzilla.gnome.org 42477: Do we have to do something about the rubberband
1027 * here? Any other non-icon items?
1028 */
1029 get_icon_bounds_for_canvas_bounds (EEL_CANVAS_GROUP (EEL_CANVAS (container)->root)((((EelCanvasGroup*) (void *) ((((((EelCanvas*) (void *) ((container
)))))->root)))))
,
1030 x1, y1, x2, y2, usage);
1031}
1032
1033/* Don't preserve visible white space the next time the scroll region
1034 * is recomputed when the container is not empty. */
1035void
1036caja_icon_container_reset_scroll_region (CajaIconContainer *container)
1037{
1038 container->details->reset_scroll_region_trigger = TRUE(!(0));
1039}
1040
1041/* Set a new scroll region without eliminating any of the currently-visible area. */
1042static void
1043canvas_set_scroll_region_include_visible_area (EelCanvas *canvas,
1044 double x1, double y1,
1045 double x2, double y2)
1046{
1047 double old_x1, old_y1, old_x2, old_y2;
1048 double old_scroll_x, old_scroll_y;
1049 double height, width;
1050 GtkAllocation allocation;
1051
1052 eel_canvas_get_scroll_region (canvas, &old_x1, &old_y1, &old_x2, &old_y2);
1053 gtk_widget_get_allocation (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))), &allocation);
1054
1055 width = (allocation.width) / canvas->pixels_per_unit;
1056 height = (allocation.height) / canvas->pixels_per_unit;
1057
1058 old_scroll_x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas)))))));
1059 old_scroll_y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas)))))));
1060
1061 x1 = MIN (x1, old_x1 + old_scroll_x)(((x1) < (old_x1 + old_scroll_x)) ? (x1) : (old_x1 + old_scroll_x
))
;
1062 y1 = MIN (y1, old_y1 + old_scroll_y)(((y1) < (old_y1 + old_scroll_y)) ? (y1) : (old_y1 + old_scroll_y
))
;
1063 x2 = MAX (x2, old_x1 + old_scroll_x + width)(((x2) > (old_x1 + old_scroll_x + width)) ? (x2) : (old_x1
+ old_scroll_x + width))
;
1064 y2 = MAX (y2, old_y1 + old_scroll_y + height)(((y2) > (old_y1 + old_scroll_y + height)) ? (y2) : (old_y1
+ old_scroll_y + height))
;
1065
1066 eel_canvas_set_scroll_region
1067 (canvas, x1, y1, x2, y2);
1068}
1069
1070void
1071caja_icon_container_update_scroll_region (CajaIconContainer *container)
1072{
1073 double x1, y1, x2, y2;
1074 double pixels_per_unit;
1075 GtkAdjustment *hadj, *vadj;
1076 float step_increment;
1077 gboolean reset_scroll_region;
1078 GtkAllocation allocation;
1079
1080 pixels_per_unit = EEL_CANVAS (container)((((EelCanvas*) (void *) ((container)))))->pixels_per_unit;
1081
1082 if (caja_icon_container_get_is_fixed_size (container))
1083 {
1084 /* Set the scroll region to the size of the container allocation */
1085 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1086 eel_canvas_set_scroll_region
1087 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
1088 (double) - container->details->left_margin / pixels_per_unit,
1089 (double) - container->details->top_margin / pixels_per_unit,
1090 ((double) (allocation.width - 1)
1091 - container->details->left_margin
1092 - container->details->right_margin)
1093 / pixels_per_unit,
1094 ((double) (allocation.height - 1)
1095 - container->details->top_margin
1096 - container->details->bottom_margin)
1097 / pixels_per_unit);
1098 return;
1099 }
1100
1101 reset_scroll_region = container->details->reset_scroll_region_trigger
1102 || caja_icon_container_is_empty (container)
1103 || caja_icon_container_is_auto_layout (container);
1104
1105 /* The trigger is only cleared when container is non-empty, so
1106 * callers can reliably reset the scroll region when an item
1107 * is added even if extraneous relayouts are called when the
1108 * window is still empty.
1109 */
1110 if (!caja_icon_container_is_empty (container))
1111 {
1112 container->details->reset_scroll_region_trigger = FALSE(0);
1113 }
1114
1115 get_all_icon_bounds (container, &x1, &y1, &x2, &y2, BOUNDS_USAGE_FOR_ENTIRE_ITEM);
1116
1117 /* Add border at the "end"of the layout (i.e. after the icons), to
1118 * ensure we get some space when scrolled to the end.
1119 * For horizontal layouts, we add a bottom border.
1120 * Vertical layout is used by the compact view so the end
1121 * depends on the RTL setting.
1122 */
1123 if (caja_icon_container_is_layout_vertical (container))
1124 {
1125 if (caja_icon_container_is_layout_rtl (container))
1126 {
1127 x1 -= ICON_PAD_LEFT4 + CONTAINER_PAD_LEFT4;
1128 }
1129 else
1130 {
1131 x2 += ICON_PAD_RIGHT4 + CONTAINER_PAD_RIGHT4;
1132 }
1133 }
1134 else
1135 {
1136 y2 += ICON_PAD_BOTTOM4 + CONTAINER_PAD_BOTTOM4;
1137 }
1138
1139 /* Auto-layout assumes a 0, 0 scroll origin and at least allocation->width.
1140 * Then we lay out to the right or to the left, so
1141 * x can be < 0 and > allocation */
1142 if (caja_icon_container_is_auto_layout (container))
1143 {
1144 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1145 x1 = MIN (x1, 0)(((x1) < (0)) ? (x1) : (0));
1146 x2 = MAX (x2, allocation.width / pixels_per_unit)(((x2) > (allocation.width / pixels_per_unit)) ? (x2) : (allocation
.width / pixels_per_unit))
;
1147 y1 = 0;
1148 }
1149 else
1150 {
1151 /* Otherwise we add the padding that is at the start of the
1152 layout */
1153 if (caja_icon_container_is_layout_rtl (container))
1154 {
1155 x2 += ICON_PAD_RIGHT4 + CONTAINER_PAD_RIGHT4;
1156 }
1157 else
1158 {
1159 x1 -= ICON_PAD_LEFT4 + CONTAINER_PAD_LEFT4;
1160 }
1161 y1 -= ICON_PAD_TOP4 + CONTAINER_PAD_TOP4;
1162 }
1163
1164 x2 -= 1;
1165 x2 = MAX(x1, x2)(((x1) > (x2)) ? (x1) : (x2));
1166
1167 y2 -= 1;
1168 y2 = MAX(y1, y2)(((y1) > (y2)) ? (y1) : (y2));
1169
1170 if (reset_scroll_region)
1171 {
1172 eel_canvas_set_scroll_region
1173 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
1174 x1, y1, x2, y2);
1175 }
1176 else
1177 {
1178 canvas_set_scroll_region_include_visible_area
1179 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
1180 x1, y1, x2, y2);
1181 }
1182
1183 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
1184 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
1185
1186 /* Scroll by 1/4 icon each time you click. */
1187 step_increment = caja_get_icon_size_for_zoom_level
1188 (container->details->zoom_level) / 4;
1189 if (gtk_adjustment_get_step_increment (hadj) != step_increment)
1190 {
1191 gtk_adjustment_set_step_increment (hadj, step_increment);
1192 }
1193 if (gtk_adjustment_get_step_increment (vadj) != step_increment)
1194 {
1195 gtk_adjustment_set_step_increment (vadj, step_increment);
1196 }
1197}
1198
1199static int
1200compare_icons (gconstpointer a, gconstpointer b, gpointer icon_container)
1201{
1202 CajaIconContainerClass *klass;
1203 const CajaIcon *icon_a, *icon_b;
1204
1205 icon_a = a;
1206 icon_b = b;
1207 klass = CAJA_ICON_CONTAINER_GET_CLASS (icon_container)((((CajaIconContainerClass*) (((GTypeInstance*) ((icon_container
)))->g_class))))
;
1208
1209 return klass->compare_icons (icon_container, icon_a->data, icon_b->data);
1210}
1211
1212static void
1213sort_icons (CajaIconContainer *container,
1214 GList **icons)
1215{
1216 CajaIconContainerClass *klass;
1217
1218 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
1219 g_assert (klass->compare_icons != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if (klass->compare_icons != ((void*)0)) _g_boolean_var_127
= 1; else _g_boolean_var_127 = 0; _g_boolean_var_127; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1219, ((const char*) (__func__)), "klass->compare_icons != NULL"
); } while (0)
;
1220
1221 *icons = g_list_sort_with_data (*icons, compare_icons, container);
1222}
1223
1224static void
1225resort (CajaIconContainer *container)
1226{
1227 sort_icons (container, &container->details->icons);
1228}
1229
1230typedef struct
1231{
1232 double width;
1233 double height;
1234 double x_offset;
1235 double y_offset;
1236} IconPositions;
1237
1238static void
1239lay_down_one_line (CajaIconContainer *container,
1240 GList *line_start,
1241 GList *line_end,
1242 double y,
1243 double max_height,
1244 GArray *positions,
1245 gboolean whole_text)
1246{
1247 GList *p;
1248 double x, y_offset;
1249 IconPositions *position;
1250 int i;
1251 gboolean is_rtl;
1252 CajaIcon *icon = NULL((void*)0);
1253
1254 is_rtl = caja_icon_container_is_layout_rtl (container);
1255
1256 /* Lay out the icons along the baseline. */
1257 x = ICON_PAD_LEFT4;
1258 i = 0;
1259 for (p = line_start; p != line_end; p = p->next)
1260 {
1261 icon = p->data;
1262
1263 position = &g_array_index (positions, IconPositions, i++)(((IconPositions*) (void *) (positions)->data) [(i++)]);
1264
1265 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
1266 {
1267 y_offset = (max_height - position->height) / 2;
1268 }
1269 else
1270 {
1271 y_offset = position->y_offset;
1272 }
1273
1274 icon_set_position
1275 (icon,
1276 is_rtl ? get_mirror_x_position (container, icon, x + position->x_offset) : x + position->x_offset,
1277 y + y_offset);
1278 caja_icon_canvas_item_set_entire_text (icon->item, whole_text);
1279
1280 icon->saved_ltr_x = is_rtl ? get_mirror_x_position (container, icon, icon->x) : icon->x;
1281
1282 x += position->width;
1283 }
1284}
1285
1286static void
1287lay_down_one_column (CajaIconContainer *container,
1288 GList *line_start,
1289 GList *line_end,
1290 double x,
1291 double y_start,
1292 double y_iter,
1293 GArray *positions)
1294{
1295 GList *p;
1296 double y;
1297 int i;
1298 gboolean is_rtl;
1299 IconPositions *position = NULL((void*)0);
1300 CajaIcon *icon = NULL((void*)0);
1301
1302 is_rtl = caja_icon_container_is_layout_rtl (container);
1303
1304 /* Lay out the icons along the baseline. */
1305 y = y_start;
1306 i = 0;
1307 for (p = line_start; p != line_end; p = p->next)
1308 {
1309 icon = p->data;
1310
1311 position = &g_array_index (positions, IconPositions, i++)(((IconPositions*) (void *) (positions)->data) [(i++)]);
1312
1313 icon_set_position
1314 (icon,
1315 is_rtl ? get_mirror_x_position (container, icon, x + position->x_offset) : x + position->x_offset,
1316 y + position->y_offset);
1317
1318 icon->saved_ltr_x = is_rtl ? get_mirror_x_position (container, icon, icon->x) : icon->x;
1319
1320 y += y_iter;
1321 }
1322}
1323
1324static void
1325lay_down_icons_horizontal (CajaIconContainer *container,
1326 GList *icons,
1327 double start_y)
1328{
1329 GList *p, *line_start;
1330 CajaIcon *icon;
1331 double canvas_width, y;
1332 EelDRect bounds;
1333 EelDRect icon_bounds;
1334 EelDRect text_bounds;
1335 double max_height_above, max_height_below;
1336 double line_width;
1337 gboolean gridded_layout;
1338 double grid_width;
1339 double max_text_width, max_icon_width;
1340 int icon_width;
1341 int i;
1342 GtkAllocation allocation;
1343 GArray *positions;
1344 IconPositions *position = NULL((void*)0);
1345
1346 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_128 = 1; else _g_boolean_var_128 =
0; _g_boolean_var_128; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 1346, ((const char*)
(__func__)), "CAJA_IS_ICON_CONTAINER (container)"); } while (
0)
;
1347
1348 if (icons == NULL((void*)0))
1349 {
1350 return;
1351 }
1352
1353 positions = g_array_new (FALSE(0), FALSE(0), sizeof (IconPositions));
1354 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1355
1356 /* Lay out icons a line at a time. */
1357 canvas_width = CANVAS_WIDTH(container, allocation)((allocation.width - container->details->left_margin - container
->details->right_margin) / ((((EelCanvas*) (void *) ((container
)))))->pixels_per_unit)
;
1358 max_icon_width = max_text_width = 0.0;
1359
1360 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
1361 {
1362 /* Would it be worth caching these bounds for the next loop? */
1363 for (p = icons; p != NULL((void*)0); p = p->next)
1364 {
1365 icon = p->data;
1366
1367 icon_bounds = caja_icon_canvas_item_get_icon_rectangle (icon->item);
1368 max_icon_width = MAX (max_icon_width, ceil (icon_bounds.x1 - icon_bounds.x0))(((max_icon_width) > (ceil (icon_bounds.x1 - icon_bounds.x0
))) ? (max_icon_width) : (ceil (icon_bounds.x1 - icon_bounds.
x0)))
;
1369
1370 text_bounds = caja_icon_canvas_item_get_text_rectangle (icon->item, TRUE(!(0)));
1371 max_text_width = MAX (max_text_width, ceil (text_bounds.x1 - text_bounds.x0))(((max_text_width) > (ceil (text_bounds.x1 - text_bounds.x0
))) ? (max_text_width) : (ceil (text_bounds.x1 - text_bounds.
x0)))
;
1372 }
1373
1374 grid_width = max_icon_width + max_text_width + ICON_PAD_LEFT4 + ICON_PAD_RIGHT4;
1375 }
1376 else
1377 {
1378 int num_columns;
1379
1380 num_columns = floor(canvas_width / STANDARD_ICON_GRID_WIDTH155);
1381 num_columns = fmax(num_columns, 1);
1382 /* Minimum of one column */
1383 grid_width = canvas_width / num_columns - 1;
1384 /* -1 prevents jitter */
1385 }
1386
1387 gridded_layout = !caja_icon_container_is_tighter_layout (container);
1388
1389 line_width = container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE ? ICON_PAD_LEFT4 : 0;
1390 line_start = icons;
1391 y = start_y + CONTAINER_PAD_TOP4;
1392 i = 0;
1393
1394 max_height_above = 0;
1395 max_height_below = 0;
1396 for (p = icons; p != NULL((void*)0); p = p->next)
1397 {
1398 double height_above, height_below;
1399
1400 icon = p->data;
1401
1402 /* Assume it's only one level hierarchy to avoid costly affine calculations */
1403 caja_icon_canvas_item_get_bounds_for_layout (icon->item,
1404 &bounds.x0, &bounds.y0,
1405 &bounds.x1, &bounds.y1);
1406
1407 icon_bounds = caja_icon_canvas_item_get_icon_rectangle (icon->item);
1408 text_bounds = caja_icon_canvas_item_get_text_rectangle (icon->item, TRUE(!(0)));
1409
1410 if (gridded_layout)
1411 {
1412 icon_width = ceil ((bounds.x1 - bounds.x0)/grid_width) * grid_width;
1413
1414
1415 }
1416 else
1417 {
1418 icon_width = (bounds.x1 - bounds.x0) + ICON_PAD_RIGHT4 + 8; /* 8 pixels extra for fancy selection box */
1419 }
1420
1421 /* Calculate size above/below baseline */
1422 height_above = icon_bounds.y1 - bounds.y0;
1423 height_below = bounds.y1 - icon_bounds.y1;
1424
1425 /* If this icon doesn't fit, it's time to lay out the line that's queued up. */
1426 if (line_start != p && line_width + icon_width >= canvas_width )
1427 {
1428 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
1429 {
1430 y += ICON_PAD_TOP4;
1431 }
1432 else
1433 {
1434 /* Advance to the baseline. */
1435 y += ICON_PAD_TOP4 + max_height_above;
1436 }
1437
1438 lay_down_one_line (container, line_start, p, y, max_height_above, positions, FALSE(0));
1439
1440 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
1441 {
1442 y += max_height_above + max_height_below + ICON_PAD_BOTTOM4;
1443 }
1444 else
1445 {
1446 /* Advance to next line. */
1447 y += max_height_below + ICON_PAD_BOTTOM4;
1448 }
1449
1450 line_width = container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE ? ICON_PAD_LEFT4 : 0;
1451 line_start = p;
1452 i = 0;
1453
1454 max_height_above = height_above;
1455 max_height_below = height_below;
1456 }
1457 else
1458 {
1459 if (height_above > max_height_above)
1460 {
1461 max_height_above = height_above;
1462 }
1463 if (height_below > max_height_below)
1464 {
1465 max_height_below = height_below;
1466 }
1467 }
1468
1469 g_array_set_size (positions, i + 1);
1470 position = &g_array_index (positions, IconPositions, i++)(((IconPositions*) (void *) (positions)->data) [(i++)]);
1471 position->width = icon_width;
1472 position->height = icon_bounds.y1 - icon_bounds.y0;
1473
1474 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
1475 {
1476 if (gridded_layout)
1477 {
1478 position->x_offset = max_icon_width + ICON_PAD_LEFT4 + ICON_PAD_RIGHT4 - (icon_bounds.x1 - icon_bounds.x0);
1479 }
1480 else
1481 {
1482 position->x_offset = icon_width - ((icon_bounds.x1 - icon_bounds.x0) + (text_bounds.x1 - text_bounds.x0));
1483 }
1484 position->y_offset = 0;
1485 }
1486 else
1487 {
1488 position->x_offset = (icon_width - (icon_bounds.x1 - icon_bounds.x0)) / 2;
1489 position->y_offset = icon_bounds.y0 - icon_bounds.y1;
1490 }
1491
1492 /* Add this icon. */
1493 line_width += icon_width;
1494 }
1495
1496 /* Lay down that last line of icons. */
1497 if (line_start != NULL((void*)0))
1498 {
1499 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
1500 {
1501 y += ICON_PAD_TOP4;
1502 }
1503 else
1504 {
1505 /* Advance to the baseline. */
1506 y += ICON_PAD_TOP4 + max_height_above;
1507 }
1508
1509 lay_down_one_line (container, line_start, NULL((void*)0), y, max_height_above, positions, TRUE(!(0)));
1510
1511 /* Advance to next line. */
1512 y += max_height_below + ICON_PAD_BOTTOM4;
Value stored to 'y' is never read
1513 }
1514
1515 g_array_free (positions, TRUE(!(0)));
1516}
1517
1518static void
1519get_max_icon_dimensions (GList *icon_start,
1520 GList *icon_end,
1521 double *max_icon_width,
1522 double *max_icon_height,
1523 double *max_text_width,
1524 double *max_text_height,
1525 double *max_bounds_height)
1526{
1527 EelDRect icon_bounds;
1528 EelDRect text_bounds;
1529 GList *p;
1530 double y1, y2;
1531 CajaIcon *icon = NULL((void*)0);
1532
1533 *max_icon_width = *max_text_width = 0.0;
1534 *max_icon_height = *max_text_height = 0.0;
1535 *max_bounds_height = 0.0;
1536
1537 /* Would it be worth caching these bounds for the next loop? */
1538 for (p = icon_start; p != icon_end; p = p->next)
1539 {
1540 icon = p->data;
1541
1542 icon_bounds = caja_icon_canvas_item_get_icon_rectangle (icon->item);
1543 *max_icon_width = MAX (*max_icon_width, ceil (icon_bounds.x1 - icon_bounds.x0))(((*max_icon_width) > (ceil (icon_bounds.x1 - icon_bounds.
x0))) ? (*max_icon_width) : (ceil (icon_bounds.x1 - icon_bounds
.x0)))
;
1544 *max_icon_height = MAX (*max_icon_height, ceil (icon_bounds.y1 - icon_bounds.y0))(((*max_icon_height) > (ceil (icon_bounds.y1 - icon_bounds
.y0))) ? (*max_icon_height) : (ceil (icon_bounds.y1 - icon_bounds
.y0)))
;
1545
1546 text_bounds = caja_icon_canvas_item_get_text_rectangle (icon->item, TRUE(!(0)));
1547 *max_text_width = MAX (*max_text_width, ceil (text_bounds.x1 - text_bounds.x0))(((*max_text_width) > (ceil (text_bounds.x1 - text_bounds.
x0))) ? (*max_text_width) : (ceil (text_bounds.x1 - text_bounds
.x0)))
;
1548 *max_text_height = MAX (*max_text_height, ceil (text_bounds.y1 - text_bounds.y0))(((*max_text_height) > (ceil (text_bounds.y1 - text_bounds
.y0))) ? (*max_text_height) : (ceil (text_bounds.y1 - text_bounds
.y0)))
;
1549
1550 caja_icon_canvas_item_get_bounds_for_layout (icon->item,
1551 NULL((void*)0), &y1,
1552 NULL((void*)0), &y2);
1553 *max_bounds_height = MAX (*max_bounds_height, y2 - y1)(((*max_bounds_height) > (y2 - y1)) ? (*max_bounds_height)
: (y2 - y1))
;
1554 }
1555}
1556
1557/* column-wise layout. At the moment, this only works with label-beside-icon (used by "Compact View"). */
1558static void
1559lay_down_icons_vertical (CajaIconContainer *container,
1560 GList *icons,
1561 double start_y)
1562{
1563 GList *p, *line_start;
1564 double x, canvas_height;
1565 GArray *positions;
1566 IconPositions *position;
1567 EelDRect icon_bounds;
1568 EelDRect text_bounds;
1569 GtkAllocation allocation;
1570
1571 double line_height;
1572
1573 double max_height;
1574 double max_height_with_borders;
1575 double max_width;
1576 double max_width_in_column;
1577
1578 double max_bounds_height;
1579 double max_bounds_height_with_borders;
1580
1581 double max_text_width, max_icon_width;
1582 double max_text_height, max_icon_height;
1583 int i;
1584
1585 CajaIcon *icon = NULL((void*)0);
1586
1587 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_129 = 1; else _g_boolean_var_129 =
0; _g_boolean_var_129; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 1587, ((const char*)
(__func__)), "CAJA_IS_ICON_CONTAINER (container)"); } while (
0)
;
1588 g_assert (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE
) _g_boolean_var_130 = 1; else _g_boolean_var_130 = 0; _g_boolean_var_130
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1588, ((const char*) (__func__)), "container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE"
); } while (0)
;
1589
1590 if (icons == NULL((void*)0))
1591 {
1592 return;
1593 }
1594
1595 positions = g_array_new (FALSE(0), FALSE(0), sizeof (IconPositions));
1596 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1597
1598 /* Lay out icons a column at a time. */
1599 canvas_height = CANVAS_HEIGHT(container, allocation)((allocation.height - container->details->top_margin - container
->details->bottom_margin) / ((((EelCanvas*) (void *) ((
container)))))->pixels_per_unit)
;
1600
1601 max_icon_width = max_text_width = 0.0;
1602 max_icon_height = max_text_height = 0.0;
1603 max_bounds_height = 0.0;
1604
1605 get_max_icon_dimensions (icons, NULL((void*)0),
1606 &max_icon_width, &max_icon_height,
1607 &max_text_width, &max_text_height,
1608 &max_bounds_height);
1609
1610 max_width = max_icon_width + max_text_width;
1611 max_height = MAX (max_icon_height, max_text_height)(((max_icon_height) > (max_text_height)) ? (max_icon_height
) : (max_text_height))
;
1612 max_height_with_borders = ICON_PAD_TOP4 + max_height;
1613
1614 max_bounds_height_with_borders = ICON_PAD_TOP4 + max_bounds_height;
1615
1616 line_height = ICON_PAD_TOP4;
1617 line_start = icons;
1618 x = 0;
1619 i = 0;
1620
1621 max_width_in_column = 0.0;
1622
1623 for (p = icons; p != NULL((void*)0); p = p->next)
1624 {
1625 int height;
1626
1627 icon = p->data;
1628
1629 /* If this icon doesn't fit, it's time to lay out the column that's queued up. */
1630
1631 /* We use the bounds height here, since for wrapping we also want to consider
1632 * overlapping emblems at the bottom. We may wrap a little bit too early since
1633 * the icon with the max. bounds height may actually not be in the last row, but
1634 * it is better than visual glitches
1635 */
1636 if (line_start != p && line_height + (max_bounds_height_with_borders-1) >= canvas_height )
1637 {
1638 x += ICON_PAD_LEFT4;
1639
1640 /* correctly set (per-column) width */
1641 if (!container->details->all_columns_same_width)
1642 {
1643 for (i = 0; i < (int) positions->len; i++)
1644 {
1645 position = &g_array_index (positions, IconPositions, i)(((IconPositions*) (void *) (positions)->data) [(i)]);
1646 position->width = max_width_in_column;
1647 }
1648 }
1649
1650 lay_down_one_column (container, line_start, p, x, CONTAINER_PAD_TOP4, max_height_with_borders, positions);
1651
1652 /* Advance to next column. */
1653 if (container->details->all_columns_same_width)
1654 {
1655 x += max_width + ICON_PAD_RIGHT4;
1656 }
1657 else
1658 {
1659 x += max_width_in_column + ICON_PAD_RIGHT4;
1660 }
1661
1662 line_height = ICON_PAD_TOP4;
1663 line_start = p;
1664 i = 0;
1665
1666 max_width_in_column = 0;
1667 }
1668
1669 icon_bounds = caja_icon_canvas_item_get_icon_rectangle (icon->item);
1670 text_bounds = caja_icon_canvas_item_get_text_rectangle (icon->item, TRUE(!(0)));
1671
1672 max_width_in_column = MAX (max_width_in_column,(((max_width_in_column) > (ceil (icon_bounds.x1 - icon_bounds
.x0) + ceil (text_bounds.x1 - text_bounds.x0))) ? (max_width_in_column
) : (ceil (icon_bounds.x1 - icon_bounds.x0) + ceil (text_bounds
.x1 - text_bounds.x0)))
1673 ceil (icon_bounds.x1 - icon_bounds.x0) +(((max_width_in_column) > (ceil (icon_bounds.x1 - icon_bounds
.x0) + ceil (text_bounds.x1 - text_bounds.x0))) ? (max_width_in_column
) : (ceil (icon_bounds.x1 - icon_bounds.x0) + ceil (text_bounds
.x1 - text_bounds.x0)))
1674 ceil (text_bounds.x1 - text_bounds.x0))(((max_width_in_column) > (ceil (icon_bounds.x1 - icon_bounds
.x0) + ceil (text_bounds.x1 - text_bounds.x0))) ? (max_width_in_column
) : (ceil (icon_bounds.x1 - icon_bounds.x0) + ceil (text_bounds
.x1 - text_bounds.x0)))
;
1675
1676 g_array_set_size (positions, i + 1);
1677 position = &g_array_index (positions, IconPositions, i++)(((IconPositions*) (void *) (positions)->data) [(i++)]);
1678 if (container->details->all_columns_same_width)
1679 {
1680 position->width = max_width;
1681 }
1682 position->height = max_height;
1683 position->y_offset = ICON_PAD_TOP4;
1684 position->x_offset = ICON_PAD_LEFT4;
1685
1686 position->x_offset += max_icon_width - ceil (icon_bounds.x1 - icon_bounds.x0);
1687
1688 height = MAX (ceil (icon_bounds.y1 - icon_bounds.y0), ceil(text_bounds.y1 - text_bounds.y0))(((ceil (icon_bounds.y1 - icon_bounds.y0)) > (ceil(text_bounds
.y1 - text_bounds.y0))) ? (ceil (icon_bounds.y1 - icon_bounds
.y0)) : (ceil(text_bounds.y1 - text_bounds.y0)))
;
1689 position->y_offset += (max_height - height) / 2;
1690
1691 /* Add this icon. */
1692 line_height += max_height_with_borders;
1693 }
1694
1695 /* Lay down that last column of icons. */
1696 if (line_start != NULL((void*)0))
1697 {
1698 x += ICON_PAD_LEFT4;
1699 lay_down_one_column (container, line_start, NULL((void*)0), x, CONTAINER_PAD_TOP4, max_height_with_borders, positions);
1700 }
1701
1702 g_array_free (positions, TRUE(!(0)));
1703}
1704
1705static void
1706snap_position (CajaIconContainer *container,
1707 CajaIcon *icon,
1708 int *x, int *y)
1709{
1710 int center_x;
1711 int baseline_y;
1712 int icon_width;
1713 int icon_height;
1714 int total_width;
1715 int total_height;
1716 EelDRect icon_position;
1717 GtkAllocation allocation;
1718
1719 icon_position = caja_icon_canvas_item_get_icon_rectangle (icon->item);
1720 icon_width = icon_position.x1 - icon_position.x0;
1721 icon_height = icon_position.y1 - icon_position.y0;
1722
1723 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1724 total_width = CANVAS_WIDTH (container, allocation)((allocation.width - container->details->left_margin - container
->details->right_margin) / ((((EelCanvas*) (void *) ((container
)))))->pixels_per_unit)
;
1725 total_height = CANVAS_HEIGHT (container, allocation)((allocation.height - container->details->top_margin - container
->details->bottom_margin) / ((((EelCanvas*) (void *) ((
container)))))->pixels_per_unit)
;
1726
1727 if (caja_icon_container_is_layout_rtl (container))
1728 *x = get_mirror_x_position (container, icon, *x);
1729
1730 if (*x + icon_width / 2 < DESKTOP_PAD_HORIZONTAL10 + SNAP_SIZE_X78)
1731 {
1732 *x = DESKTOP_PAD_HORIZONTAL10 + SNAP_SIZE_X78 - icon_width / 2;
1733 }
1734
1735 if (*x + icon_width / 2 > total_width - (DESKTOP_PAD_HORIZONTAL10 + SNAP_SIZE_X78))
1736 {
1737 *x = total_width - (DESKTOP_PAD_HORIZONTAL10 + SNAP_SIZE_X78 + (icon_width / 2));
1738 }
1739
1740 if (*y + icon_height < DESKTOP_PAD_VERTICAL10 + SNAP_SIZE_Y20)
1741 {
1742 *y = DESKTOP_PAD_VERTICAL10 + SNAP_SIZE_Y20 - icon_height;
1743 }
1744
1745 if (*y + icon_height > total_height - (DESKTOP_PAD_VERTICAL10 + SNAP_SIZE_Y20))
1746 {
1747 *y = total_height - (DESKTOP_PAD_VERTICAL10 + SNAP_SIZE_Y20 + (icon_height / 2));
1748 }
1749
1750 center_x = *x + icon_width / 2;
1751 *x = SNAP_NEAREST_HORIZONTAL (center_x)((eel_round ((double)((center_x) - 10) / 78) * 78) + 10) - (icon_width / 2);
1752 if (caja_icon_container_is_layout_rtl (container))
1753 {
1754 *x = get_mirror_x_position (container, icon, *x);
1755 }
1756
1757
1758 /* Find the grid position vertically and place on the proper baseline */
1759 baseline_y = *y + icon_height;
1760 baseline_y = SNAP_NEAREST_VERTICAL (baseline_y)((eel_round ((double)((baseline_y) - 10) / 20) * 20) + 10);
1761 *y = baseline_y - icon_height;
1762}
1763
1764static int
1765compare_icons_by_position (gconstpointer a, gconstpointer b)
1766{
1767 CajaIcon *icon_a, *icon_b;
1768 int x1, y1, x2, y2;
1769 int center_a;
1770 int center_b;
1771
1772 icon_a = (CajaIcon*)a;
1773 icon_b = (CajaIcon*)b;
1774
1775 icon_get_bounding_box (icon_a, &x1, &y1, &x2, &y2,
1776 BOUNDS_USAGE_FOR_DISPLAY);
1777 center_a = x1 + (x2 - x1) / 2;
1778 icon_get_bounding_box (icon_b, &x1, &y1, &x2, &y2,
1779 BOUNDS_USAGE_FOR_DISPLAY);
1780 center_b = x1 + (x2 - x1) / 2;
1781
1782 return center_a == center_b ?
1783 icon_a->y - icon_b->y :
1784 center_a - center_b;
1785}
1786
1787static PlacementGrid *
1788placement_grid_new (CajaIconContainer *container, gboolean tight)
1789{
1790 PlacementGrid *grid;
1791 int width, height;
1792 int num_columns;
1793 int num_rows;
1794 int i;
1795 GtkAllocation allocation;
1796
1797 /* Get container dimensions */
1798 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1799 width = CANVAS_WIDTH(container, allocation)((allocation.width - container->details->left_margin - container
->details->right_margin) / ((((EelCanvas*) (void *) ((container
)))))->pixels_per_unit)
;
1800 height = CANVAS_HEIGHT(container, allocation)((allocation.height - container->details->top_margin - container
->details->bottom_margin) / ((((EelCanvas*) (void *) ((
container)))))->pixels_per_unit)
;
1801
1802 num_columns = width / SNAP_SIZE_X78;
1803 num_rows = height / SNAP_SIZE_Y20;
1804
1805 if (num_columns == 0 || num_rows == 0)
1806 {
1807 return NULL((void*)0);
1808 }
1809
1810 grid = g_new0 (PlacementGrid, 1)(PlacementGrid *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (PlacementGrid); 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; }))
;
1811 grid->tight = tight;
1812 grid->num_columns = num_columns;
1813 grid->num_rows = num_rows;
1814
1815 grid->grid_memory = g_new0 (int, (num_rows * num_columns))(int *) (__extension__ ({ gsize __n = (gsize) ((num_rows * num_columns
)); gsize __s = sizeof (int); 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; }))
;
1816 grid->icon_grid = g_new0 (int *, num_columns)(int * *) (__extension__ ({ gsize __n = (gsize) (num_columns)
; gsize __s = sizeof (int *); 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; }))
;
1817
1818 for (i = 0; i < num_columns; i++)
1819 {
1820 grid->icon_grid[i] = grid->grid_memory + (i * num_rows);
1821 }
1822
1823 return grid;
1824}
1825
1826static void
1827placement_grid_free (PlacementGrid *grid)
1828{
1829 g_free (grid->icon_grid);
1830 g_free (grid->grid_memory);
1831 g_free (grid);
1832}
1833
1834static gboolean
1835placement_grid_position_is_free (PlacementGrid *grid, EelIRect pos)
1836{
1837 int x, y;
1838
1839 g_assert (pos.x0 >= 0 && pos.x0 < grid->num_columns)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if (pos.x0 >= 0 && pos.x0 < grid->num_columns
) _g_boolean_var_131 = 1; else _g_boolean_var_131 = 0; _g_boolean_var_131
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1839, ((const char*) (__func__)), "pos.x0 >= 0 && pos.x0 < grid->num_columns"
); } while (0)
;
1840 g_assert (pos.y0 >= 0 && pos.y0 < grid->num_rows)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if (pos.y0 >= 0 && pos.y0 < grid->num_rows
) _g_boolean_var_132 = 1; else _g_boolean_var_132 = 0; _g_boolean_var_132
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1840, ((const char*) (__func__)), "pos.y0 >= 0 && pos.y0 < grid->num_rows"
); } while (0)
;
1841 g_assert (pos.x1 >= 0 && pos.x1 < grid->num_columns)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if (pos.x1 >= 0 && pos.x1 < grid->num_columns
) _g_boolean_var_133 = 1; else _g_boolean_var_133 = 0; _g_boolean_var_133
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1841, ((const char*) (__func__)), "pos.x1 >= 0 && pos.x1 < grid->num_columns"
); } while (0)
;
1842 g_assert (pos.y1 >= 0 && pos.y1 < grid->num_rows)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (pos.y1 >= 0 && pos.y1 < grid->num_rows
) _g_boolean_var_134 = 1; else _g_boolean_var_134 = 0; _g_boolean_var_134
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1842, ((const char*) (__func__)), "pos.y1 >= 0 && pos.y1 < grid->num_rows"
); } while (0)
;
1843
1844 for (x = pos.x0; x <= pos.x1; x++)
1845 {
1846 for (y = pos.y0; y <= pos.y1; y++)
1847 {
1848 if (grid->icon_grid[x][y] != 0)
1849 {
1850 return FALSE(0);
1851 }
1852 }
1853 }
1854
1855 return TRUE(!(0));
1856}
1857
1858static void
1859placement_grid_mark (PlacementGrid *grid, EelIRect pos)
1860{
1861 int x, y;
1862
1863 g_assert (pos.x0 >= 0 && pos.x0 < grid->num_columns)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if (pos.x0 >= 0 && pos.x0 < grid->num_columns
) _g_boolean_var_135 = 1; else _g_boolean_var_135 = 0; _g_boolean_var_135
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1863, ((const char*) (__func__)), "pos.x0 >= 0 && pos.x0 < grid->num_columns"
); } while (0)
;
1864 g_assert (pos.y0 >= 0 && pos.y0 < grid->num_rows)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if (pos.y0 >= 0 && pos.y0 < grid->num_rows
) _g_boolean_var_136 = 1; else _g_boolean_var_136 = 0; _g_boolean_var_136
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1864, ((const char*) (__func__)), "pos.y0 >= 0 && pos.y0 < grid->num_rows"
); } while (0)
;
1865 g_assert (pos.x1 >= 0 && pos.x1 < grid->num_columns)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if (pos.x1 >= 0 && pos.x1 < grid->num_columns
) _g_boolean_var_137 = 1; else _g_boolean_var_137 = 0; _g_boolean_var_137
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1865, ((const char*) (__func__)), "pos.x1 >= 0 && pos.x1 < grid->num_columns"
); } while (0)
;
1866 g_assert (pos.y1 >= 0 && pos.y1 < grid->num_rows)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if (pos.y1 >= 0 && pos.y1 < grid->num_rows
) _g_boolean_var_138 = 1; else _g_boolean_var_138 = 0; _g_boolean_var_138
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 1866, ((const char*) (__func__)), "pos.y1 >= 0 && pos.y1 < grid->num_rows"
); } while (0)
;
1867
1868 for (x = pos.x0; x <= pos.x1; x++)
1869 {
1870 for (y = pos.y0; y <= pos.y1; y++)
1871 {
1872 grid->icon_grid[x][y] = 1;
1873 }
1874 }
1875}
1876
1877static void
1878canvas_position_to_grid_position (PlacementGrid *grid,
1879 EelIRect canvas_position,
1880 EelIRect *grid_position)
1881{
1882 /* The first causes minimal moving around during a snap, but
1883 * can end up with partially overlapping icons. The second one won't
1884 * allow any overlapping, but can cause more movement to happen
1885 * during a snap. */
1886 if (grid->tight)
1887 {
1888 grid_position->x0 = ceil ((double)(canvas_position.x0 - DESKTOP_PAD_HORIZONTAL10) / SNAP_SIZE_X78);
1889 grid_position->y0 = ceil ((double)(canvas_position.y0 - DESKTOP_PAD_VERTICAL10) / SNAP_SIZE_Y20);
1890 grid_position->x1 = floor ((double)(canvas_position.x1 - DESKTOP_PAD_HORIZONTAL10) / SNAP_SIZE_X78);
1891 grid_position->y1 = floor ((double)(canvas_position.y1 - DESKTOP_PAD_VERTICAL10) / SNAP_SIZE_Y20);
1892 }
1893 else
1894 {
1895 grid_position->x0 = floor ((double)(canvas_position.x0 - DESKTOP_PAD_HORIZONTAL10) / SNAP_SIZE_X78);
1896 grid_position->y0 = floor ((double)(canvas_position.y0 - DESKTOP_PAD_VERTICAL10) / SNAP_SIZE_Y20);
1897 grid_position->x1 = floor ((double)(canvas_position.x1 - DESKTOP_PAD_HORIZONTAL10) / SNAP_SIZE_X78);
1898 grid_position->y1 = floor ((double)(canvas_position.y1 - DESKTOP_PAD_VERTICAL10) / SNAP_SIZE_Y20);
1899 }
1900
1901 grid_position->x0 = CLAMP (grid_position->x0, 0, grid->num_columns - 1)(((grid_position->x0) > (grid->num_columns - 1)) ? (
grid->num_columns - 1) : (((grid_position->x0) < (0)
) ? (0) : (grid_position->x0)))
;
1902 grid_position->y0 = CLAMP (grid_position->y0, 0, grid->num_rows - 1)(((grid_position->y0) > (grid->num_rows - 1)) ? (grid
->num_rows - 1) : (((grid_position->y0) < (0)) ? (0)
: (grid_position->y0)))
;
1903 grid_position->x1 = CLAMP (grid_position->x1, grid_position->x0, grid->num_columns - 1)(((grid_position->x1) > (grid->num_columns - 1)) ? (
grid->num_columns - 1) : (((grid_position->x1) < (grid_position
->x0)) ? (grid_position->x0) : (grid_position->x1)))
;
1904 grid_position->y1 = CLAMP (grid_position->y1, grid_position->y0, grid->num_rows - 1)(((grid_position->y1) > (grid->num_rows - 1)) ? (grid
->num_rows - 1) : (((grid_position->y1) < (grid_position
->y0)) ? (grid_position->y0) : (grid_position->y1)))
;
1905}
1906
1907static void
1908placement_grid_mark_icon (PlacementGrid *grid, CajaIcon *icon)
1909{
1910 EelIRect icon_pos;
1911 EelIRect grid_pos;
1912
1913 icon_get_bounding_box (icon,
1914 &icon_pos.x0, &icon_pos.y0,
1915 &icon_pos.x1, &icon_pos.y1,
1916 BOUNDS_USAGE_FOR_LAYOUT);
1917 canvas_position_to_grid_position (grid,
1918 icon_pos,
1919 &grid_pos);
1920 placement_grid_mark (grid, grid_pos);
1921}
1922
1923static void
1924find_empty_location (CajaIconContainer *container,
1925 PlacementGrid *grid,
1926 CajaIcon *icon,
1927 int start_x,
1928 int start_y,
1929 int *x,
1930 int *y)
1931{
1932 double icon_width, icon_height;
1933 int canvas_width;
1934 int canvas_height;
1935 int height_for_bound_check;
1936 EelIRect icon_position;
1937 EelDRect pixbuf_rect;
1938 gboolean collision;
1939 GtkAllocation allocation;
1940
1941 /* Get container dimensions */
1942 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1943 canvas_width = CANVAS_WIDTH(container, allocation)((allocation.width - container->details->left_margin - container
->details->right_margin) / ((((EelCanvas*) (void *) ((container
)))))->pixels_per_unit)
;
1944 canvas_height = CANVAS_HEIGHT(container, allocation)((allocation.height - container->details->top_margin - container
->details->bottom_margin) / ((((EelCanvas*) (void *) ((
container)))))->pixels_per_unit)
;
1945
1946 icon_get_bounding_box (icon,
1947 &icon_position.x0, &icon_position.y0,
1948 &icon_position.x1, &icon_position.y1,
1949 BOUNDS_USAGE_FOR_LAYOUT);
1950 icon_width = icon_position.x1 - icon_position.x0;
1951 icon_height = icon_position.y1 - icon_position.y0;
1952
1953 icon_get_bounding_box (icon,
1954 NULL((void*)0), &icon_position.y0,
1955 NULL((void*)0), &icon_position.y1,
1956 BOUNDS_USAGE_FOR_ENTIRE_ITEM);
1957 height_for_bound_check = icon_position.y1 - icon_position.y0;
1958
1959 pixbuf_rect = caja_icon_canvas_item_get_icon_rectangle (icon->item);
1960
1961 /* Start the icon on a grid location */
1962 snap_position (container, icon, &start_x, &start_y);
1963
1964 icon_position.x0 = start_x;
1965 icon_position.y0 = start_y;
1966 icon_position.x1 = icon_position.x0 + icon_width;
1967 icon_position.y1 = icon_position.y0 + icon_height;
1968
1969 do
1970 {
1971 EelIRect grid_position;
1972 gboolean need_new_column;
1973
1974 collision = FALSE(0);
1975
1976 canvas_position_to_grid_position (grid,
1977 icon_position,
1978 &grid_position);
1979
1980 need_new_column = icon_position.y0 + height_for_bound_check + DESKTOP_PAD_VERTICAL10 > canvas_height;
1981
1982 if (need_new_column ||
1983 !placement_grid_position_is_free (grid, grid_position))
1984 {
1985 icon_position.y0 += SNAP_SIZE_Y20;
1986 icon_position.y1 = icon_position.y0 + icon_height;
1987
1988 if (need_new_column)
1989 {
1990 /* Move to the next column */
1991 icon_position.y0 = DESKTOP_PAD_VERTICAL10 + SNAP_SIZE_Y20 - (pixbuf_rect.y1 - pixbuf_rect.y0);
1992 while (icon_position.y0 < DESKTOP_PAD_VERTICAL10)
1993 {
1994 icon_position.y0 += SNAP_SIZE_Y20;
1995 }
1996 icon_position.y1 = icon_position.y0 + icon_height;
1997
1998 icon_position.x0 += SNAP_SIZE_X78;
1999 icon_position.x1 = icon_position.x0 + icon_width;
2000 }
2001
2002 collision = TRUE(!(0));
2003 }
2004 }
2005 while (collision && (icon_position.x1 < canvas_width));
2006
2007 *x = icon_position.x0;
2008 *y = icon_position.y0;
2009}
2010
2011static void
2012align_icons (CajaIconContainer *container)
2013{
2014 GList *unplaced_icons;
2015 GList *l;
2016 PlacementGrid *grid;
2017
2018 unplaced_icons = g_list_copy (container->details->icons);
2019
2020 unplaced_icons = g_list_sort (unplaced_icons,
2021 compare_icons_by_position);
2022
2023 if (caja_icon_container_is_layout_rtl (container))
2024 {
2025 unplaced_icons = g_list_reverse (unplaced_icons);
2026 }
2027
2028 grid = placement_grid_new (container, TRUE(!(0)));
2029
2030 if (!grid)
2031 {
2032 g_list_free (unplaced_icons);
2033 return;
2034 }
2035
2036 for (l = unplaced_icons; l != NULL((void*)0); l = l->next)
2037 {
2038 CajaIcon *icon;
2039 int x, y;
2040
2041 icon = l->data;
2042 x = icon->saved_ltr_x;
2043 y = icon->y;
2044 find_empty_location (container, grid,
2045 icon, x, y, &x, &y);
2046
2047 icon_set_position (icon, x, y);
2048 icon->saved_ltr_x = icon->x;
2049 placement_grid_mark_icon (grid, icon);
2050 }
2051
2052 g_list_free (unplaced_icons);
2053
2054 placement_grid_free (grid);
2055
2056 if (caja_icon_container_is_layout_rtl (container))
2057 {
2058 caja_icon_container_set_rtl_positions (container);
2059 }
2060}
2061
2062static double
2063get_mirror_x_position (CajaIconContainer *container, CajaIcon *icon, double x)
2064{
2065 EelDRect icon_bounds;
2066 GtkAllocation allocation;
2067
2068 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
2069 icon_bounds = caja_icon_canvas_item_get_icon_rectangle (icon->item);
2070
2071 return CANVAS_WIDTH(container, allocation)((allocation.width - container->details->left_margin - container
->details->right_margin) / ((((EelCanvas*) (void *) ((container
)))))->pixels_per_unit)
- x - (icon_bounds.x1 - icon_bounds.x0);
2072}
2073
2074static void
2075caja_icon_container_set_rtl_positions (CajaIconContainer *container)
2076{
2077 GList *l;
2078 CajaIcon *icon = NULL((void*)0);
2079
2080 if (!container->details->icons)
2081 {
2082 return;
2083 }
2084
2085 for (l = container->details->icons; l != NULL((void*)0); l = l->next)
2086 {
2087 double x;
2088
2089 icon = l->data;
2090 x = get_mirror_x_position (container, icon, icon->saved_ltr_x);
2091 icon_set_position (icon, x, icon->y);
2092 }
2093}
2094
2095static void
2096lay_down_icons_vertical_desktop (CajaIconContainer *container, GList *icons)
2097{
2098 GList *p, *placed_icons, *unplaced_icons;
2099 int total, new_length, placed;
2100 CajaIcon *icon;
2101 int height;
2102 int x, y, x1, x2, y1, y2;
2103 EelDRect icon_rect;
2104 GtkAllocation allocation;
2105
2106 /* Get container dimensions */
2107 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
2108 height = CANVAS_HEIGHT(container, allocation)((allocation.height - container->details->top_margin - container
->details->bottom_margin) / ((((EelCanvas*) (void *) ((
container)))))->pixels_per_unit)
;
2109
2110 /* Determine which icons have and have not been placed */
2111 placed_icons = NULL((void*)0);
2112 unplaced_icons = NULL((void*)0);
2113
2114 total = g_list_length (container->details->icons);
2115 new_length = g_list_length (icons);
2116 placed = total - new_length;
2117 if (placed > 0)
2118 {
2119 PlacementGrid *grid;
2120 /* Add only placed icons in list */
2121 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2122 {
2123 icon = p->data;
2124 if (icon_is_positioned (icon))
2125 {
2126 icon_set_position(icon, icon->saved_ltr_x, icon->y);
2127 placed_icons = g_list_prepend (placed_icons, icon);
2128 }
2129 else
2130 {
2131 icon->x = 0;
2132 icon->y = 0;
2133 unplaced_icons = g_list_prepend (unplaced_icons, icon);
2134 }
2135 }
2136 placed_icons = g_list_reverse (placed_icons);
2137 unplaced_icons = g_list_reverse (unplaced_icons);
2138
2139 grid = placement_grid_new (container, FALSE(0));
2140
2141 if (grid)
2142 {
2143 for (p = placed_icons; p != NULL((void*)0); p = p->next)
2144 {
2145 placement_grid_mark_icon
2146 (grid, (CajaIcon*)p->data);
2147 }
2148
2149 /* Place unplaced icons in the best locations */
2150 for (p = unplaced_icons; p != NULL((void*)0); p = p->next)
2151 {
2152 icon = p->data;
2153
2154 icon_rect = caja_icon_canvas_item_get_icon_rectangle (icon->item);
2155
2156 /* Start the icon in the first column */
2157 x = DESKTOP_PAD_HORIZONTAL10 + (SNAP_SIZE_X78 / 2) - ((icon_rect.x1 - icon_rect.x0) / 2);
2158 y = DESKTOP_PAD_VERTICAL10 + SNAP_SIZE_Y20 - (icon_rect.y1 - icon_rect.y0);
2159
2160 find_empty_location (container,
2161 grid,
2162 icon,
2163 x, y,
2164 &x, &y);
2165
2166 icon_set_position (icon, x, y);
2167 icon->saved_ltr_x = x;
2168 placement_grid_mark_icon (grid, icon);
2169 }
2170
2171 placement_grid_free (grid);
2172 }
2173
2174 g_list_free (placed_icons);
2175 g_list_free (unplaced_icons);
2176 }
2177 else
2178 {
2179 /* There are no placed icons. Just lay them down using our rules */
2180 x = DESKTOP_PAD_HORIZONTAL10;
2181
2182 while (icons != NULL((void*)0))
2183 {
2184 int max_width, column_width, icon_height;
2185 int center_x;
2186 int baseline;
2187 int icon_height_for_bound_check;
2188 gboolean should_snap;
2189
2190 should_snap = !(container->details->tighter_layout && !container->details->keep_aligned);
2191
2192 y = DESKTOP_PAD_VERTICAL10;
2193
2194 max_width = 0;
2195
2196 /* Calculate max width for column */
2197 for (p = icons; p != NULL((void*)0); p = p->next)
2198 {
2199 int icon_width;
2200
2201 icon = p->data;
2202
2203 icon_get_bounding_box (icon, &x1, &y1, &x2, &y2,
2204 BOUNDS_USAGE_FOR_LAYOUT);
2205 icon_width = x2 - x1;
2206 icon_height = y2 - y1;
2207
2208 icon_get_bounding_box (icon, NULL((void*)0), &y1, NULL((void*)0), &y2,
2209 BOUNDS_USAGE_FOR_ENTIRE_ITEM);
2210 icon_height_for_bound_check = y2 - y1;
2211
2212 if (should_snap)
2213 {
2214 /* Snap the baseline to a grid position */
2215 icon_rect = caja_icon_canvas_item_get_icon_rectangle (icon->item);
2216 baseline = y + (icon_rect.y1 - icon_rect.y0);
2217 baseline = SNAP_CEIL_VERTICAL (baseline)((ceil ((double)((baseline) - 10) / 20) * 20) + 10);
2218 y = baseline - (icon_rect.y1 - icon_rect.y0);
2219 }
2220
2221 /* Check and see if we need to move to a new column */
2222 if (y != DESKTOP_PAD_VERTICAL10 && y + icon_height_for_bound_check > height)
2223 {
2224 break;
2225 }
2226
2227 if (max_width < icon_width)
2228 {
2229 max_width = icon_width;
2230 }
2231
2232 y += icon_height + DESKTOP_PAD_VERTICAL10;
2233 }
2234
2235 y = DESKTOP_PAD_VERTICAL10;
2236
2237 center_x = x + max_width / 2;
2238 column_width = max_width;
2239 if (should_snap)
2240 {
2241 /* Find the grid column to center on */
2242 center_x = SNAP_CEIL_HORIZONTAL (center_x)((ceil ((double)((center_x) - 10) / 78) * 78) + 10);
2243 column_width = (center_x - x) + (max_width / 2);
2244 }
2245
2246 /* Lay out column */
2247 for (p = icons; p != NULL((void*)0); p = p->next)
2248 {
2249 icon = p->data;
2250 icon_get_bounding_box (icon, &x1, &y1, &x2, &y2,
2251 BOUNDS_USAGE_FOR_LAYOUT);
2252 icon_height = y2 - y1;
2253
2254 icon_get_bounding_box (icon, NULL((void*)0), &y1, NULL((void*)0), &y2,
2255 BOUNDS_USAGE_FOR_ENTIRE_ITEM);
2256 icon_height_for_bound_check = y2 - y1;
2257
2258 icon_rect = caja_icon_canvas_item_get_icon_rectangle (icon->item);
2259
2260 if (should_snap)
2261 {
2262 baseline = y + (icon_rect.y1 - icon_rect.y0);
2263 baseline = SNAP_CEIL_VERTICAL (baseline)((ceil ((double)((baseline) - 10) / 20) * 20) + 10);
2264 y = baseline - (icon_rect.y1 - icon_rect.y0);
2265 }
2266
2267 /* Check and see if we need to move to a new column */
2268 if (y != DESKTOP_PAD_VERTICAL10 && y > height - icon_height_for_bound_check &&
2269 /* Make sure we lay out at least one icon per column, to make progress */
2270 p != icons)
2271 {
2272 x += column_width + DESKTOP_PAD_HORIZONTAL10;
2273 break;
2274 }
2275
2276 icon_set_position (icon,
2277 center_x - (icon_rect.x1 - icon_rect.x0) / 2,
2278 y);
2279
2280 icon->saved_ltr_x = icon->x;
2281 y += icon_height + DESKTOP_PAD_VERTICAL10;
2282 }
2283 icons = p;
2284 }
2285 }
2286
2287 /* These modes are special. We freeze all of our positions
2288 * after we do the layout.
2289 */
2290 /* FIXME bugzilla.gnome.org 42478:
2291 * This should not be tied to the direction of layout.
2292 * It should be a separate switch.
2293 */
2294 caja_icon_container_freeze_icon_positions (container);
2295}
2296
2297
2298static void
2299lay_down_icons (CajaIconContainer *container, GList *icons, double start_y)
2300{
2301 switch (container->details->layout_mode)
2302 {
2303 case CAJA_ICON_LAYOUT_L_R_T_B:
2304 case CAJA_ICON_LAYOUT_R_L_T_B:
2305 lay_down_icons_horizontal (container, icons, start_y);
2306 break;
2307
2308 case CAJA_ICON_LAYOUT_T_B_L_R:
2309 case CAJA_ICON_LAYOUT_T_B_R_L:
2310 if (caja_icon_container_get_is_desktop (container))
2311 {
2312 lay_down_icons_vertical_desktop (container, icons);
2313 }
2314 else
2315 {
2316 lay_down_icons_vertical (container, icons, start_y);
2317 }
2318 break;
2319
2320 default:
2321 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 2321, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2322 }
2323}
2324
2325static void
2326redo_layout_internal (CajaIconContainer *container)
2327{
2328 finish_adding_new_icons (container);
2329
2330 /* Don't do any re-laying-out during stretching. Later we
2331 * might add smart logic that does this and leaves room for
2332 * the stretched icon, but if we do it we want it to be fast
2333 * and only re-lay-out when it's really needed.
2334 */
2335 if (container->details->auto_layout
2336 && container->details->drag_state != DRAG_STATE_STRETCH)
2337 {
2338 resort (container);
2339 lay_down_icons (container, container->details->icons, 0);
2340 }
2341
2342 if (caja_icon_container_is_layout_rtl (container))
2343 {
2344 caja_icon_container_set_rtl_positions (container);
2345 }
2346
2347 caja_icon_container_update_scroll_region (container);
2348
2349 process_pending_icon_to_reveal (container);
2350 process_pending_icon_to_rename (container);
2351 caja_icon_container_update_visible_icons (container);
2352}
2353
2354static gboolean
2355redo_layout_callback (gpointer callback_data)
2356{
2357 CajaIconContainer *container;
2358
2359 container = CAJA_ICON_CONTAINER (callback_data)((((CajaIconContainer*) (void *) ((callback_data)))));
2360 redo_layout_internal (container);
2361 container->details->idle_id = 0;
2362
2363 return FALSE(0);
2364}
2365
2366static void
2367unschedule_redo_layout (CajaIconContainer *container)
2368{
2369 if (container->details->idle_id != 0)
2370 {
2371 g_source_remove (container->details->idle_id);
2372 container->details->idle_id = 0;
2373 }
2374}
2375
2376static void
2377schedule_redo_layout (CajaIconContainer *container)
2378{
2379 if (container->details->idle_id == 0
2380 && container->details->has_been_allocated)
2381 {
2382 container->details->idle_id = g_idle_add
2383 (redo_layout_callback, container);
2384 }
2385}
2386
2387static void
2388redo_layout (CajaIconContainer *container)
2389{
2390 unschedule_redo_layout (container);
2391 redo_layout_internal (container);
2392}
2393
2394static void
2395reload_icon_positions (CajaIconContainer *container)
2396{
2397 GList *p, *no_position_icons;
2398 gboolean have_stored_position;
2399 CajaIconPosition position;
2400 EelDRect bounds;
2401 double bottom;
2402 EelCanvasItem *item;
2403 CajaIcon *icon = NULL((void*)0);
2404
2405 g_assert (!container->details->auto_layout)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if (!container->details->auto_layout) _g_boolean_var_139
= 1; else _g_boolean_var_139 = 0; _g_boolean_var_139; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 2405, ((const char*) (__func__)), "!container->details->auto_layout"
); } while (0)
;
2406
2407 resort (container);
2408
2409 no_position_icons = NULL((void*)0);
2410
2411 /* Place all the icons with positions. */
2412 bottom = 0;
2413 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2414 {
2415 icon = p->data;
2416
2417 have_stored_position = FALSE(0);
2418 g_signal_emit (container,
2419 signals[GET_STORED_ICON_POSITION], 0,
2420 icon->data,
2421 &position,
2422 &have_stored_position);
2423 if (have_stored_position)
2424 {
2425 icon_set_position (icon, position.x, position.y);
2426 item = EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))));
2427 caja_icon_canvas_item_get_bounds_for_layout (icon->item,
2428 &bounds.x0,
2429 &bounds.y0,
2430 &bounds.x1,
2431 &bounds.y1);
2432 eel_canvas_item_i2w (item->parent,
2433 &bounds.x0,
2434 &bounds.y0);
2435 eel_canvas_item_i2w (item->parent,
2436 &bounds.x1,
2437 &bounds.y1);
2438 if (bounds.y1 > bottom)
2439 {
2440 bottom = bounds.y1;
2441 }
2442 }
2443 else
2444 {
2445 no_position_icons = g_list_prepend (no_position_icons, icon);
2446 }
2447 }
2448 no_position_icons = g_list_reverse (no_position_icons);
2449
2450 /* Place all the other icons. */
2451 lay_down_icons (container, no_position_icons, bottom + ICON_PAD_BOTTOM4);
2452 g_list_free (no_position_icons);
2453}
2454
2455/* Container-level icon handling functions. */
2456
2457static gboolean
2458button_event_modifies_selection (GdkEventButton *event)
2459{
2460 return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0;
2461}
2462
2463/* invalidate the cached label sizes for all the icons */
2464static void
2465invalidate_label_sizes (CajaIconContainer *container)
2466{
2467 GList *p;
2468 CajaIcon *icon = NULL((void*)0);
2469
2470 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2471 {
2472 icon = p->data;
2473
2474 caja_icon_canvas_item_invalidate_label_size (icon->item);
2475 }
2476}
2477
2478/* invalidate the entire labels (i.e. their attributes) for all the icons */
2479static void
2480invalidate_labels (CajaIconContainer *container)
2481{
2482 GList *p;
2483 CajaIcon *icon = NULL((void*)0);
2484
2485 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2486 {
2487 icon = p->data;
2488
2489 caja_icon_canvas_item_invalidate_label (icon->item);
2490 }
2491}
2492
2493static gboolean
2494select_range (CajaIconContainer *container,
2495 CajaIcon *icon1,
2496 CajaIcon *icon2,
2497 gboolean unselect_outside_range)
2498{
2499 gboolean selection_changed;
2500 GList *p;
2501 CajaIcon *icon = NULL((void*)0);
2502 CajaIcon *unmatched_icon;
2503 gboolean select;
2504
2505 selection_changed = FALSE(0);
2506
2507 unmatched_icon = NULL((void*)0);
2508 select = FALSE(0);
2509 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2510 {
2511 icon = p->data;
2512
2513 if (unmatched_icon == NULL((void*)0))
2514 {
2515 if (icon == icon1)
2516 {
2517 unmatched_icon = icon2;
2518 select = TRUE(!(0));
2519 }
2520 else if (icon == icon2)
2521 {
2522 unmatched_icon = icon1;
2523 select = TRUE(!(0));
2524 }
2525 }
2526
2527 if (select || unselect_outside_range)
2528 {
2529 selection_changed |= icon_set_selected
2530 (container, icon, select);
2531 }
2532
2533 if (unmatched_icon != NULL((void*)0) && icon == unmatched_icon)
2534 {
2535 select = FALSE(0);
2536 }
2537
2538 }
2539
2540 if (selection_changed && icon2 != NULL((void*)0))
2541 {
2542 emit_atk_focus_state_change (icon2, TRUE(!(0)));
2543 }
2544 return selection_changed;
2545}
2546
2547
2548static gboolean
2549select_one_unselect_others (CajaIconContainer *container,
2550 CajaIcon *icon_to_select)
2551{
2552 gboolean selection_changed;
2553 GList *p;
2554 CajaIcon *icon = NULL((void*)0);
2555
2556 selection_changed = FALSE(0);
2557
2558 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2559 {
2560 icon = p->data;
2561
2562 selection_changed |= icon_set_selected
2563 (container, icon, icon == icon_to_select);
2564 }
2565
2566 if (selection_changed && icon_to_select != NULL((void*)0))
2567 {
2568 emit_atk_focus_state_change (icon_to_select, TRUE(!(0)));
2569 reveal_icon (container, icon_to_select);
2570 }
2571 return selection_changed;
2572}
2573
2574static gboolean
2575unselect_all (CajaIconContainer *container)
2576{
2577 return select_one_unselect_others (container, NULL((void*)0));
2578}
2579
2580void
2581caja_icon_container_move_icon (CajaIconContainer *container,
2582 CajaIcon *icon,
2583 int x, int y,
2584 double scale,
2585 gboolean raise,
2586 gboolean snap,
2587 gboolean update_position)
2588{
2589 CajaIconContainerDetails *details;
2590 gboolean emit_signal;
2591 CajaIconPosition position;
2592
2593 details = container->details;
2594
2595 emit_signal = FALSE(0);
2596
2597 if (icon == get_icon_being_renamed (container))
2598 {
2599 end_renaming_mode (container, TRUE(!(0)));
2600 }
2601
2602 if (scale != icon->scale)
2603 {
2604 icon->scale = scale;
2605 caja_icon_container_update_icon (container, icon);
2606 if (update_position)
2607 {
2608 redo_layout (container);
2609 emit_signal = TRUE(!(0));
2610 }
2611 }
2612
2613 if (!details->auto_layout && !details->lock_icons_position)
2614 {
2615 if (details->keep_aligned && snap)
2616 {
2617 snap_position (container, icon, &x, &y);
2618 }
2619
2620 if (x != icon->x || y != icon->y)
2621 {
2622 icon_set_position (icon, x, y);
2623 emit_signal = update_position;
2624 }
2625
2626 icon->saved_ltr_x = caja_icon_container_is_layout_rtl (container) ? get_mirror_x_position (container, icon, icon->x) : icon->x;
2627 }
2628
2629 if (emit_signal)
2630 {
2631 position.x = icon->saved_ltr_x;
2632 position.y = icon->y;
2633 position.scale = scale;
2634 g_signal_emit (container,
2635 signals[ICON_POSITION_CHANGED], 0,
2636 icon->data, &position);
2637 }
2638
2639 if (raise)
2640 {
2641 icon_raise (icon);
2642 }
2643
2644 /* FIXME bugzilla.gnome.org 42474:
2645 * Handling of the scroll region is inconsistent here. In
2646 * the scale-changing case, redo_layout is called, which updates the
2647 * scroll region appropriately. In other cases, it's up to the
2648 * caller to make sure the scroll region is updated. This could
2649 * lead to hard-to-track-down bugs.
2650 */
2651}
2652
2653/* Implementation of rubberband selection. */
2654static void
2655rubberband_select (CajaIconContainer *container,
2656 const EelDRect *previous_rect,
2657 const EelDRect *current_rect)
2658{
2659 GList *p;
2660 gboolean selection_changed, is_in, canvas_rect_calculated;
2661 EelIRect canvas_rect;
2662 EelCanvas *canvas;
2663 CajaIcon *icon = NULL((void*)0);
2664
2665 selection_changed = FALSE(0);
2666 canvas_rect_calculated = FALSE(0);
2667
2668 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2669 {
2670 icon = p->data;
2671
2672 if (!canvas_rect_calculated)
2673 {
2674 /* Only do this calculation once, since all the canvas items
2675 * we are interating are in the same coordinate space
2676 */
2677 canvas = EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))))->canvas;
2678 eel_canvas_w2c (canvas,
2679 current_rect->x0,
2680 current_rect->y0,
2681 &canvas_rect.x0,
2682 &canvas_rect.y0);
2683 eel_canvas_w2c (canvas,
2684 current_rect->x1,
2685 current_rect->y1,
2686 &canvas_rect.x1,
2687 &canvas_rect.y1);
2688 canvas_rect_calculated = TRUE(!(0));
2689 }
2690
2691 is_in = caja_icon_canvas_item_hit_test_rectangle (icon->item, canvas_rect);
2692
2693 selection_changed |= icon_set_selected
2694 (container, icon,
2695 is_in ^ icon->was_selected_before_rubberband);
2696 }
2697
2698 if (selection_changed)
2699 {
2700 g_signal_emit (container,
2701 signals[SELECTION_CHANGED], 0);
2702 }
2703}
2704
2705static int
2706rubberband_timeout_callback (gpointer data)
2707{
2708 CajaIconContainer *container;
2709 GtkWidget *widget;
2710 CajaIconRubberbandInfo *band_info;
2711 int x, y;
2712 double x1, y1, x2, y2;
2713 double world_x, world_y;
2714 int x_scroll, y_scroll;
2715 int adj_x, adj_y;
2716 GdkDisplay *display;
2717 GdkSeat *seat;
2718 gboolean adj_changed;
2719 GtkAllocation allocation;
2720
2721 EelDRect selection_rect;
2722
2723 widget = GTK_WIDGET (data)((((GtkWidget*) (void *) ((data)))));
2724 container = CAJA_ICON_CONTAINER (data)((((CajaIconContainer*) (void *) ((data)))));
2725 band_info = &container->details->rubberband_info;
2726
2727 g_assert (band_info->timer_id != 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (band_info->timer_id != 0) _g_boolean_var_140 = 1; else
_g_boolean_var_140 = 0; _g_boolean_var_140; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 2727, ((const char*)
(__func__)), "band_info->timer_id != 0"); } while (0)
;
2728 g_assert (EEL_IS_CANVAS_RECT (band_info->selection_rectangle) ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((band_info->selection_rectangle)); GType __t = ((eel_canvas_rect_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; })))) || (((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((band_info->selection_rectangle)); GType __t = ((eel_canvas_rect_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_141 = 1; else _g_boolean_var_141 =
0; _g_boolean_var_141; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 2729, ((const char*)
(__func__)), "EEL_IS_CANVAS_RECT (band_info->selection_rectangle) || EEL_IS_CANVAS_RECT (band_info->selection_rectangle)"
); } while (0)
2729 EEL_IS_CANVAS_RECT (band_info->selection_rectangle))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((band_info->selection_rectangle)); GType __t = ((eel_canvas_rect_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; })))) || (((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((band_info->selection_rectangle)); GType __t = ((eel_canvas_rect_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_141 = 1; else _g_boolean_var_141 =
0; _g_boolean_var_141; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 2729, ((const char*)
(__func__)), "EEL_IS_CANVAS_RECT (band_info->selection_rectangle) || EEL_IS_CANVAS_RECT (band_info->selection_rectangle)"
); } while (0)
;
2730
2731 adj_changed = FALSE(0);
2732 gtk_widget_get_allocation (widget, &allocation);
2733
2734 adj_x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
2735 if (adj_x != band_info->last_adj_x)
2736 {
2737 band_info->last_adj_x = adj_x;
2738 adj_changed = TRUE(!(0));
2739 }
2740
2741 adj_y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
2742 if (adj_y != band_info->last_adj_y)
2743 {
2744 band_info->last_adj_y = adj_y;
2745 adj_changed = TRUE(!(0));
2746 }
2747 display = gtk_widget_get_display (widget);
2748 seat = gdk_display_get_default_seat (display);
2749
2750 gdk_window_get_device_position (gtk_widget_get_window (widget),
2751 gdk_seat_get_pointer (seat),
2752 &x, &y, NULL((void*)0));
2753
2754 if (x < 0)
2755 {
2756 x_scroll = x;
2757 x = 0;
2758 }
2759 else if (x >= allocation.width)
2760 {
2761 x_scroll = x - allocation.width + 1;
2762 x = allocation.width - 1;
2763 }
2764 else
2765 {
2766 x_scroll = 0;
2767 }
2768
2769 if (y < 0)
2770 {
2771 y_scroll = y;
2772 y = 0;
2773 }
2774 else if (y >= allocation.height)
2775 {
2776 y_scroll = y - allocation.height + 1;
2777 y = allocation.height - 1;
2778 }
2779 else
2780 {
2781 y_scroll = 0;
2782 }
2783
2784 if (y_scroll == 0 && x_scroll == 0
2785 && (int) band_info->prev_x == x && (int) band_info->prev_y == y && !adj_changed)
2786 {
2787 return TRUE(!(0));
2788 }
2789
2790 caja_icon_container_scroll (container, x_scroll, y_scroll);
2791
2792 /* Remember to convert from widget to scrolled window coords */
2793 eel_canvas_window_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
2794 x + gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))))),
2795 y + gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))))),
2796 &world_x, &world_y);
2797
2798 if (world_x < band_info->start_x)
2799 {
2800 x1 = world_x;
2801 x2 = band_info->start_x;
2802 }
2803 else
2804 {
2805 x1 = band_info->start_x;
2806 x2 = world_x;
2807 }
2808
2809 if (world_y < band_info->start_y)
2810 {
2811 y1 = world_y;
2812 y2 = band_info->start_y;
2813 }
2814 else
2815 {
2816 y1 = band_info->start_y;
2817 y2 = world_y;
2818 }
2819
2820 /* Don't let the area of the selection rectangle be empty.
2821 * Aside from the fact that it would be funny when the rectangle disappears,
2822 * this also works around a crash in libart that happens sometimes when a
2823 * zero height rectangle is passed.
2824 */
2825 x2 = MAX (x1 + 1, x2)(((x1 + 1) > (x2)) ? (x1 + 1) : (x2));
2826 y2 = MAX (y1 + 1, y2)(((y1 + 1) > (y2)) ? (y1 + 1) : (y2));
2827
2828 eel_canvas_item_set
2829 (band_info->selection_rectangle,
2830 "x1", x1, "y1", y1,
2831 "x2", x2, "y2", y2,
2832 NULL((void*)0));
2833
2834 selection_rect.x0 = x1;
2835 selection_rect.y0 = y1;
2836 selection_rect.x1 = x2;
2837 selection_rect.y1 = y2;
2838
2839 rubberband_select (container,
2840 &band_info->prev_rect,
2841 &selection_rect);
2842
2843 band_info->prev_x = x;
2844 band_info->prev_y = y;
2845
2846 band_info->prev_rect = selection_rect;
2847
2848 return TRUE(!(0));
2849}
2850
2851/*borrowed from Nemo, makes Caja rubberbanding follow same selectors as Nemo and presumably Nautilus */
2852static void
2853start_rubberbanding (CajaIconContainer *container,
2854 GdkEventButton *event)
2855{
2856 AtkObject *accessible;
2857 CajaIconContainerDetails *details;
2858 CajaIconRubberbandInfo *band_info;
2859 GdkRGBA bg_color, border_color;
2860 GdkRGBA *c;
2861 GList *p;
2862 CajaIcon *icon;
2863 GtkStyleContext *context;
2864
2865 details = container->details;
2866 band_info = &details->rubberband_info;
2867
2868 g_signal_emit (container,
2869 signals[BAND_SELECT_STARTED], 0);
2870
2871 for (p = details->icons; p != NULL((void*)0); p = p->next) {
2872 icon = p->data;
2873 icon->was_selected_before_rubberband = icon->is_selected;
2874 }
2875
2876 eel_canvas_window_to_world
2877 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), event->x, event->y,
2878 &band_info->start_x, &band_info->start_y);
2879
2880 context = gtk_widget_get_style_context (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
2881 gtk_style_context_save (context);
2882 gtk_style_context_add_class (context, GTK_STYLE_CLASS_RUBBERBAND"rubberband");
2883
2884 gtk_style_context_get (context, GTK_STATE_FLAG_NORMAL,
2885 GTK_STYLE_PROPERTY_BACKGROUND_COLOR"background-color",
2886 &c, NULL((void*)0));
2887
2888 bg_color = *c;
2889
2890 gtk_style_context_get (context, GTK_STATE_FLAG_NORMAL,
2891 GTK_STYLE_PROPERTY_BORDER_COLOR"border-color",
2892 &c, NULL((void*)0));
2893
2894 border_color = *c;
2895 gdk_rgba_free (c);
2896
2897 gtk_style_context_restore (context);
2898
2899 band_info->selection_rectangle = eel_canvas_item_new
2900 (eel_canvas_root
2901 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container)))))),
2902 EEL_TYPE_CANVAS_RECT(eel_canvas_rect_get_type ()),
2903 "x1", band_info->start_x,
2904 "y1", band_info->start_y,
2905 "x2", band_info->start_x,
2906 "y2", band_info->start_y,
2907 "fill_color_rgba", &bg_color,
2908 "outline_color_rgba", &border_color,
2909 "width_pixels", 1,
2910 NULL((void*)0));
2911
2912 accessible = atk_gobject_accessible_for_object
2913 (G_OBJECT (band_info->selection_rectangle)((((GObject*) (void *) ((band_info->selection_rectangle)))
))
);
2914 atk_object_set_name (accessible, "selection");
2915 atk_object_set_description (accessible, _("The selection rectangle")dcgettext (((void*)0), "The selection rectangle", 5));
2916
2917 band_info->prev_x = event->x - gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
2918 band_info->prev_y = event->y - gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
2919
2920 band_info->active = TRUE(!(0));
2921
2922 if (band_info->timer_id == 0) {
2923 band_info->timer_id = g_timeout_add
2924 (RUBBERBAND_TIMEOUT_INTERVAL10,
2925 rubberband_timeout_callback,
2926 container);
2927 }
2928
2929 eel_canvas_item_grab (band_info->selection_rectangle,
2930 (GDK_POINTER_MOTION_MASK
2931 | GDK_BUTTON_RELEASE_MASK
2932 | GDK_SCROLL_MASK),
2933 NULL((void*)0),
2934 (GdkEvent *)event);
2935}
2936
2937static void
2938stop_rubberbanding (CajaIconContainer *container)
2939{
2940 CajaIconRubberbandInfo *band_info;
2941 GList *icons;
2942
2943 band_info = &container->details->rubberband_info;
2944
2945 g_assert (band_info->timer_id != 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if (band_info->timer_id != 0) _g_boolean_var_142 = 1; else
_g_boolean_var_142 = 0; _g_boolean_var_142; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 2945, ((const char*)
(__func__)), "band_info->timer_id != 0"); } while (0)
;
2946 g_source_remove (band_info->timer_id);
2947 band_info->timer_id = 0;
2948
2949 band_info->active = FALSE(0);
2950
2951 /* Destroy this canvas item; the parent will unref it. */
2952 eel_canvas_item_ungrab (band_info->selection_rectangle);
2953 eel_canvas_item_destroy (band_info->selection_rectangle);
2954 band_info->selection_rectangle = NULL((void*)0);
2955
2956 /* if only one item has been selected, use it as range
2957 * selection base (cf. handle_icon_button_press) */
2958 icons = caja_icon_container_get_selected_icons (container);
2959 if (g_list_length (icons) == 1)
2960 {
2961 container->details->range_selection_base_icon = icons->data;
2962 }
2963 g_list_free (icons);
2964
2965 g_signal_emit (container,
2966 signals[BAND_SELECT_ENDED], 0);
2967}
2968
2969/* Keyboard navigation. */
2970
2971typedef gboolean (* IsBetterIconFunction) (CajaIconContainer *container,
2972 CajaIcon *start_icon,
2973 CajaIcon *best_so_far,
2974 CajaIcon *candidate,
2975 void *data);
2976
2977static CajaIcon *
2978find_best_icon (CajaIconContainer *container,
2979 CajaIcon *start_icon,
2980 IsBetterIconFunction function,
2981 void *data)
2982{
2983 GList *p;
2984 CajaIcon *best, *candidate;
2985
2986 best = NULL((void*)0);
2987 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
2988 {
2989 candidate = p->data;
2990
2991 if (candidate != start_icon)
2992 {
2993 if ((* function) (container, start_icon, best, candidate, data))
2994 {
2995 best = candidate;
2996 }
2997 }
2998 }
2999 return best;
3000}
3001
3002static CajaIcon *
3003find_best_selected_icon (CajaIconContainer *container,
3004 CajaIcon *start_icon,
3005 IsBetterIconFunction function,
3006 void *data)
3007{
3008 GList *p;
3009 CajaIcon *best, *candidate;
3010
3011 best = NULL((void*)0);
3012 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
3013 {
3014 candidate = p->data;
3015
3016 if (candidate != start_icon && candidate->is_selected)
3017 {
3018 if ((* function) (container, start_icon, best, candidate, data))
3019 {
3020 best = candidate;
3021 }
3022 }
3023 }
3024 return best;
3025}
3026
3027static int
3028compare_icons_by_uri (CajaIconContainer *container,
3029 CajaIcon *icon_a,
3030 CajaIcon *icon_b)
3031{
3032 char *uri_a, *uri_b;
3033 int result;
3034
3035 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 3035, ((const char*)
(__func__)), "CAJA_IS_ICON_CONTAINER (container)"); } while (
0)
;
3036 g_assert (icon_a != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if (icon_a != ((void*)0)) _g_boolean_var_144 = 1; else _g_boolean_var_144
= 0; _g_boolean_var_144; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 3036, ((const char*)
(__func__)), "icon_a != NULL"); } while (0)
;
3037 g_assert (icon_b != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if (icon_b != ((void*)0)) _g_boolean_var_145 = 1; else _g_boolean_var_145
= 0; _g_boolean_var_145; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 3037, ((const char*)
(__func__)), "icon_b != NULL"); } while (0)
;
3038 g_assert (icon_a != icon_b)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if (icon_a != icon_b) _g_boolean_var_146 = 1; else _g_boolean_var_146
= 0; _g_boolean_var_146; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 3038, ((const char*)
(__func__)), "icon_a != icon_b"); } while (0)
;
3039
3040 uri_a = caja_icon_container_get_icon_uri (container, icon_a);
3041 uri_b = caja_icon_container_get_icon_uri (container, icon_b);
3042 result = strcmp (uri_a, uri_b);
3043 g_assert (result != 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if (result != 0) _g_boolean_var_147 = 1; else _g_boolean_var_147
= 0; _g_boolean_var_147; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 3043, ((const char*)
(__func__)), "result != 0"); } while (0)
;
3044 g_free (uri_a);
3045 g_free (uri_b);
3046
3047 return result;
3048}
3049
3050static int
3051get_cmp_point_x (CajaIconContainer *container,
3052 EelDRect icon_rect)
3053{
3054 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
3055 {
3056 if (gtk_widget_get_direction (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))) == GTK_TEXT_DIR_RTL)
3057 {
3058 return icon_rect.x0;
3059 }
3060 else
3061 {
3062 return icon_rect.x1;
3063 }
3064 }
3065 else
3066 {
3067 return (icon_rect.x0 + icon_rect.x1) / 2;
3068 }
3069}
3070
3071static int
3072get_cmp_point_y (CajaIconContainer *container,
3073 EelDRect icon_rect)
3074{
3075 if (container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
3076 {
3077 return (icon_rect.y0 + icon_rect.y1)/2;
3078 }
3079 else
3080 {
3081 return icon_rect.y1;
3082 }
3083}
3084
3085
3086static int
3087compare_icons_horizontal (CajaIconContainer *container,
3088 CajaIcon *icon_a,
3089 CajaIcon *icon_b)
3090{
3091 EelDRect world_rect;
3092 int ax, bx;
3093
3094 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_a->item);
3095 eel_canvas_w2c
3096 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3097 get_cmp_point_x (container, world_rect),
3098 get_cmp_point_y (container, world_rect),
3099 &ax,
3100 NULL((void*)0));
3101 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_b->item);
3102 eel_canvas_w2c
3103 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3104 get_cmp_point_x (container, world_rect),
3105 get_cmp_point_y (container, world_rect),
3106 &bx,
3107 NULL((void*)0));
3108
3109 if (ax < bx)
3110 {
3111 return -1;
3112 }
3113 if (ax > bx)
3114 {
3115 return +1;
3116 }
3117 return 0;
3118}
3119
3120static int
3121compare_icons_vertical (CajaIconContainer *container,
3122 CajaIcon *icon_a,
3123 CajaIcon *icon_b)
3124{
3125 EelDRect world_rect;
3126 int ay, by;
3127
3128 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_a->item);
3129 eel_canvas_w2c
3130 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3131 get_cmp_point_x (container, world_rect),
3132 get_cmp_point_y (container, world_rect),
3133 NULL((void*)0),
3134 &ay);
3135 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_b->item);
3136 eel_canvas_w2c
3137 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3138 get_cmp_point_x (container, world_rect),
3139 get_cmp_point_y (container, world_rect),
3140 NULL((void*)0),
3141 &by);
3142
3143 if (ay < by)
3144 {
3145 return -1;
3146 }
3147 if (ay > by)
3148 {
3149 return +1;
3150 }
3151 return 0;
3152}
3153
3154static int
3155compare_icons_horizontal_first (CajaIconContainer *container,
3156 CajaIcon *icon_a,
3157 CajaIcon *icon_b)
3158{
3159 EelDRect world_rect;
3160 int ax, ay, bx, by;
3161
3162 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_a->item);
3163 eel_canvas_w2c
3164 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3165 get_cmp_point_x (container, world_rect),
3166 get_cmp_point_y (container, world_rect),
3167 &ax,
3168 &ay);
3169 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_b->item);
3170 eel_canvas_w2c
3171 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3172 get_cmp_point_x (container, world_rect),
3173 get_cmp_point_y (container, world_rect),
3174 &bx,
3175 &by);
3176
3177 if (ax < bx)
3178 {
3179 return -1;
3180 }
3181 if (ax > bx)
3182 {
3183 return +1;
3184 }
3185 if (ay < by)
3186 {
3187 return -1;
3188 }
3189 if (ay > by)
3190 {
3191 return +1;
3192 }
3193 return compare_icons_by_uri (container, icon_a, icon_b);
3194}
3195
3196static int
3197compare_icons_vertical_first (CajaIconContainer *container,
3198 CajaIcon *icon_a,
3199 CajaIcon *icon_b)
3200{
3201 EelDRect world_rect;
3202 int ax, ay, bx, by;
3203
3204 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_a->item);
3205 eel_canvas_w2c
3206 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3207 get_cmp_point_x (container, world_rect),
3208 get_cmp_point_y (container, world_rect),
3209 &ax,
3210 &ay);
3211 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon_b->item);
3212 eel_canvas_w2c
3213 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3214 get_cmp_point_x (container, world_rect),
3215 get_cmp_point_y (container, world_rect),
3216 &bx,
3217 &by);
3218
3219 if (ay < by)
3220 {
3221 return -1;
3222 }
3223 if (ay > by)
3224 {
3225 return +1;
3226 }
3227 if (ax < bx)
3228 {
3229 return -1;
3230 }
3231 if (ax > bx)
3232 {
3233 return +1;
3234 }
3235 return compare_icons_by_uri (container, icon_a, icon_b);
3236}
3237
3238static gboolean
3239leftmost_in_top_row (CajaIconContainer *container,
3240 CajaIcon *start_icon,
3241 CajaIcon *best_so_far,
3242 CajaIcon *candidate,
3243 void *data)
3244{
3245 if (best_so_far == NULL((void*)0))
3246 {
3247 return TRUE(!(0));
3248 }
3249 return compare_icons_vertical_first (container, best_so_far, candidate) > 0;
3250}
3251
3252static gboolean
3253rightmost_in_top_row (CajaIconContainer *container,
3254 CajaIcon *start_icon,
3255 CajaIcon *best_so_far,
3256 CajaIcon *candidate,
3257 void *data)
3258{
3259 if (best_so_far == NULL((void*)0))
3260 {
3261 return TRUE(!(0));
3262 }
3263 return ((compare_icons_vertical (container, best_so_far, candidate) > 0) &&
3264 (compare_icons_horizontal (container, best_so_far, candidate) < 0));
3265}
3266
3267static gboolean
3268rightmost_in_bottom_row (CajaIconContainer *container,
3269 CajaIcon *start_icon,
3270 CajaIcon *best_so_far,
3271 CajaIcon *candidate,
3272 void *data)
3273{
3274 if (best_so_far == NULL((void*)0))
3275 {
3276 return TRUE(!(0));
3277 }
3278 return compare_icons_vertical_first (container, best_so_far, candidate) < 0;
3279}
3280
3281static int
3282compare_with_start_row (CajaIconContainer *container,
3283 CajaIcon *icon)
3284{
3285 EelCanvasItem *item;
3286
3287 item = EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))));
3288
3289 if (container->details->arrow_key_start_y < item->y1)
3290 {
3291 return -1;
3292 }
3293 if (container->details->arrow_key_start_y > item->y2)
3294 {
3295 return +1;
3296 }
3297 return 0;
3298}
3299
3300static int
3301compare_with_start_column (CajaIconContainer *container,
3302 CajaIcon *icon)
3303{
3304 EelCanvasItem *item;
3305
3306 item = EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))));
3307
3308 if (container->details->arrow_key_start_x < item->x1)
3309 {
3310 return -1;
3311 }
3312 if (container->details->arrow_key_start_x > item->x2)
3313 {
3314 return +1;
3315 }
3316 return 0;
3317}
3318
3319static gboolean
3320same_row_right_side_leftmost (CajaIconContainer *container,
3321 CajaIcon *start_icon,
3322 CajaIcon *best_so_far,
3323 CajaIcon *candidate,
3324 void *data)
3325{
3326 /* Candidates not on the start row do not qualify. */
3327 if (compare_with_start_row (container, candidate) != 0)
3328 {
3329 return FALSE(0);
3330 }
3331
3332 /* Candidates that are farther right lose out. */
3333 if (best_so_far != NULL((void*)0))
3334 {
3335 if (compare_icons_horizontal_first (container,
3336 best_so_far,
3337 candidate) < 0)
3338 {
3339 return FALSE(0);
3340 }
3341 }
3342
3343 /* Candidate to the left of the start do not qualify. */
3344 if (compare_icons_horizontal_first (container,
3345 candidate,
3346 start_icon) <= 0)
3347 {
3348 return FALSE(0);
3349 }
3350
3351 return TRUE(!(0));
3352}
3353
3354static gboolean
3355same_row_left_side_rightmost (CajaIconContainer *container,
3356 CajaIcon *start_icon,
3357 CajaIcon *best_so_far,
3358 CajaIcon *candidate,
3359 void *data)
3360{
3361 /* Candidates not on the start row do not qualify. */
3362 if (compare_with_start_row (container, candidate) != 0)
3363 {
3364 return FALSE(0);
3365 }
3366
3367 /* Candidates that are farther left lose out. */
3368 if (best_so_far != NULL((void*)0))
3369 {
3370 if (compare_icons_horizontal_first (container,
3371 best_so_far,
3372 candidate) > 0)
3373 {
3374 return FALSE(0);
3375 }
3376 }
3377
3378 /* Candidate to the right of the start do not qualify. */
3379 if (compare_icons_horizontal_first (container,
3380 candidate,
3381 start_icon) >= 0)
3382 {
3383 return FALSE(0);
3384 }
3385
3386 return TRUE(!(0));
3387}
3388
3389static gboolean
3390next_row_leftmost (CajaIconContainer *container,
3391 CajaIcon *start_icon,
3392 CajaIcon *best_so_far,
3393 CajaIcon *candidate,
3394 void *data)
3395{
3396 /* sort out icons that are not below the current row */
3397 if (compare_with_start_row (container, candidate) >= 0)
3398 {
3399 return FALSE(0);
3400 }
3401
3402 if (best_so_far != NULL((void*)0))
3403 {
3404 if (compare_icons_vertical_first (container,
3405 best_so_far,
3406 candidate) > 0)
3407 {
3408 /* candidate is above best choice, but below the current row */
3409 return TRUE(!(0));
3410 }
3411
3412 if (compare_icons_horizontal_first (container,
3413 best_so_far,
3414 candidate) > 0)
3415 {
3416 return TRUE(!(0));
3417 }
3418 }
3419
3420 return best_so_far == NULL((void*)0);
3421}
3422
3423static gboolean
3424next_row_rightmost (CajaIconContainer *container,
3425 CajaIcon *start_icon,
3426 CajaIcon *best_so_far,
3427 CajaIcon *candidate,
3428 void *data)
3429{
3430 /* sort out icons that are not below the current row */
3431 if (compare_with_start_row (container, candidate) >= 0)
3432 {
3433 return FALSE(0);
3434 }
3435
3436 if (best_so_far != NULL((void*)0))
3437 {
3438 if (compare_icons_vertical_first (container,
3439 best_so_far,
3440 candidate) > 0)
3441 {
3442 /* candidate is above best choice, but below the current row */
3443 return TRUE(!(0));
3444 }
3445
3446 if (compare_icons_horizontal_first (container,
3447 best_so_far,
3448 candidate) < 0)
3449 {
3450 return TRUE(!(0));
3451 }
3452 }
3453
3454 return best_so_far == NULL((void*)0);
3455}
3456
3457static gboolean
3458next_column_bottommost (CajaIconContainer *container,
3459 CajaIcon *start_icon,
3460 CajaIcon *best_so_far,
3461 CajaIcon *candidate,
3462 void *data)
3463{
3464 /* sort out icons that are not on the right of the current column */
3465 if (compare_with_start_column (container, candidate) >= 0)
3466 {
3467 return FALSE(0);
3468 }
3469
3470 if (best_so_far != NULL((void*)0))
3471 {
3472 if (compare_icons_horizontal_first (container,
3473 best_so_far,
3474 candidate) > 0)
3475 {
3476 /* candidate is above best choice, but below the current row */
3477 return TRUE(!(0));
3478 }
3479
3480 if (compare_icons_vertical_first (container,
3481 best_so_far,
3482 candidate) < 0)
3483 {
3484 return TRUE(!(0));
3485 }
3486 }
3487
3488 return best_so_far == NULL((void*)0);
3489}
3490
3491static gboolean
3492previous_row_rightmost (CajaIconContainer *container,
3493 CajaIcon *start_icon,
3494 CajaIcon *best_so_far,
3495 CajaIcon *candidate,
3496 void *data)
3497{
3498 /* sort out icons that are not above the current row */
3499 if (compare_with_start_row (container, candidate) <= 0)
3500 {
3501 return FALSE(0);
3502 }
3503
3504 if (best_so_far != NULL((void*)0))
3505 {
3506 if (compare_icons_vertical_first (container,
3507 best_so_far,
3508 candidate) < 0)
3509 {
3510 /* candidate is below the best choice, but above the current row */
3511 return TRUE(!(0));
3512 }
3513
3514 if (compare_icons_horizontal_first (container,
3515 best_so_far,
3516 candidate) < 0)
3517 {
3518 return TRUE(!(0));
3519 }
3520 }
3521
3522 return best_so_far == NULL((void*)0);
3523}
3524
3525static gboolean
3526same_column_above_lowest (CajaIconContainer *container,
3527 CajaIcon *start_icon,
3528 CajaIcon *best_so_far,
3529 CajaIcon *candidate,
3530 void *data)
3531{
3532 /* Candidates not on the start column do not qualify. */
3533 if (compare_with_start_column (container, candidate) != 0)
3534 {
3535 return FALSE(0);
3536 }
3537
3538 /* Candidates that are higher lose out. */
3539 if (best_so_far != NULL((void*)0))
3540 {
3541 if (compare_icons_vertical_first (container,
3542 best_so_far,
3543 candidate) > 0)
3544 {
3545 return FALSE(0);
3546 }
3547 }
3548
3549 /* Candidates below the start do not qualify. */
3550 if (compare_icons_vertical_first (container,
3551 candidate,
3552 start_icon) >= 0)
3553 {
3554 return FALSE(0);
3555 }
3556
3557 return TRUE(!(0));
3558}
3559
3560static gboolean
3561same_column_below_highest (CajaIconContainer *container,
3562 CajaIcon *start_icon,
3563 CajaIcon *best_so_far,
3564 CajaIcon *candidate,
3565 void *data)
3566{
3567 /* Candidates not on the start column do not qualify. */
3568 if (compare_with_start_column (container, candidate) != 0)
3569 {
3570 return FALSE(0);
3571 }
3572
3573 /* Candidates that are lower lose out. */
3574 if (best_so_far != NULL((void*)0))
3575 {
3576 if (compare_icons_vertical_first (container,
3577 best_so_far,
3578 candidate) < 0)
3579 {
3580 return FALSE(0);
3581 }
3582 }
3583
3584 /* Candidates above the start do not qualify. */
3585 if (compare_icons_vertical_first (container,
3586 candidate,
3587 start_icon) <= 0)
3588 {
3589 return FALSE(0);
3590 }
3591
3592 return TRUE(!(0));
3593}
3594
3595static gboolean
3596previous_column_highest (CajaIconContainer *container,
3597 CajaIcon *start_icon,
3598 CajaIcon *best_so_far,
3599 CajaIcon *candidate,
3600 void *data)
3601{
3602 /* sort out icons that are not before the current column */
3603 if (compare_with_start_column (container, candidate) <= 0)
3604 {
3605 return FALSE(0);
3606 }
3607
3608 if (best_so_far != NULL((void*)0))
3609 {
3610 if (compare_icons_horizontal (container,
3611 best_so_far,
3612 candidate) < 0)
3613 {
3614 /* candidate is right of the best choice, but left of the current column */
3615 return TRUE(!(0));
3616 }
3617
3618 if (compare_icons_vertical (container,
3619 best_so_far,
3620 candidate) > 0)
3621 {
3622 return TRUE(!(0));
3623 }
3624 }
3625
3626 return best_so_far == NULL((void*)0);
3627}
3628
3629
3630static gboolean
3631next_column_highest (CajaIconContainer *container,
3632 CajaIcon *start_icon,
3633 CajaIcon *best_so_far,
3634 CajaIcon *candidate,
3635 void *data)
3636{
3637 /* sort out icons that are not after the current column */
3638 if (compare_with_start_column (container, candidate) >= 0)
3639 {
3640 return FALSE(0);
3641 }
3642
3643 if (best_so_far != NULL((void*)0))
3644 {
3645 if (compare_icons_horizontal_first (container,
3646 best_so_far,
3647 candidate) > 0)
3648 {
3649 /* candidate is left of the best choice, but right of the current column */
3650 return TRUE(!(0));
3651 }
3652
3653 if (compare_icons_vertical_first (container,
3654 best_so_far,
3655 candidate) > 0)
3656 {
3657 return TRUE(!(0));
3658 }
3659 }
3660
3661 return best_so_far == NULL((void*)0);
3662}
3663
3664static gboolean
3665previous_column_lowest (CajaIconContainer *container,
3666 CajaIcon *start_icon,
3667 CajaIcon *best_so_far,
3668 CajaIcon *candidate,
3669 void *data)
3670{
3671 /* sort out icons that are not before the current column */
3672 if (compare_with_start_column (container, candidate) <= 0)
3673 {
3674 return FALSE(0);
3675 }
3676
3677 if (best_so_far != NULL((void*)0))
3678 {
3679 if (compare_icons_horizontal_first (container,
3680 best_so_far,
3681 candidate) < 0)
3682 {
3683 /* candidate is right of the best choice, but left of the current column */
3684 return TRUE(!(0));
3685 }
3686
3687 if (compare_icons_vertical_first (container,
3688 best_so_far,
3689 candidate) < 0)
3690 {
3691 return TRUE(!(0));
3692 }
3693 }
3694
3695 return best_so_far == NULL((void*)0);
3696}
3697
3698static gboolean
3699last_column_lowest (CajaIconContainer *container,
3700 CajaIcon *start_icon,
3701 CajaIcon *best_so_far,
3702 CajaIcon *candidate,
3703 void *data)
3704{
3705 if (best_so_far == NULL((void*)0))
3706 {
3707 return TRUE(!(0));
3708 }
3709 return compare_icons_horizontal_first (container, best_so_far, candidate) < 0;
3710}
3711
3712static gboolean
3713closest_in_90_degrees (CajaIconContainer *container,
3714 CajaIcon *start_icon,
3715 CajaIcon *best_so_far,
3716 CajaIcon *candidate,
3717 void *data)
3718{
3719 EelDRect world_rect;
3720 int x, y;
3721 int dx, dy;
3722 int dist;
3723 int *best_dist;
3724
3725
3726 world_rect = caja_icon_canvas_item_get_icon_rectangle (candidate->item);
3727 eel_canvas_w2c
3728 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3729 get_cmp_point_x (container, world_rect),
3730 get_cmp_point_y (container, world_rect),
3731 &x,
3732 &y);
3733
3734 dx = x - container->details->arrow_key_start_x;
3735 dy = y - container->details->arrow_key_start_y;
3736
3737 switch (container->details->arrow_key_direction)
3738 {
3739 case GTK_DIR_UP:
3740 if (dy > 0 ||
3741 ABS(dx)(((dx) < 0) ? -(dx) : (dx)) > ABS(dy)(((dy) < 0) ? -(dy) : (dy)))
3742 {
3743 return FALSE(0);
3744 }
3745 break;
3746 case GTK_DIR_DOWN:
3747 if (dy < 0 ||
3748 ABS(dx)(((dx) < 0) ? -(dx) : (dx)) > ABS(dy)(((dy) < 0) ? -(dy) : (dy)))
3749 {
3750 return FALSE(0);
3751 }
3752 break;
3753 case GTK_DIR_LEFT:
3754 if (dx > 0 ||
3755 ABS(dy)(((dy) < 0) ? -(dy) : (dy)) > ABS(dx)(((dx) < 0) ? -(dx) : (dx)))
3756 {
3757 return FALSE(0);
3758 }
3759 break;
3760 case GTK_DIR_RIGHT:
3761 if (dx < 0 ||
3762 ABS(dy)(((dy) < 0) ? -(dy) : (dy)) > ABS(dx)(((dx) < 0) ? -(dx) : (dx)))
3763 {
3764 return FALSE(0);
3765 }
3766 break;
3767 default:
3768 g_assert_not_reached()do { g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 3768, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3769 }
3770
3771 dist = dx*dx + dy*dy;
3772 best_dist = data;
3773
3774 if (best_so_far == NULL((void*)0))
3775 {
3776 *best_dist = dist;
3777 return TRUE(!(0));
3778 }
3779
3780 if (dist < *best_dist)
3781 {
3782 *best_dist = dist;
3783 return TRUE(!(0));
3784 }
3785
3786 return FALSE(0);
3787}
3788
3789static EelDRect
3790get_rubberband (CajaIcon *icon1,
3791 CajaIcon *icon2)
3792{
3793 EelDRect rect1;
3794 EelDRect rect2;
3795 EelDRect ret;
3796
3797 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon1->item)((((EelCanvasItem*) (void *) ((icon1->item))))),
3798 &rect1.x0, &rect1.y0,
3799 &rect1.x1, &rect1.y1);
3800 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon2->item)((((EelCanvasItem*) (void *) ((icon2->item))))),
3801 &rect2.x0, &rect2.y0,
3802 &rect2.x1, &rect2.y1);
3803
3804 eel_drect_union (&ret, &rect1, &rect2);
3805
3806 return ret;
3807}
3808
3809static void
3810keyboard_move_to (CajaIconContainer *container,
3811 CajaIcon *icon,
3812 CajaIcon *from,
3813 GdkEventKey *event)
3814{
3815 if (icon == NULL((void*)0))
3816 {
3817 return;
3818 }
3819
3820 if (event != NULL((void*)0) &&
3821 (event->state & GDK_CONTROL_MASK) != 0 &&
3822 (event->state & GDK_SHIFT_MASK) == 0)
3823 {
3824 /* Move the keyboard focus. Use Control modifier
3825 * rather than Alt to avoid Sawfish conflict.
3826 */
3827 set_keyboard_focus (container, icon);
3828 container->details->keyboard_rubberband_start = NULL((void*)0);
3829 }
3830 else if (event != NULL((void*)0) &&
3831 ((event->state & GDK_CONTROL_MASK) != 0 ||
3832 !container->details->auto_layout) &&
3833 (event->state & GDK_SHIFT_MASK) != 0)
3834 {
3835 /* Do rubberband selection */
3836 EelDRect rect;
3837
3838 if (from && !container->details->keyboard_rubberband_start)
3839 {
3840 set_keyboard_rubberband_start (container, from);
3841 }
3842
3843 set_keyboard_focus (container, icon);
3844
3845 if (icon && container->details->keyboard_rubberband_start)
3846 {
3847 rect = get_rubberband (container->details->keyboard_rubberband_start,
3848 icon);
3849 rubberband_select (container, NULL((void*)0), &rect);
3850 }
3851 }
3852 else if (event != NULL((void*)0) &&
3853 (event->state & GDK_CONTROL_MASK) == 0 &&
3854 (event->state & GDK_SHIFT_MASK) != 0)
3855 {
3856 /* Select range */
3857 CajaIcon *start_icon;
3858
3859 start_icon = container->details->range_selection_base_icon;
3860 if (start_icon == NULL((void*)0) || !start_icon->is_selected)
3861 {
3862 start_icon = icon;
3863 container->details->range_selection_base_icon = icon;
3864 }
3865
3866 set_keyboard_focus (container, icon);
3867
3868 if (select_range (container, start_icon, icon, TRUE(!(0))))
3869 {
3870 g_signal_emit (container,
3871 signals[SELECTION_CHANGED], 0);
3872 }
3873 }
3874 else
3875 {
3876 /* Select icons and get rid of the special keyboard focus. */
3877 clear_keyboard_focus (container);
3878 clear_keyboard_rubberband_start (container);
3879
3880 container->details->range_selection_base_icon = icon;
3881 if (select_one_unselect_others (container, icon))
3882 {
3883 g_signal_emit (container,
3884 signals[SELECTION_CHANGED], 0);
3885 }
3886 }
3887 schedule_keyboard_icon_reveal (container, icon);
3888}
3889
3890static void
3891keyboard_home (CajaIconContainer *container,
3892 GdkEventKey *event)
3893{
3894 CajaIcon *from;
3895 CajaIcon *to;
3896
3897 /* Home selects the first icon.
3898 * Control-Home sets the keyboard focus to the first icon.
3899 */
3900
3901 from = find_best_selected_icon (container, NULL((void*)0),
3902 rightmost_in_bottom_row,
3903 NULL((void*)0));
3904 to = find_best_icon (container, NULL((void*)0), leftmost_in_top_row, NULL((void*)0));
3905
3906 keyboard_move_to (container, to, from, event);
3907}
3908
3909static void
3910keyboard_end (CajaIconContainer *container,
3911 GdkEventKey *event)
3912{
3913 CajaIcon *to;
3914 CajaIcon *from;
3915
3916 /* End selects the last icon.
3917 * Control-End sets the keyboard focus to the last icon.
3918 */
3919 from = find_best_selected_icon (container, NULL((void*)0),
3920 leftmost_in_top_row,
3921 NULL((void*)0));
3922 to = find_best_icon (container, NULL((void*)0),
3923 caja_icon_container_is_layout_vertical (container) ?
3924 last_column_lowest :
3925 rightmost_in_bottom_row,
3926 NULL((void*)0));
3927
3928 keyboard_move_to (container, to, from, event);
3929}
3930
3931static void
3932record_arrow_key_start (CajaIconContainer *container,
3933 CajaIcon *icon,
3934 GtkDirectionType direction)
3935{
3936 EelDRect world_rect;
3937
3938 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon->item);
3939 eel_canvas_w2c
3940 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
3941 get_cmp_point_x (container, world_rect),
3942 get_cmp_point_y (container, world_rect),
3943 &container->details->arrow_key_start_x,
3944 &container->details->arrow_key_start_y);
3945 container->details->arrow_key_direction = direction;
3946}
3947
3948static void
3949keyboard_arrow_key (CajaIconContainer *container,
3950 GdkEventKey *event,
3951 GtkDirectionType direction,
3952 IsBetterIconFunction better_start,
3953 IsBetterIconFunction empty_start,
3954 IsBetterIconFunction better_destination,
3955 IsBetterIconFunction better_destination_fallback,
3956 IsBetterIconFunction better_destination_fallback_fallback,
3957 IsBetterIconFunction better_destination_manual)
3958{
3959 CajaIcon *from;
3960 CajaIcon *to;
3961 int data;
3962
3963 /* Chose the icon to start with.
3964 * If we have a keyboard focus, start with it.
3965 * Otherwise, use the single selected icon.
3966 * If there's multiple selection, use the icon farthest toward the end.
3967 */
3968
3969 from = container->details->keyboard_focus;
3970
3971 if (from == NULL((void*)0))
3972 {
3973 if (has_multiple_selection (container))
3974 {
3975 if (all_selected (container))
3976 {
3977 from = find_best_selected_icon
3978 (container, NULL((void*)0),
3979 empty_start, NULL((void*)0));
3980 }
3981 else
3982 {
3983 from = find_best_selected_icon
3984 (container, NULL((void*)0),
3985 better_start, NULL((void*)0));
3986 }
3987 }
3988 else
3989 {
3990 from = get_first_selected_icon (container);
3991 }
3992 }
3993
3994 /* If there's no icon, select the icon farthest toward the end.
3995 * If there is an icon, select the next icon based on the arrow direction.
3996 */
3997 if (from == NULL((void*)0))
3998 {
3999 to = from = find_best_icon
4000 (container, NULL((void*)0),
4001 empty_start, NULL((void*)0));
4002 }
4003 else
4004 {
4005 record_arrow_key_start (container, from, direction);
4006
4007 to = find_best_icon
4008 (container, from,
4009 container->details->auto_layout ? better_destination : better_destination_manual,
4010 &data);
4011
4012 /* Wrap around to next/previous row/column */
4013 if (to == NULL((void*)0) &&
4014 better_destination_fallback != NULL((void*)0)) {
4015 to = find_best_icon
4016 (container, from,
4017 better_destination_fallback,
4018 &data);
4019 }
4020
4021 /* With a layout like
4022 * 1 2 3
4023 * 4
4024 * (horizontal layout)
4025 *
4026 * or
4027 *
4028 * 1 4
4029 * 2
4030 * 3
4031 * (vertical layout)
4032 *
4033 * * pressing down for any of 1,2,3 (horizontal layout)
4034 * * pressing right for any of 1,2,3 (vertical layout)
4035 *
4036 * Should select 4.
4037 */
4038 if (to == NULL((void*)0) &&
4039 container->details->auto_layout &&
4040 better_destination_fallback_fallback != NULL((void*)0))
4041 {
4042 to = find_best_icon
4043 (container, from,
4044 better_destination_fallback_fallback,
4045 &data);
4046 }
4047
4048 if (to == NULL((void*)0))
4049 {
4050 to = from;
4051 }
4052
4053 }
4054
4055 keyboard_move_to (container, to, from, event);
4056}
4057
4058static gboolean
4059is_rectangle_selection_event (GdkEventKey *event)
4060{
4061 return (event->state & GDK_CONTROL_MASK) != 0 &&
4062 (event->state & GDK_SHIFT_MASK) != 0;
4063}
4064
4065static void
4066keyboard_right (CajaIconContainer *container,
4067 GdkEventKey *event)
4068{
4069 IsBetterIconFunction fallback;
4070 IsBetterIconFunction next_column_fallback;
4071
4072 fallback = NULL((void*)0);
4073 if (container->details->auto_layout &&
4074 !caja_icon_container_is_layout_vertical (container) &&
4075 !is_rectangle_selection_event (event))
4076 {
4077 fallback = next_row_leftmost;
4078 }
4079
4080 next_column_fallback = NULL((void*)0);
4081 if (caja_icon_container_is_layout_vertical (container) &&
4082 gtk_widget_get_direction (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))) != GTK_TEXT_DIR_RTL)
4083 {
4084 next_column_fallback = next_column_bottommost;
4085 }
4086
4087 /* Right selects the next icon in the same row.
4088 * Control-Right sets the keyboard focus to the next icon in the same row.
4089 */
4090 keyboard_arrow_key (container,
4091 event,
4092 GTK_DIR_RIGHT,
4093 rightmost_in_bottom_row,
4094 caja_icon_container_is_layout_rtl (container) ?
4095 rightmost_in_top_row : leftmost_in_top_row,
4096 same_row_right_side_leftmost,
4097 fallback,
4098 next_column_fallback,
4099 closest_in_90_degrees);
4100}
4101
4102static void
4103keyboard_left (CajaIconContainer *container,
4104 GdkEventKey *event)
4105{
4106 IsBetterIconFunction fallback;
4107 IsBetterIconFunction previous_column_fallback;
4108
4109 fallback = NULL((void*)0);
4110 if (container->details->auto_layout &&
4111 !caja_icon_container_is_layout_vertical (container) &&
4112 !is_rectangle_selection_event (event))
4113 {
4114 fallback = previous_row_rightmost;
4115 }
4116
4117 previous_column_fallback = NULL((void*)0);
4118 if (caja_icon_container_is_layout_vertical (container) &&
4119 gtk_widget_get_direction (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))) == GTK_TEXT_DIR_RTL)
4120 {
4121 previous_column_fallback = previous_column_lowest;
4122 }
4123
4124 /* Left selects the next icon in the same row.
4125 * Control-Left sets the keyboard focus to the next icon in the same row.
4126 */
4127 keyboard_arrow_key (container,
4128 event,
4129 GTK_DIR_LEFT,
4130 rightmost_in_bottom_row,
4131 caja_icon_container_is_layout_rtl (container) ?
4132 rightmost_in_top_row : leftmost_in_top_row,
4133 same_row_left_side_rightmost,
4134 fallback,
4135 previous_column_fallback,
4136 closest_in_90_degrees);
4137}
4138
4139static void
4140keyboard_down (CajaIconContainer *container,
4141 GdkEventKey *event)
4142{
4143 IsBetterIconFunction fallback;
4144 IsBetterIconFunction next_row_fallback;
4145
4146 fallback = NULL((void*)0);
4147 if (container->details->auto_layout &&
4148 caja_icon_container_is_layout_vertical (container) &&
4149 !is_rectangle_selection_event (event))
4150 {
4151 if (gtk_widget_get_direction (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))) == GTK_TEXT_DIR_RTL)
4152 {
4153 fallback = previous_column_highest;
4154 }
4155 else
4156 {
4157 fallback = next_column_highest;
4158 }
4159 }
4160
4161 next_row_fallback = NULL((void*)0);
4162 if (!caja_icon_container_is_layout_vertical (container))
4163 {
4164 if (gtk_widget_get_direction (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))) == GTK_TEXT_DIR_RTL)
4165 {
4166 next_row_fallback = next_row_leftmost;
4167 }
4168 else
4169 {
4170 next_row_fallback = next_row_rightmost;
4171 }
4172 }
4173
4174 /* Down selects the next icon in the same column.
4175 * Control-Down sets the keyboard focus to the next icon in the same column.
4176 */
4177 keyboard_arrow_key (container,
4178 event,
4179 GTK_DIR_DOWN,
4180 rightmost_in_bottom_row,
4181 caja_icon_container_is_layout_rtl (container) ?
4182 rightmost_in_top_row : leftmost_in_top_row,
4183 same_column_below_highest,
4184 fallback,
4185 next_row_fallback,
4186 closest_in_90_degrees);
4187}
4188
4189static void
4190keyboard_up (CajaIconContainer *container,
4191 GdkEventKey *event)
4192{
4193 IsBetterIconFunction fallback;
4194
4195 fallback = NULL((void*)0);
4196 if (container->details->auto_layout &&
4197 caja_icon_container_is_layout_vertical (container) &&
4198 !is_rectangle_selection_event (event))
4199 {
4200 if (gtk_widget_get_direction (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))) == GTK_TEXT_DIR_RTL)
4201 {
4202 fallback = next_column_bottommost;
4203 }
4204 else
4205 {
4206 fallback = previous_column_lowest;
4207 }
4208 }
4209
4210 /* Up selects the next icon in the same column.
4211 * Control-Up sets the keyboard focus to the next icon in the same column.
4212 */
4213 keyboard_arrow_key (container,
4214 event,
4215 GTK_DIR_UP,
4216 rightmost_in_bottom_row,
4217 caja_icon_container_is_layout_rtl (container) ?
4218 rightmost_in_top_row : leftmost_in_top_row,
4219 same_column_above_lowest,
4220 fallback,
4221 NULL((void*)0),
4222 closest_in_90_degrees);
4223}
4224
4225static void
4226keyboard_space (CajaIconContainer *container,
4227 GdkEventKey *event)
4228{
4229 CajaIcon *icon;
4230
4231 if (!has_selection (container) &&
4232 container->details->keyboard_focus != NULL((void*)0))
4233 {
4234 keyboard_move_to (container,
4235 container->details->keyboard_focus,
4236 NULL((void*)0), NULL((void*)0));
4237 }
4238 else if ((event->state & GDK_CONTROL_MASK) != 0 &&
4239 (event->state & GDK_SHIFT_MASK) == 0)
4240 {
4241 /* Control-space toggles the selection state of the current icon. */
4242 if (container->details->keyboard_focus != NULL((void*)0))
4243 {
4244 icon_toggle_selected (container, container->details->keyboard_focus);
4245 g_signal_emit (container, signals[SELECTION_CHANGED], 0);
4246 if (container->details->keyboard_focus->is_selected)
4247 {
4248 container->details->range_selection_base_icon = container->details->keyboard_focus;
4249 }
4250 }
4251 else
4252 {
4253 icon = find_best_selected_icon (container,
4254 NULL((void*)0),
4255 leftmost_in_top_row,
4256 NULL((void*)0));
4257 if (icon == NULL((void*)0))
4258 {
4259 icon = find_best_icon (container,
4260 NULL((void*)0),
4261 leftmost_in_top_row,
4262 NULL((void*)0));
4263 }
4264 if (icon != NULL((void*)0))
4265 {
4266 set_keyboard_focus (container, icon);
4267 }
4268 }
4269 }
4270 else if ((event->state & GDK_SHIFT_MASK) != 0)
4271 {
4272 activate_selected_items_alternate (container, NULL((void*)0));
4273 }
4274 else
4275 {
4276 activate_selected_items (container);
4277 }
4278}
4279
4280/* look for the first icon that matches the longest part of a given
4281 * search pattern
4282 */
4283typedef struct
4284{
4285 gunichar *name;
4286 int last_match_length;
4287} BestNameMatch;
4288
4289#ifndef TAB_NAVIGATION_DISABLED
4290static void
4291select_previous_or_next_icon (CajaIconContainer *container,
4292 gboolean next,
4293 GdkEventKey *event)
4294{
4295 CajaIcon *icon;
4296 const GList *item;
4297
4298 item = NULL((void*)0);
4299 /* Chose the icon to start with.
4300 * If we have a keyboard focus, start with it.
4301 * Otherwise, use the single selected icon.
4302 */
4303 icon = container->details->keyboard_focus;
4304 if (icon == NULL((void*)0))
4305 {
4306 icon = get_first_selected_icon (container);
4307 }
4308
4309 if (icon != NULL((void*)0))
4310 {
4311 /* must have at least @icon in the list */
4312 g_assert (container->details->icons != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_148
; if (container->details->icons != ((void*)0)) _g_boolean_var_148
= 1; else _g_boolean_var_148 = 0; _g_boolean_var_148; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 4312, ((const char*) (__func__)), "container->details->icons != NULL"
); } while (0)
;
4313 item = g_list_find (container->details->icons, icon);
4314 g_assert (item != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if (item != ((void*)0)) _g_boolean_var_149 = 1; else _g_boolean_var_149
= 0; _g_boolean_var_149; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 4314, ((const char*)
(__func__)), "item != NULL"); } while (0)
;
4315
4316 item = next ? item->next : item->prev;
4317 if (item == NULL((void*)0))
4318 {
4319 item = next ? g_list_first (container->details->icons) : g_list_last (container->details->icons);
4320 }
4321
4322 }
4323 else if (container->details->icons != NULL((void*)0))
4324 {
4325 /* no selection yet, pick the first or last item to select */
4326 item = next ? g_list_first (container->details->icons) : g_list_last (container->details->icons);
4327 }
4328
4329 icon = (item != NULL((void*)0)) ? item->data : NULL((void*)0);
4330
4331 if (icon != NULL((void*)0))
4332 {
4333 keyboard_move_to (container, icon, NULL((void*)0), event);
4334 }
4335}
4336#endif
4337
4338static void
4339destroy (GtkWidget *object)
4340{
4341 CajaIconContainer *container;
4342
4343 container = CAJA_ICON_CONTAINER (object)((((CajaIconContainer*) (void *) ((object)))));
4344
4345 caja_icon_container_clear (container);
4346
4347 if (container->details->rubberband_info.timer_id != 0)
4348 {
4349 g_source_remove (container->details->rubberband_info.timer_id);
4350 container->details->rubberband_info.timer_id = 0;
4351 }
4352
4353 if (container->details->idle_id != 0)
4354 {
4355 g_source_remove (container->details->idle_id);
4356 container->details->idle_id = 0;
4357 }
4358
4359 if (container->details->stretch_idle_id != 0)
4360 {
4361 g_source_remove (container->details->stretch_idle_id);
4362 container->details->stretch_idle_id = 0;
4363 }
4364
4365 if (container->details->align_idle_id != 0)
4366 {
4367 g_source_remove (container->details->align_idle_id);
4368 container->details->align_idle_id = 0;
4369 }
4370
4371 if (container->details->selection_changed_id != 0)
4372 {
4373 g_source_remove (container->details->selection_changed_id);
4374 container->details->selection_changed_id = 0;
4375 }
4376
4377 if (container->details->size_allocation_count_id != 0)
4378 {
4379 g_source_remove (container->details->size_allocation_count_id);
4380 container->details->size_allocation_count_id = 0;
4381 }
4382
4383 /* destroy interactive search dialog */
4384 if (container->details->search_window)
4385 {
4386 gtk_widget_destroy (container->details->search_window);
4387 container->details->search_window = NULL((void*)0);
4388 container->details->search_entry = NULL((void*)0);
4389 if (container->details->typeselect_flush_timeout)
4390 {
4391 g_source_remove (container->details->typeselect_flush_timeout);
4392 container->details->typeselect_flush_timeout = 0;
4393 }
4394 }
4395
4396 GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->destroy (object);
4397}
4398
4399static void
4400finalize (GObject *object)
4401{
4402 CajaIconContainerDetails *details;
4403
4404 details = CAJA_ICON_CONTAINER (object)((((CajaIconContainer*) (void *) ((object)))))->details;
4405
4406 g_signal_handlers_disconnect_by_func (caja_icon_view_preferences,g_signal_handlers_disconnect_matched ((caja_icon_view_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_ellipsis_limit_changed_container_callback
), (object))
4407 text_ellipsis_limit_changed_container_callback,g_signal_handlers_disconnect_matched ((caja_icon_view_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_ellipsis_limit_changed_container_callback
), (object))
4408 object)g_signal_handlers_disconnect_matched ((caja_icon_view_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_ellipsis_limit_changed_container_callback
), (object))
;
4409 g_signal_handlers_disconnect_by_func (caja_desktop_preferences,g_signal_handlers_disconnect_matched ((caja_desktop_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_ellipsis_limit_changed_container_callback
), (object))
4410 text_ellipsis_limit_changed_container_callback,g_signal_handlers_disconnect_matched ((caja_desktop_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_ellipsis_limit_changed_container_callback
), (object))
4411 object)g_signal_handlers_disconnect_matched ((caja_desktop_preferences
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (text_ellipsis_limit_changed_container_callback
), (object))
;
4412
4413 g_hash_table_destroy (details->icon_set);
4414 details->icon_set = NULL((void*)0);
4415
4416 g_free (details->font);
4417
4418 if (details->a11y_item_action_queue != NULL((void*)0))
4419 {
4420 while (!g_queue_is_empty (details->a11y_item_action_queue))
4421 {
4422 g_free (g_queue_pop_head (details->a11y_item_action_queue));
4423 }
4424 g_queue_free (details->a11y_item_action_queue);
4425 }
4426 if (details->a11y_item_action_idle_handler != 0)
4427 {
4428 g_source_remove (details->a11y_item_action_idle_handler);
4429 }
4430
4431 g_free (details);
4432
4433 G_OBJECT_CLASS (caja_icon_container_parent_class)((((GObjectClass*) (void *) ((caja_icon_container_parent_class
)))))
->finalize (object);
4434}
4435
4436/* GtkWidget methods. */
4437
4438static gboolean
4439clear_size_allocation_count (gpointer data)
4440{
4441 CajaIconContainer *container;
4442
4443 container = CAJA_ICON_CONTAINER (data)((((CajaIconContainer*) (void *) ((data)))));
4444
4445 container->details->size_allocation_count_id = 0;
4446 container->details->size_allocation_count = 0;
4447
4448 return FALSE(0);
4449}
4450
4451static void
4452size_allocate (GtkWidget *widget,
4453 GtkAllocation *allocation)
4454{
4455 CajaIconContainer *container;
4456 gboolean need_layout_redone;
4457 GtkAllocation wid_allocation;
4458
4459 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
4460
4461 need_layout_redone = !container->details->has_been_allocated;
4462 gtk_widget_get_allocation (widget, &wid_allocation);
4463
4464 if (allocation->width != wid_allocation.width)
4465 {
4466 need_layout_redone = TRUE(!(0));
4467 }
4468
4469 if (allocation->height != wid_allocation.height)
4470 {
4471 need_layout_redone = TRUE(!(0));
4472 }
4473
4474 /* Under some conditions we can end up in a loop when size allocating.
4475 * This happens when the icons don't fit without a scrollbar, but fits
4476 * when a scrollbar is added (bug #129963 for details).
4477 * We keep track of this looping by increasing a counter in size_allocate
4478 * and clearing it in a high-prio idle (the only way to detect the loop is
4479 * done).
4480 * When we've done at more than two iterations (with/without scrollbar)
4481 * we terminate this looping by not redoing the layout when the width
4482 * is wider than the current one (i.e when removing the scrollbar).
4483 */
4484 if (container->details->size_allocation_count_id == 0)
4485 {
4486 container->details->size_allocation_count_id =
4487 g_idle_add_full (G_PRIORITY_HIGH-100,
4488 clear_size_allocation_count,
4489 container, NULL((void*)0));
4490 }
4491 container->details->size_allocation_count++;
4492 if (container->details->size_allocation_count > 2 &&
4493 allocation->width >= wid_allocation.width)
4494 {
4495 need_layout_redone = FALSE(0);
4496 }
4497
4498 GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->size_allocate (widget, allocation);
4499
4500 container->details->has_been_allocated = TRUE(!(0));
4501
4502 if (need_layout_redone)
4503 {
4504 redo_layout (container);
4505 }
4506}
4507
4508static GtkSizeRequestMode
4509get_request_mode (GtkWidget *widget)
4510{
4511 /* Don't trade size at all, since we get whatever we get anyway. */
4512 return GTK_SIZE_REQUEST_CONSTANT_SIZE;
4513}
4514
4515 /* We need to implement these since the GtkScrolledWindow uses them
4516 to guess whether to show scrollbars or not, and if we don't report
4517 anything it'll tend to get it wrong causing double calls
4518 to size_allocate (at different sizes) during its size allocation. */
4519static void
4520get_prefered_width (GtkWidget *widget,
4521 gint *minimum_size,
4522 gint *natural_size)
4523{
4524 EelCanvasGroup *root;
4525 double x1, x2;
4526 int cx1, cx2;
4527 int width;
4528
4529 root = eel_canvas_root (EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget))))));
4530 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (root)((((EelCanvasItem*) (void *) ((root))))),
4531 &x1, NULL((void*)0), &x2, NULL((void*)0));
4532 eel_canvas_w2c (EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget))))), x1, 0, &cx1, NULL((void*)0));
4533 eel_canvas_w2c (EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget))))), x2, 0, &cx2, NULL((void*)0));
4534
4535 width = cx2 - cx1;
4536 if (natural_size) {
4537 *natural_size = width;
4538 }
4539 if (minimum_size) {
4540 *minimum_size = width;
4541 }
4542}
4543
4544static void
4545get_prefered_height (GtkWidget *widget,
4546 gint *minimum_size,
4547 gint *natural_size)
4548{
4549 EelCanvasGroup *root;
4550 double y1, y2;
4551 int cy1, cy2;
4552 int height;
4553
4554 root = eel_canvas_root (EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget))))));
4555 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (root)((((EelCanvasItem*) (void *) ((root))))),
4556 NULL((void*)0), &y1, NULL((void*)0), &y2);
4557 eel_canvas_w2c (EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget))))), 0, y1, NULL((void*)0), &cy1);
4558 eel_canvas_w2c (EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget))))), 0, y2, NULL((void*)0), &cy2);
4559
4560 height = cy2 - cy1;
4561 if (natural_size) {
4562 *natural_size = height;
4563 }
4564 if (minimum_size) {
4565 *minimum_size = height;
4566 }
4567}
4568
4569static gboolean
4570draw (GtkWidget *widget, cairo_t *cr)
4571{
4572 if (!CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->is_desktop)
4573 {
4574 eel_background_draw (widget, cr);
4575 }
4576
4577 return GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->draw (widget,
4578 cr);
4579}
4580
4581static void
4582realize (GtkWidget *widget)
4583{
4584 GtkAdjustment *vadj, *hadj;
4585 CajaIconContainer *container;
4586
4587 GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->realize (widget);
4588
4589 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
4590
4591 /* Set up DnD. */
4592 caja_icon_dnd_init (container);
4593
4594 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (widget)((((GtkScrollable*) (void *) ((widget))))));
4595 g_signal_connect (hadj, "value_changed",g_signal_connect_data ((hadj), ("value_changed"), (((GCallback
) (handle_hadjustment_changed))), (widget), ((void*)0), (GConnectFlags
) 0)
4596 G_CALLBACK (handle_hadjustment_changed), widget)g_signal_connect_data ((hadj), ("value_changed"), (((GCallback
) (handle_hadjustment_changed))), (widget), ((void*)0), (GConnectFlags
) 0)
;
4597
4598 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (widget)((((GtkScrollable*) (void *) ((widget))))));
4599 g_signal_connect (vadj, "value_changed",g_signal_connect_data ((vadj), ("value_changed"), (((GCallback
) (handle_vadjustment_changed))), (widget), ((void*)0), (GConnectFlags
) 0)
4600 G_CALLBACK (handle_vadjustment_changed), widget)g_signal_connect_data ((vadj), ("value_changed"), (((GCallback
) (handle_vadjustment_changed))), (widget), ((void*)0), (GConnectFlags
) 0)
;
4601
4602}
4603
4604static void
4605unrealize (GtkWidget *widget)
4606{
4607 CajaIconContainer *container;
4608
4609 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
4610
4611 caja_icon_dnd_fini (container);
4612
4613 if (container->details->typeselect_flush_timeout)
4614 {
4615 g_source_remove (container->details->typeselect_flush_timeout);
4616 container->details->typeselect_flush_timeout = 0;
4617 }
4618
4619 GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->unrealize (widget);
4620}
4621
4622static void
4623style_updated (GtkWidget *widget)
4624{
4625 CajaIconContainer *container;
4626
4627 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
4628 container->details->use_drop_shadows = container->details->drop_shadows_requested;
4629
4630 /* Don't chain up to parent, if this is a desktop container,
4631 * because that resets the background of the window.
4632 */
4633 if (!caja_icon_container_get_is_desktop (container)) {
4634 GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->style_updated (widget);
4635 }
4636
4637 if (gtk_widget_get_realized (widget))
4638 {
4639 invalidate_labels (container);
4640 caja_icon_container_request_update_all (container);
4641 }
4642}
4643
4644static gboolean
4645button_press_event (GtkWidget *widget,
4646 GdkEventButton *event)
4647{
4648 CajaIconContainer *container;
4649 gboolean selection_changed;
4650 gboolean return_value;
4651 gboolean clicked_on_icon;
4652
4653 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
4654 container->details->button_down_time = event->time;
4655
4656 /* Forget about the old keyboard selection now that we've started mousing. */
4657 clear_keyboard_focus (container);
4658 clear_keyboard_rubberband_start (container);
4659
4660 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
4661 {
4662 /* We use our own double-click detection. */
4663 return TRUE(!(0));
4664 }
4665
4666 /* Invoke the canvas event handler and see if an item picks up the event. */
4667 clicked_on_icon = GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->button_press_event (widget, event);
4668
4669 /* Move focus to icon container, unless we're still renaming (to avoid exiting
4670 * renaming mode)
4671 */
4672 if (!gtk_widget_has_focus (widget) && !(is_renaming (container) || is_renaming_pending (container)))
4673 {
4674 gtk_widget_grab_focus (widget);
4675 }
4676
4677 if (clicked_on_icon)
4678 {
4679 return TRUE(!(0));
4680 }
4681
4682 if (event->button == DRAG_BUTTON1 &&
4683 event->type == GDK_BUTTON_PRESS)
4684 {
4685 /* Clear the last click icon for double click */
4686 container->details->double_click_icon[1] = container->details->double_click_icon[0];
4687 container->details->double_click_icon[0] = NULL((void*)0);
4688 }
4689
4690 /* Button 1 does rubber banding. */
4691 if (event->button == RUBBERBAND_BUTTON1)
4692 {
4693 if (! button_event_modifies_selection (event))
4694 {
4695 selection_changed = unselect_all (container);
4696 if (selection_changed)
4697 {
4698 g_signal_emit (container,
4699 signals[SELECTION_CHANGED], 0);
4700 }
4701 }
4702
4703 start_rubberbanding (container, event);
4704 return TRUE(!(0));
4705 }
4706
4707 /* Prevent multi-button weirdness such as bug 6181 */
4708 if (container->details->rubberband_info.active)
4709 {
4710 return TRUE(!(0));
4711 }
4712
4713 /* Button 2 may be passed to the window manager. */
4714 if (event->button == MIDDLE_BUTTON2)
4715 {
4716 selection_changed = unselect_all (container);
4717 if (selection_changed)
4718 {
4719 g_signal_emit (container, signals[SELECTION_CHANGED], 0);
4720 }
4721 g_signal_emit (widget, signals[MIDDLE_CLICK], 0, event);
4722 return TRUE(!(0));
4723 }
4724
4725 /* Button 3 does a contextual menu. */
4726 if (event->button == CONTEXTUAL_MENU_BUTTON3)
4727 {
4728 end_renaming_mode (container, TRUE(!(0)));
4729 selection_changed = unselect_all (container);
4730 if (selection_changed)
4731 {
4732 g_signal_emit (container, signals[SELECTION_CHANGED], 0);
4733 }
4734 g_signal_emit (widget, signals[CONTEXT_CLICK_BACKGROUND], 0, event);
4735 return TRUE(!(0));
4736 }
4737
4738 /* Otherwise, we emit a button_press message. */
4739 g_signal_emit (widget,
4740 signals[BUTTON_PRESS], 0, event,
4741 &return_value);
4742 return return_value;
4743}
4744
4745static void
4746caja_icon_container_did_not_drag (CajaIconContainer *container,
4747 GdkEventButton *event)
4748{
4749 CajaIconContainerDetails *details;
4750 gboolean selection_changed;
4751 static gint64 last_click_time = 0;
4752 static gint click_count = 0;
4753 gint double_click_time;
4754 gint64 current_time;
4755
4756 details = container->details;
4757
4758 if (details->icon_selected_on_button_down &&
4759 ((event->state & GDK_CONTROL_MASK) != 0 ||
4760 (event->state & GDK_SHIFT_MASK) == 0))
4761 {
4762 if (button_event_modifies_selection (event))
4763 {
4764 details->range_selection_base_icon = NULL((void*)0);
4765 icon_toggle_selected (container, details->drag_icon);
4766 g_signal_emit (container,
4767 signals[SELECTION_CHANGED], 0);
4768 }
4769 else
4770 {
4771 details->range_selection_base_icon = details->drag_icon;
4772 selection_changed = select_one_unselect_others
4773 (container, details->drag_icon);
4774
4775 if (selection_changed)
4776 {
4777 g_signal_emit (container,
4778 signals[SELECTION_CHANGED], 0);
4779 }
4780 }
4781 }
4782
4783 if (details->drag_icon != NULL((void*)0) &&
4784 (details->single_click_mode ||
4785 event->button == MIDDLE_BUTTON2))
4786 {
4787 /* Determine click count */
4788 g_object_get (G_OBJECT (gtk_widget_get_settings (GTK_WIDGET (container)))((((GObject*) (void *) ((gtk_widget_get_settings (((((GtkWidget
*) (void *) ((container)))))))))))
,
4789 "gtk-double-click-time", &double_click_time,
4790 NULL((void*)0));
4791 current_time = g_get_monotonic_time ();
4792 if (current_time - last_click_time < double_click_time * 1000)
4793 {
4794 click_count++;
4795 }
4796 else
4797 {
4798 click_count = 0;
4799 }
4800
4801 /* Stash time for next compare */
4802 last_click_time = current_time;
4803
4804 /* If single-click mode, activate the selected icons, unless modifying
4805 * the selection or pressing for a very long time, or double clicking.
4806 */
4807
4808
4809 if (click_count == 0 &&
4810 event->time - details->button_down_time < MAX_CLICK_TIME1500 &&
4811 ! button_event_modifies_selection (event))
4812 {
4813
4814 /* It's a tricky UI issue whether this should activate
4815 * just the clicked item (as if it were a link), or all
4816 * the selected items (as if you were issuing an "activate
4817 * selection" command). For now, we're trying the activate
4818 * entire selection version to see how it feels. Note that
4819 * CajaList goes the other way because its "links" seem
4820 * much more link-like.
4821 */
4822 if (event->button == MIDDLE_BUTTON2)
4823 {
4824 activate_selected_items_alternate (container, NULL((void*)0));
4825 }
4826 else
4827 {
4828 activate_selected_items (container);
4829 }
4830 }
4831 }
4832}
4833
4834static gboolean
4835clicked_within_double_click_interval (CajaIconContainer *container)
4836{
4837 static gint64 last_click_time = 0;
4838 static gint click_count = 0;
4839 gint double_click_time;
4840 gint64 current_time;
4841
4842 /* Determine click count */
4843 g_object_get (G_OBJECT (gtk_widget_get_settings (GTK_WIDGET (container)))((((GObject*) (void *) ((gtk_widget_get_settings (((((GtkWidget
*) (void *) ((container)))))))))))
,
4844 "gtk-double-click-time", &double_click_time,
4845 NULL((void*)0));
4846 current_time = g_get_monotonic_time ();
4847 if (current_time - last_click_time < double_click_time * 1000)
4848 {
4849 click_count++;
4850 }
4851 else
4852 {
4853 click_count = 0;
4854 }
4855
4856 /* Stash time for next compare */
4857 last_click_time = current_time;
4858
4859 /* Only allow double click */
4860 if (click_count == 1) {
4861 click_count = 0;
4862 return TRUE(!(0));
4863 } else {
4864 return FALSE(0);
4865 }
4866}
4867
4868static void
4869clear_drag_state (CajaIconContainer *container)
4870{
4871 container->details->drag_icon = NULL((void*)0);
4872 container->details->drag_state = DRAG_STATE_INITIAL;
4873}
4874
4875static gboolean
4876start_stretching (CajaIconContainer *container,
4877 GdkEvent *event)
4878{
4879 CajaIconContainerDetails *details;
4880 CajaIcon *icon;
4881 EelDPoint world_point;
4882 GtkWidget *toplevel;
4883 GdkDisplay *display;
4884 GtkCornerType corner;
4885 GdkCursor *cursor;
4886
4887 details = container->details;
4888 icon = details->stretch_icon;
4889 display = gtk_widget_get_display (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
4890
4891 /* Check if we hit the stretch handles. */
4892 world_point.x = details->drag_x;
4893 world_point.y = details->drag_y;
4894 if (!caja_icon_canvas_item_hit_test_stretch_handles (icon->item, world_point, &corner))
4895 {
4896 return FALSE(0);
4897 }
4898
4899 switch (corner)
4900 {
4901 case GTK_CORNER_TOP_LEFT:
4902 cursor = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_CORNER);
4903 break;
4904 case GTK_CORNER_BOTTOM_LEFT:
4905 cursor = gdk_cursor_new_for_display (display, GDK_BOTTOM_LEFT_CORNER);
4906 break;
4907 case GTK_CORNER_TOP_RIGHT:
4908 cursor = gdk_cursor_new_for_display (display, GDK_TOP_RIGHT_CORNER);
4909 break;
4910 case GTK_CORNER_BOTTOM_RIGHT:
4911 cursor = gdk_cursor_new_for_display (display, GDK_BOTTOM_RIGHT_CORNER);
4912 break;
4913 default:
4914 cursor = NULL((void*)0);
4915 break;
4916 }
4917 /* Set up the dragging. */
4918 details->drag_state = DRAG_STATE_STRETCH;
4919 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
4920 details->drag_x,
4921 details->drag_y,
4922 &details->stretch_start.pointer_x,
4923 &details->stretch_start.pointer_y);
4924 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
4925 icon->x, icon->y,
4926 &details->stretch_start.icon_x,
4927 &details->stretch_start.icon_y);
4928 icon_get_size (container, icon,
4929 &details->stretch_start.icon_size);
4930
4931 eel_canvas_item_grab (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
4932 (GDK_POINTER_MOTION_MASK
4933 | GDK_BUTTON_RELEASE_MASK),
4934 cursor,
4935 event);
4936
4937 if (cursor)
4938 g_object_unref (cursor);
4939
4940 /* Ensure the window itself is focused.. */
4941 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
4942 if (toplevel != NULL((void*)0) && gtk_widget_get_realized (toplevel))
4943 {
4944 gdk_window_focus (gtk_widget_get_window (toplevel), GDK_CURRENT_TIME0L);
4945 }
4946
4947 return TRUE(!(0));
4948}
4949
4950static gboolean
4951update_stretch_at_idle (CajaIconContainer *container)
4952{
4953 CajaIconContainerDetails *details;
4954 CajaIcon *icon;
4955 double world_x, world_y;
4956 StretchState stretch_state;
4957
4958 details = container->details;
4959 icon = details->stretch_icon;
4960
4961 if (icon == NULL((void*)0))
4962 {
4963 container->details->stretch_idle_id = 0;
4964 return FALSE(0);
4965 }
4966
4967 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
4968 details->world_x, details->world_y,
4969 &stretch_state.pointer_x, &stretch_state.pointer_y);
4970
4971 compute_stretch (&details->stretch_start,
4972 &stretch_state);
4973
4974 eel_canvas_c2w (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
4975 stretch_state.icon_x, stretch_state.icon_y,
4976 &world_x, &world_y);
4977
4978 icon_set_position (icon, world_x, world_y);
4979 icon_set_size (container, icon, stretch_state.icon_size, FALSE(0), FALSE(0));
4980
4981 container->details->stretch_idle_id = 0;
4982
4983 return FALSE(0);
4984}
4985
4986static void
4987continue_stretching (CajaIconContainer *container,
4988 double world_x, double world_y)
4989{
4990
4991 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_150 = 1; else _g_boolean_var_150 =
0; _g_boolean_var_150; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
4992
4993 container->details->world_x = world_x;
4994 container->details->world_y = world_y;
4995
4996 if (container->details->stretch_idle_id == 0)
4997 {
4998 container->details->stretch_idle_id = g_idle_add ((GSourceFunc) update_stretch_at_idle, container);
4999 }
5000}
5001
5002static gboolean
5003keyboard_stretching (CajaIconContainer *container,
5004 GdkEventKey *event)
5005{
5006 CajaIcon *icon;
5007 guint size;
5008
5009 icon = container->details->stretch_icon;
5010
5011 if (icon == NULL((void*)0) || !icon->is_selected)
5012 {
5013 return FALSE(0);
5014 }
5015
5016 icon_get_size (container, icon, &size);
5017
5018 switch (event->keyval)
5019 {
5020 case GDK_KEY_equal0x03d:
5021 case GDK_KEY_plus0x02b:
5022 case GDK_KEY_KP_Add0xffab:
5023 icon_set_size (container, icon, size + 5, FALSE(0), FALSE(0));
5024 break;
5025 case GDK_KEY_minus0x02d:
5026 case GDK_KEY_KP_Subtract0xffad:
5027 icon_set_size (container, icon, size - 5, FALSE(0), FALSE(0));
5028 break;
5029 case GDK_KEY_00x030:
5030 case GDK_KEY_KP_00xffb0:
5031 caja_icon_container_move_icon (container, icon,
5032 icon->x, icon->y,
5033 1.0,
5034 FALSE(0), TRUE(!(0)), TRUE(!(0)));
5035 break;
5036 }
5037
5038 return TRUE(!(0));
5039}
5040
5041static void
5042ungrab_stretch_icon (CajaIconContainer *container)
5043{
5044 eel_canvas_item_ungrab (EEL_CANVAS_ITEM (container->details->stretch_icon->item)((((EelCanvasItem*) (void *) ((container->details->stretch_icon
->item)))))
);
5045}
5046
5047static void
5048end_stretching (CajaIconContainer *container,
5049 double world_x, double world_y)
5050{
5051 CajaIconPosition position;
5052 CajaIcon *icon;
5053
5054 continue_stretching (container, world_x, world_y);
5055 ungrab_stretch_icon (container);
5056
5057 /* now that we're done stretching, update the icon's position */
5058
5059 icon = container->details->drag_icon;
5060 if (caja_icon_container_is_layout_rtl (container))
5061 {
5062 position.x = icon->saved_ltr_x = get_mirror_x_position (container, icon, icon->x);
5063 }
5064 else
5065 {
5066 position.x = icon->x;
5067 }
5068 position.y = icon->y;
5069 position.scale = icon->scale;
5070 g_signal_emit (container,
5071 signals[ICON_POSITION_CHANGED], 0,
5072 icon->data, &position);
5073
5074 clear_drag_state (container);
5075 redo_layout (container);
5076}
5077
5078static gboolean
5079undo_stretching (CajaIconContainer *container)
5080{
5081 CajaIcon *stretched_icon;
5082
5083 stretched_icon = container->details->stretch_icon;
5084
5085 if (stretched_icon == NULL((void*)0))
5086 {
5087 return FALSE(0);
5088 }
5089
5090 if (container->details->drag_state == DRAG_STATE_STRETCH)
5091 {
5092 ungrab_stretch_icon (container);
5093 clear_drag_state (container);
5094 }
5095 caja_icon_canvas_item_set_show_stretch_handles
5096 (stretched_icon->item, FALSE(0));
5097
5098 icon_set_position (stretched_icon,
5099 container->details->stretch_initial_x,
5100 container->details->stretch_initial_y);
5101 icon_set_size (container,
5102 stretched_icon,
5103 container->details->stretch_initial_size,
5104 TRUE(!(0)),
5105 TRUE(!(0)));
5106
5107 container->details->stretch_icon = NULL((void*)0);
5108 emit_stretch_ended (container, stretched_icon);
5109 redo_layout (container);
5110
5111 return TRUE(!(0));
5112}
5113
5114static gboolean
5115button_release_event (GtkWidget *widget,
5116 GdkEventButton *event)
5117{
5118 CajaIconContainer *container;
5119 CajaIconContainerDetails *details;
5120 double world_x, world_y;
5121
5122 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
5123 details = container->details;
5124
5125 if (event->button == RUBBERBAND_BUTTON1 && details->rubberband_info.active)
5126 {
5127 stop_rubberbanding (container);
5128 return TRUE(!(0));
5129 }
5130
5131 if (event->button == details->drag_button)
5132 {
5133 details->drag_button = 0;
5134
5135 switch (details->drag_state)
5136 {
5137 case DRAG_STATE_MOVE_OR_COPY:
5138 if (!details->drag_started)
5139 {
5140 caja_icon_container_did_not_drag (container, event);
5141 }
5142 else
5143 {
5144 caja_icon_dnd_end_drag (container);
5145 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
5146 "end drag from icon container");
5147 }
5148 break;
5149 case DRAG_STATE_STRETCH:
5150 eel_canvas_window_to_world
5151 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), event->x, event->y, &world_x, &world_y);
5152 end_stretching (container, world_x, world_y);
5153 break;
5154 default:
5155 break;
5156 }
5157
5158 clear_drag_state (container);
5159 return TRUE(!(0));
5160 }
5161
5162 return GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->button_release_event (widget, event);
5163}
5164
5165static int
5166motion_notify_event (GtkWidget *widget,
5167 GdkEventMotion *event)
5168{
5169 CajaIconContainer *container;
5170 CajaIconContainerDetails *details;
5171 double world_x, world_y;
5172 int canvas_x, canvas_y;
5173 GdkDragAction actions;
5174
5175 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
5176 details = container->details;
5177
5178 if (details->drag_button != 0)
5179 {
5180 switch (details->drag_state)
5181 {
5182 case DRAG_STATE_MOVE_OR_COPY:
5183 if (details->drag_started)
5184 {
5185 break;
5186 }
5187
5188 eel_canvas_window_to_world
5189 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), event->x, event->y, &world_x, &world_y);
5190
5191 if (gtk_drag_check_threshold (widget,
5192 details->drag_x,
5193 details->drag_y,
5194 world_x,
5195 world_y))
5196 {
5197 details->drag_started = TRUE(!(0));
5198 details->drag_state = DRAG_STATE_MOVE_OR_COPY;
5199
5200 end_renaming_mode (container, TRUE(!(0)));
5201
5202 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
5203 details->drag_x,
5204 details->drag_y,
5205 &canvas_x,
5206 &canvas_y);
5207
5208 actions = GDK_ACTION_COPY
5209 | GDK_ACTION_LINK
5210 | GDK_ACTION_ASK;
5211
5212 if (container->details->drag_allow_moves)
5213 {
5214 actions |= GDK_ACTION_MOVE;
5215 }
5216
5217 caja_icon_dnd_begin_drag (container,
5218 actions,
5219 details->drag_button,
5220 event,
5221 canvas_x,
5222 canvas_y);
5223 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
5224 "begin drag from icon container");
5225 }
5226 break;
5227 case DRAG_STATE_STRETCH:
5228 eel_canvas_window_to_world
5229 (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), event->x, event->y, &world_x, &world_y);
5230 continue_stretching (container, world_x, world_y);
5231 break;
5232 default:
5233 break;
5234 }
5235 }
5236
5237 return GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->motion_notify_event (widget, event);
5238}
5239
5240static void
5241caja_icon_container_search_position_func (CajaIconContainer *container,
5242 GtkWidget *search_dialog)
5243{
5244 gint x, y;
5245 gint cont_x, cont_y;
5246 gint cont_width, cont_height;
5247 gint scale;
5248 GdkWindow *cont_window;
5249 GdkScreen *screen;
5250 GtkRequisition requisition;
5251 GdkMonitor *monitor_num;
5252 GdkRectangle monitor;
5253
5254
5255 cont_window = gtk_widget_get_window (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
5256 scale = gtk_widget_get_scale_factor (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
5257 screen = gdk_window_get_screen (cont_window);
5258
5259 monitor_num = gdk_display_get_monitor_at_window (gdk_screen_get_display (screen),
5260 cont_window);
5261 gdk_monitor_get_geometry (monitor_num, &monitor);
5262
5263 gtk_widget_realize (search_dialog);
5264
5265 gdk_window_get_origin (cont_window, &cont_x, &cont_y);
5266
5267 cont_width = gdk_window_get_width (cont_window);
5268 cont_height = gdk_window_get_height (cont_window);
5269
5270 gtk_widget_get_preferred_size (search_dialog, &requisition, NULL((void*)0));
5271
5272 if (cont_x + cont_width - requisition.width > WidthOfScreen (gdk_x11_screen_get_xscreen (screen))((gdk_x11_screen_get_xscreen (screen))->width) / scale)
5273 {
5274 x = WidthOfScreen (gdk_x11_screen_get_xscreen (screen))((gdk_x11_screen_get_xscreen (screen))->width) / scale - requisition.width;
5275 }
5276 else if (cont_x + cont_width - requisition.width < 0)
5277 {
5278 x = 0;
5279 }
5280 else
5281 {
5282 x = cont_x + cont_width - requisition.width;
5283 }
5284
5285 if (cont_y + cont_height > HeightOfScreen (gdk_x11_screen_get_xscreen (screen))((gdk_x11_screen_get_xscreen (screen))->height))
5286 {
5287 y = HeightOfScreen (gdk_x11_screen_get_xscreen (screen))((gdk_x11_screen_get_xscreen (screen))->height) - requisition.height;
5288 }
5289 else if (cont_y + cont_height < 0) /* isn't really possible ... */
5290 {
5291 y = 0;
5292 }
5293 else
5294 {
5295 y = cont_y + cont_height;
5296 }
5297
5298 gtk_window_move (GTK_WINDOW (search_dialog)((((GtkWindow*) (void *) ((search_dialog))))), x, y);
5299}
5300
5301static gboolean
5302caja_icon_container_real_search_enable_popdown (gpointer data)
5303{
5304 CajaIconContainer *container = (CajaIconContainer *)data;
5305
5306 container->details->disable_popdown = FALSE(0);
5307
5308 g_object_unref (container);
5309
5310 return FALSE(0);
5311}
5312
5313static void
5314caja_icon_container_search_enable_popdown (GtkWidget *widget,
5315 gpointer data)
5316{
5317 CajaIconContainer *container = (CajaIconContainer *) data;
5318
5319 g_object_ref (container)((__typeof__ (container)) (g_object_ref) (container));
5320 g_timeout_add (200, caja_icon_container_real_search_enable_popdown, data);
5321}
5322
5323static void
5324caja_icon_container_search_disable_popdown (GtkEntry *entry,
5325 GtkMenu *menu,
5326 gpointer data)
5327{
5328 CajaIconContainer *container = (CajaIconContainer *) data;
5329
5330 container->details->disable_popdown = TRUE(!(0));
5331 g_signal_connect (menu, "hide",g_signal_connect_data ((menu), ("hide"), (((GCallback) (caja_icon_container_search_enable_popdown
))), (data), ((void*)0), (GConnectFlags) 0)
5332 G_CALLBACK (caja_icon_container_search_enable_popdown),g_signal_connect_data ((menu), ("hide"), (((GCallback) (caja_icon_container_search_enable_popdown
))), (data), ((void*)0), (GConnectFlags) 0)
5333 data)g_signal_connect_data ((menu), ("hide"), (((GCallback) (caja_icon_container_search_enable_popdown
))), (data), ((void*)0), (GConnectFlags) 0)
;
5334}
5335
5336/* Cut and paste from gtkwindow.c */
5337static void
5338send_focus_change (GtkWidget *widget, gboolean in)
5339{
5340 GdkEvent *fevent;
5341
5342 fevent = gdk_event_new (GDK_FOCUS_CHANGE);
5343
5344 g_object_ref (widget)((__typeof__ (widget)) (g_object_ref) (widget));
5345 ((GdkEventFocus *) fevent)->in = in;
5346
5347 gtk_widget_send_focus_change (widget, fevent);
5348
5349 fevent->focus_change.type = GDK_FOCUS_CHANGE;
5350 fevent->focus_change.window = g_object_ref (gtk_widget_get_window (widget))((__typeof__ (gtk_widget_get_window (widget))) (g_object_ref)
(gtk_widget_get_window (widget)))
;
5351 fevent->focus_change.in = in;
5352
5353 gtk_widget_event (widget, fevent);
5354
5355 g_object_notify (G_OBJECT (widget)((((GObject*) (void *) ((widget))))), "has-focus");
5356
5357 g_object_unref (widget);
5358 gdk_event_free (fevent);
5359}
5360
5361static void
5362caja_icon_container_search_dialog_hide (GtkWidget *search_dialog,
5363 CajaIconContainer *container)
5364{
5365 if (container->details->disable_popdown)
5366 {
5367 return;
5368 }
5369
5370 if (container->details->search_entry_changed_id)
5371 {
5372 g_signal_handler_disconnect (container->details->search_entry,
5373 container->details->search_entry_changed_id);
5374 container->details->search_entry_changed_id = 0;
5375 }
5376 if (container->details->typeselect_flush_timeout)
5377 {
5378 g_source_remove (container->details->typeselect_flush_timeout);
5379 container->details->typeselect_flush_timeout = 0;
5380 }
5381
5382 /* send focus-in event */
5383 send_focus_change (GTK_WIDGET (container->details->search_entry)((((GtkWidget*) (void *) ((container->details->search_entry
)))))
, FALSE(0));
5384 gtk_widget_hide (search_dialog);
5385 gtk_entry_set_text (GTK_ENTRY (container->details->search_entry)((((GtkEntry*) (void *) ((container->details->search_entry
)))))
, "");
5386}
5387
5388static gboolean
5389caja_icon_container_search_entry_flush_timeout (CajaIconContainer *container)
5390{
5391 caja_icon_container_search_dialog_hide (container->details->search_window, container);
5392
5393 return TRUE(!(0));
5394}
5395
5396/* Because we're visible but offscreen, we just set a flag in the preedit
5397 * callback.
5398 */
5399static void
5400caja_icon_container_search_preedit_changed (GtkEntry *entry,
5401 gchar *preedit,
5402 CajaIconContainer *container)
5403{
5404 container->details->imcontext_changed = 1;
5405 if (container->details->typeselect_flush_timeout)
5406 {
5407 g_source_remove (container->details->typeselect_flush_timeout);
5408 container->details->typeselect_flush_timeout =
5409 g_timeout_add_seconds (CAJA_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT5,
5410 (GSourceFunc) caja_icon_container_search_entry_flush_timeout,
5411 container);
5412 }
5413}
5414
5415static void
5416caja_icon_container_search_activate (GtkEntry *entry,
5417 CajaIconContainer *container)
5418{
5419 caja_icon_container_search_dialog_hide (container->details->search_window,
5420 container);
5421
5422 activate_selected_items (container);
5423}
5424
5425static gboolean
5426caja_icon_container_search_delete_event (GtkWidget *widget,
5427 GdkEventAny *event,
5428 CajaIconContainer *container)
5429{
5430 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_151
= 1; else _g_boolean_var_151 = 0; _g_boolean_var_151; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 5430, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
5431
5432 caja_icon_container_search_dialog_hide (widget, container);
5433
5434 return TRUE(!(0));
5435}
5436
5437static gboolean
5438caja_icon_container_search_button_press_event (GtkWidget *widget,
5439 GdkEventButton *event,
5440 CajaIconContainer *container)
5441{
5442 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_152
= 1; else _g_boolean_var_152 = 0; _g_boolean_var_152; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 5442, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
5443
5444 caja_icon_container_search_dialog_hide (widget, container);
5445
5446 if (event->window == gtk_layout_get_bin_window (GTK_LAYOUT (container)((((GtkLayout*) (void *) ((container)))))))
5447 {
5448 button_press_event (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), event);
5449 }
5450
5451 return TRUE(!(0));
5452}
5453
5454static void
5455caja_icon_container_get_icon_text (CajaIconContainer *container,
5456 CajaIconData *data,
5457 char **editable_text,
5458 char **additional_text,
5459 gboolean include_invisible)
5460{
5461 CajaIconContainerClass *klass;
5462
5463 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
5464 g_assert (klass->get_icon_text != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if (klass->get_icon_text != ((void*)0)) _g_boolean_var_153
= 1; else _g_boolean_var_153 = 0; _g_boolean_var_153; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 5464, ((const char*) (__func__)), "klass->get_icon_text != NULL"
); } while (0)
;
5465
5466 klass->get_icon_text (container, data, editable_text, additional_text, include_invisible);
5467}
5468
5469static gboolean
5470caja_icon_container_search_iter (CajaIconContainer *container,
5471 const char *key, gint n)
5472{
5473 GList *p;
5474 CajaIcon *icon;
5475 char *name;
5476 int count;
5477 char *normalized_key, *case_normalized_key;
5478 char *normalized_name, *case_normalized_name;
5479
5480 g_assert (key != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if (key != ((void*)0)) _g_boolean_var_154 = 1; else _g_boolean_var_154
= 0; _g_boolean_var_154; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 5480, ((const char*)
(__func__)), "key != NULL"); } while (0)
;
5481 g_assert (n >= 1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if (n >= 1) _g_boolean_var_155 = 1; else _g_boolean_var_155
= 0; _g_boolean_var_155; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 5481, ((const char*)
(__func__)), "n >= 1"); } while (0)
;
5482
5483 normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
5484 if (!normalized_key)
5485 {
5486 return FALSE(0);
5487 }
5488 case_normalized_key = g_utf8_casefold (normalized_key, -1);
5489 g_free (normalized_key);
5490 if (!case_normalized_key)
5491 {
5492 return FALSE(0);
5493 }
5494
5495 icon = NULL((void*)0);
5496 name = NULL((void*)0);
5497 count = 0;
5498 for (p = container->details->icons; p != NULL((void*)0) && count != n; p = p->next)
5499 {
5500 icon = p->data;
5501 caja_icon_container_get_icon_text (container, icon->data, &name,
5502 NULL((void*)0), TRUE(!(0)));
5503
5504 /* This can happen if a key event is handled really early while
5505 * loading the icon container, before the items have all been
5506 * updated once.
5507 */
5508 if (!name)
5509 {
5510 continue;
5511 }
5512
5513 normalized_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
5514 if (!normalized_name)
5515 {
5516 continue;
5517 }
5518 case_normalized_name = g_utf8_casefold (normalized_name, -1);
5519 g_free (normalized_name);
5520 if (!case_normalized_name)
5521 {
5522 continue;
5523 }
5524
5525 if (strncmp (case_normalized_key, case_normalized_name,
5526 strlen (case_normalized_key)) == 0)
5527 {
5528 count++;
5529 }
5530
5531 g_free (case_normalized_name);
5532 g_free (name);
5533 name = NULL((void*)0);
5534 }
5535
5536 g_free (case_normalized_key);
5537
5538 if (count == n)
5539 {
5540 if (select_one_unselect_others (container, icon))
5541 {
5542 g_signal_emit (container, signals[SELECTION_CHANGED], 0);
5543 }
5544 schedule_keyboard_icon_reveal (container, icon);
5545
5546 return TRUE(!(0));
5547 }
5548
5549 return FALSE(0);
5550}
5551
5552static void
5553caja_icon_container_search_move (GtkWidget *window,
5554 CajaIconContainer *container,
5555 gboolean up)
5556{
5557 gboolean ret;
5558 gint len;
5559 const gchar *text;
5560
5561 text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry)((((GtkEntry*) (void *) ((container->details->search_entry
)))))
);
5562
5563 g_assert (text != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if (text != ((void*)0)) _g_boolean_var_156 = 1; else _g_boolean_var_156
= 0; _g_boolean_var_156; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 5563, ((const char*)
(__func__)), "text != NULL"); } while (0)
;
5564
5565 if (container->details->selected_iter == 0)
5566 {
5567 return;
5568 }
5569
5570 if (up && container->details->selected_iter == 1)
5571 {
5572 return;
5573 }
5574
5575 len = strlen (text);
5576
5577 if (len < 1)
5578 {
5579 return;
5580 }
5581
5582 /* search */
5583 unselect_all (container);
5584
5585 ret = caja_icon_container_search_iter (container, text,
5586 up?((container->details->selected_iter) - 1):((container->details->selected_iter + 1)));
5587
5588 if (ret)
5589 {
5590 /* found */
5591 container->details->selected_iter += up?(-1):(1);
5592 }
5593 else
5594 {
5595 /* return to old iter */
5596 caja_icon_container_search_iter (container, text,
5597 container->details->selected_iter);
5598 }
5599}
5600
5601static gboolean
5602caja_icon_container_search_scroll_event (GtkWidget *widget,
5603 GdkEventScroll *event,
5604 CajaIconContainer *container)
5605{
5606 gboolean retval = FALSE(0);
5607
5608 if (event->direction == GDK_SCROLL_UP)
5609 {
5610 caja_icon_container_search_move (widget, container, TRUE(!(0)));
5611 retval = TRUE(!(0));
5612 }
5613 else if (event->direction == GDK_SCROLL_DOWN)
5614 {
5615 caja_icon_container_search_move (widget, container, FALSE(0));
5616 retval = TRUE(!(0));
5617 }
5618
5619 /* renew the flush timeout */
5620 if (retval && container->details->typeselect_flush_timeout)
5621 {
5622 g_source_remove (container->details->typeselect_flush_timeout);
5623 container->details->typeselect_flush_timeout =
5624 g_timeout_add_seconds (CAJA_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT5,
5625 (GSourceFunc) caja_icon_container_search_entry_flush_timeout,
5626 container);
5627 }
5628
5629 return retval;
5630}
5631
5632static gboolean
5633caja_icon_container_search_key_press_event (GtkWidget *widget,
5634 GdkEventKey *event,
5635 CajaIconContainer *container)
5636{
5637 gboolean retval = FALSE(0);
5638
5639 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 5639, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
5640 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 5640, ((const char*)
(__func__)), "CAJA_IS_ICON_CONTAINER (container)"); } while (
0)
;
5641
5642 /* close window and cancel the search */
5643 if (event->keyval == GDK_KEY_Escape0xff1b || event->keyval == GDK_KEY_Tab0xff09)
5644 {
5645 caja_icon_container_search_dialog_hide (widget, container);
5646 return TRUE(!(0));
5647 }
5648
5649 /* close window and activate alternate */
5650 if (event->keyval == GDK_KEY_Return0xff0d && event->state & GDK_SHIFT_MASK)
5651 {
5652 caja_icon_container_search_dialog_hide (widget,
5653 container);
5654
5655 activate_selected_items_alternate (container, NULL((void*)0));
5656 return TRUE(!(0));
5657 }
5658
5659 /* select previous matching iter */
5660 if (event->keyval == GDK_KEY_Up0xff52 || event->keyval == GDK_KEY_KP_Up0xff97)
5661 {
5662 caja_icon_container_search_move (widget, container, TRUE(!(0)));
5663 retval = TRUE(!(0));
5664 }
5665
5666 if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
5667 && (event->keyval == GDK_KEY_g0x067 || event->keyval == GDK_KEY_G0x047))
5668 {
5669 caja_icon_container_search_move (widget, container, TRUE(!(0)));
5670 retval = TRUE(!(0));
5671 }
5672
5673 /* select next matching iter */
5674 if (event->keyval == GDK_KEY_Down0xff54 || event->keyval == GDK_KEY_KP_Down0xff99)
5675 {
5676 caja_icon_container_search_move (widget, container, FALSE(0));
5677 retval = TRUE(!(0));
5678 }
5679
5680 if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
5681 && (event->keyval == GDK_KEY_g0x067 || event->keyval == GDK_KEY_G0x047))
5682 {
5683 caja_icon_container_search_move (widget, container, FALSE(0));
5684 retval = TRUE(!(0));
5685 }
5686
5687 /* renew the flush timeout */
5688 if (retval && container->details->typeselect_flush_timeout)
5689 {
5690 g_source_remove (container->details->typeselect_flush_timeout);
5691 container->details->typeselect_flush_timeout =
5692 g_timeout_add_seconds (CAJA_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT5,
5693 (GSourceFunc) caja_icon_container_search_entry_flush_timeout,
5694 container);
5695 }
5696
5697 return retval;
5698}
5699
5700static void
5701caja_icon_container_search_init (GtkWidget *entry,
5702 CajaIconContainer *container)
5703{
5704 gint ret;
5705 gint len;
5706 const gchar *text;
5707
5708 g_assert (GTK_IS_ENTRY (entry))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((entry)); GType __t = ((gtk_entry_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_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 5708, ((const char*) (__func__)), "GTK_IS_ENTRY (entry)"); }
while (0)
;
5709 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_160 = 1; else _g_boolean_var_160 =
0; _g_boolean_var_160; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 5709, ((const char*)
(__func__)), "CAJA_IS_ICON_CONTAINER (container)"); } while (
0)
;
5710
5711 text = gtk_entry_get_text (GTK_ENTRY (entry)((((GtkEntry*) (void *) ((entry))))));
5712 len = strlen (text);
5713
5714 /* search */
5715 unselect_all (container);
5716 if (container->details->typeselect_flush_timeout)
5717 {
5718 g_source_remove (container->details->typeselect_flush_timeout);
5719 container->details->typeselect_flush_timeout =
5720 g_timeout_add_seconds (CAJA_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT5,
5721 (GSourceFunc) caja_icon_container_search_entry_flush_timeout,
5722 container);
5723 }
5724
5725 if (len < 1)
5726 {
5727 return;
5728 }
5729
5730 ret = caja_icon_container_search_iter (container, text, 1);
5731
5732 if (ret)
5733 {
5734 container->details->selected_iter = 1;
5735 }
5736}
5737
5738static void
5739caja_icon_container_ensure_interactive_directory (CajaIconContainer *container)
5740{
5741 GtkWidget *frame, *vbox;
5742
5743 if (container->details->search_window != NULL((void*)0))
5744 {
5745 return;
5746 }
5747
5748 container->details->search_window = gtk_window_new (GTK_WINDOW_POPUP);
5749
5750 gtk_window_set_modal (GTK_WINDOW (container->details->search_window)((((GtkWindow*) (void *) ((container->details->search_window
)))))
, TRUE(!(0)));
5751 gtk_window_set_type_hint (GTK_WINDOW (container->details->search_window)((((GtkWindow*) (void *) ((container->details->search_window
)))))
,
5752 GDK_WINDOW_TYPE_HINT_COMBO);
5753
5754 g_signal_connect (container->details->search_window, "delete_event",g_signal_connect_data ((container->details->search_window
), ("delete_event"), (((GCallback) (caja_icon_container_search_delete_event
))), (container), ((void*)0), (GConnectFlags) 0)
5755 G_CALLBACK (caja_icon_container_search_delete_event),g_signal_connect_data ((container->details->search_window
), ("delete_event"), (((GCallback) (caja_icon_container_search_delete_event
))), (container), ((void*)0), (GConnectFlags) 0)
5756 container)g_signal_connect_data ((container->details->search_window
), ("delete_event"), (((GCallback) (caja_icon_container_search_delete_event
))), (container), ((void*)0), (GConnectFlags) 0)
;
5757 g_signal_connect (container->details->search_window, "key_press_event",g_signal_connect_data ((container->details->search_window
), ("key_press_event"), (((GCallback) (caja_icon_container_search_key_press_event
))), (container), ((void*)0), (GConnectFlags) 0)
5758 G_CALLBACK (caja_icon_container_search_key_press_event),g_signal_connect_data ((container->details->search_window
), ("key_press_event"), (((GCallback) (caja_icon_container_search_key_press_event
))), (container), ((void*)0), (GConnectFlags) 0)
5759 container)g_signal_connect_data ((container->details->search_window
), ("key_press_event"), (((GCallback) (caja_icon_container_search_key_press_event
))), (container), ((void*)0), (GConnectFlags) 0)
;
5760 g_signal_connect (container->details->search_window, "button_press_event",g_signal_connect_data ((container->details->search_window
), ("button_press_event"), (((GCallback) (caja_icon_container_search_button_press_event
))), (container), ((void*)0), (GConnectFlags) 0)
5761 G_CALLBACK (caja_icon_container_search_button_press_event),g_signal_connect_data ((container->details->search_window
), ("button_press_event"), (((GCallback) (caja_icon_container_search_button_press_event
))), (container), ((void*)0), (GConnectFlags) 0)
5762 container)g_signal_connect_data ((container->details->search_window
), ("button_press_event"), (((GCallback) (caja_icon_container_search_button_press_event
))), (container), ((void*)0), (GConnectFlags) 0)
;
5763 g_signal_connect (container->details->search_window, "scroll_event",g_signal_connect_data ((container->details->search_window
), ("scroll_event"), (((GCallback) (caja_icon_container_search_scroll_event
))), (container), ((void*)0), (GConnectFlags) 0)
5764 G_CALLBACK (caja_icon_container_search_scroll_event),g_signal_connect_data ((container->details->search_window
), ("scroll_event"), (((GCallback) (caja_icon_container_search_scroll_event
))), (container), ((void*)0), (GConnectFlags) 0)
5765 container)g_signal_connect_data ((container->details->search_window
), ("scroll_event"), (((GCallback) (caja_icon_container_search_scroll_event
))), (container), ((void*)0), (GConnectFlags) 0)
;
5766
5767 frame = gtk_frame_new (NULL((void*)0));
5768 gtk_frame_set_shadow_type (GTK_FRAME (frame)((((GtkFrame*) (void *) ((frame))))), GTK_SHADOW_ETCHED_IN);
5769 gtk_widget_show (frame);
5770 gtk_container_add (GTK_CONTAINER (container->details->search_window)((((GtkContainer*) (void *) ((container->details->search_window
)))))
, frame);
5771
5772 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
5773 gtk_widget_show (vbox);
5774 gtk_container_add (GTK_CONTAINER (frame)((((GtkContainer*) (void *) ((frame))))), vbox);
5775 gtk_container_set_border_width (GTK_CONTAINER (vbox)((((GtkContainer*) (void *) ((vbox))))), 3);
5776
5777 /* add entry */
5778 container->details->search_entry = gtk_entry_new ();
5779 gtk_widget_show (container->details->search_entry);
5780 g_signal_connect (container->details->search_entry, "populate_popup",g_signal_connect_data ((container->details->search_entry
), ("populate_popup"), (((GCallback) (caja_icon_container_search_disable_popdown
))), (container), ((void*)0), (GConnectFlags) 0)
5781 G_CALLBACK (caja_icon_container_search_disable_popdown),g_signal_connect_data ((container->details->search_entry
), ("populate_popup"), (((GCallback) (caja_icon_container_search_disable_popdown
))), (container), ((void*)0), (GConnectFlags) 0)
5782 container)g_signal_connect_data ((container->details->search_entry
), ("populate_popup"), (((GCallback) (caja_icon_container_search_disable_popdown
))), (container), ((void*)0), (GConnectFlags) 0)
;
5783 g_signal_connect (container->details->search_entry, "activate",g_signal_connect_data ((container->details->search_entry
), ("activate"), (((GCallback) (caja_icon_container_search_activate
))), (container), ((void*)0), (GConnectFlags) 0)
5784 G_CALLBACK (caja_icon_container_search_activate),g_signal_connect_data ((container->details->search_entry
), ("activate"), (((GCallback) (caja_icon_container_search_activate
))), (container), ((void*)0), (GConnectFlags) 0)
5785 container)g_signal_connect_data ((container->details->search_entry
), ("activate"), (((GCallback) (caja_icon_container_search_activate
))), (container), ((void*)0), (GConnectFlags) 0)
;
5786 g_signal_connect (container->details->search_entry,g_signal_connect_data ((container->details->search_entry
), ("preedit-changed"), (((GCallback) (caja_icon_container_search_preedit_changed
))), (container), ((void*)0), (GConnectFlags) 0)
5787 "preedit-changed",g_signal_connect_data ((container->details->search_entry
), ("preedit-changed"), (((GCallback) (caja_icon_container_search_preedit_changed
))), (container), ((void*)0), (GConnectFlags) 0)
5788 G_CALLBACK (caja_icon_container_search_preedit_changed),g_signal_connect_data ((container->details->search_entry
), ("preedit-changed"), (((GCallback) (caja_icon_container_search_preedit_changed
))), (container), ((void*)0), (GConnectFlags) 0)
5789 container)g_signal_connect_data ((container->details->search_entry
), ("preedit-changed"), (((GCallback) (caja_icon_container_search_preedit_changed
))), (container), ((void*)0), (GConnectFlags) 0)
;
5790 gtk_container_add (GTK_CONTAINER (vbox)((((GtkContainer*) (void *) ((vbox))))), container->details->search_entry);
5791
5792 gtk_widget_realize (container->details->search_entry);
5793}
5794
5795/* Pops up the interactive search entry. If keybinding is TRUE then the user
5796 * started this by typing the start_interactive_search keybinding. Otherwise, it came from
5797 */
5798static gboolean
5799caja_icon_container_real_start_interactive_search (CajaIconContainer *container,
5800 gboolean keybinding)
5801{
5802 /* We only start interactive search if we have focus. If one of our
5803 * children have focus, we don't want to start the search.
5804 */
5805 GtkWidgetClass *entry_parent_class;
5806
5807 if (container->details->search_window != NULL((void*)0) &&
5808 gtk_widget_get_visible (container->details->search_window))
5809 {
5810 return TRUE(!(0));
5811 }
5812
5813 if (!gtk_widget_has_focus (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))))
5814 {
5815 return FALSE(0);
5816 }
5817
5818 caja_icon_container_ensure_interactive_directory (container);
5819
5820 if (keybinding)
5821 {
5822 gtk_entry_set_text (GTK_ENTRY (container->details->search_entry)((((GtkEntry*) (void *) ((container->details->search_entry
)))))
, "");
5823 }
5824
5825 /* done, show it */
5826 caja_icon_container_search_position_func (container, container->details->search_window);
5827 gtk_widget_show (container->details->search_window);
5828 if (container->details->search_entry_changed_id == 0)
5829 {
5830 container->details->search_entry_changed_id =
5831 g_signal_connect (container->details->search_entry, "changed",g_signal_connect_data ((container->details->search_entry
), ("changed"), (((GCallback) (caja_icon_container_search_init
))), (container), ((void*)0), (GConnectFlags) 0)
5832 G_CALLBACK (caja_icon_container_search_init),g_signal_connect_data ((container->details->search_entry
), ("changed"), (((GCallback) (caja_icon_container_search_init
))), (container), ((void*)0), (GConnectFlags) 0)
5833 container)g_signal_connect_data ((container->details->search_entry
), ("changed"), (((GCallback) (caja_icon_container_search_init
))), (container), ((void*)0), (GConnectFlags) 0)
;
5834 }
5835
5836 container->details->typeselect_flush_timeout =
5837 g_timeout_add_seconds (CAJA_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT5,
5838 (GSourceFunc) caja_icon_container_search_entry_flush_timeout,
5839 container);
5840
5841 /* Grab focus will select all the text. We don't want that to happen, so we
5842 * call the parent instance and bypass the selection change. This is probably
5843 * really non-kosher. */
5844 entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (container->details->search_entry)((((GtkEntryClass*) (((GTypeInstance*) ((container->details
->search_entry)))->g_class))))
);
5845 (entry_parent_class->grab_focus) (container->details->search_entry);
5846
5847 /* send focus-in event */
5848 send_focus_change (container->details->search_entry, TRUE(!(0)));
5849
5850 /* search first matching iter */
5851 caja_icon_container_search_init (container->details->search_entry, container);
5852
5853 return TRUE(!(0));
5854}
5855
5856static gboolean
5857caja_icon_container_start_interactive_search (CajaIconContainer *container)
5858{
5859 return caja_icon_container_real_start_interactive_search (container, TRUE(!(0)));
5860}
5861
5862static gboolean
5863handle_popups (CajaIconContainer *container,
5864 GdkEventKey *event,
5865 const char *signal)
5866{
5867 GdkEventButton button_event = { 0 };
5868
5869 g_signal_emit_by_name (container, signal, &button_event);
5870
5871 return TRUE(!(0));
5872}
5873
5874static int
5875key_press_event (GtkWidget *widget,
5876 GdkEventKey *event)
5877{
5878 CajaIconContainer *container;
5879 gboolean handled;
5880
5881 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
5882 handled = FALSE(0);
5883
5884 if (is_renaming (container) || is_renaming_pending (container))
5885 {
5886 switch (event->keyval)
5887 {
5888 case GDK_KEY_Return0xff0d:
5889 case GDK_KEY_KP_Enter0xff8d:
5890 end_renaming_mode (container, TRUE(!(0)));
5891 handled = TRUE(!(0));
5892 break;
5893 case GDK_KEY_Escape0xff1b:
5894 end_renaming_mode (container, FALSE(0));
5895 handled = TRUE(!(0));
5896 break;
5897 default:
5898 break;
5899 }
5900 }
5901 else
5902 {
5903 switch (event->keyval)
5904 {
5905 case GDK_KEY_Home0xff50:
5906 case GDK_KEY_KP_Home0xff95:
5907 keyboard_home (container, event);
5908 handled = TRUE(!(0));
5909 break;
5910 case GDK_KEY_End0xff57:
5911 case GDK_KEY_KP_End0xff9c:
5912 keyboard_end (container, event);
5913 handled = TRUE(!(0));
5914 break;
5915 case GDK_KEY_Left0xff51:
5916 case GDK_KEY_KP_Left0xff96:
5917 /* Don't eat Alt-Left, as that is used for history browsing */
5918 if ((event->state & GDK_MOD1_MASK) == 0)
5919 {
5920 keyboard_left (container, event);
5921 handled = TRUE(!(0));
5922 }
5923 break;
5924 case GDK_KEY_Up0xff52:
5925 case GDK_KEY_KP_Up0xff97:
5926 /* Don't eat Alt-Up, as that is used for alt-shift-Up */
5927 if ((event->state & GDK_MOD1_MASK) == 0)
5928 {
5929 keyboard_up (container, event);
5930 handled = TRUE(!(0));
5931 }
5932 break;
5933 case GDK_KEY_Right0xff53:
5934 case GDK_KEY_KP_Right0xff98:
5935 /* Don't eat Alt-Right, as that is used for history browsing */
5936 if ((event->state & GDK_MOD1_MASK) == 0)
5937 {
5938 keyboard_right (container, event);
5939 handled = TRUE(!(0));
5940 }
5941 break;
5942 case GDK_KEY_Down0xff54:
5943 case GDK_KEY_KP_Down0xff99:
5944 /* Don't eat Alt-Down, as that is used for Open */
5945 if ((event->state & GDK_MOD1_MASK) == 0)
5946 {
5947 keyboard_down (container, event);
5948 handled = TRUE(!(0));
5949 }
5950 break;
5951 case GDK_KEY_space0x020:
5952 keyboard_space (container, event);
5953 handled = TRUE(!(0));
5954 break;
5955#ifndef TAB_NAVIGATION_DISABLED
5956 case GDK_KEY_Tab0xff09:
5957 case GDK_KEY_ISO_Left_Tab0xfe20:
5958 select_previous_or_next_icon (container,
5959 (event->state & GDK_SHIFT_MASK) == 0, event);
5960 handled = TRUE(!(0));
5961 break;
5962#endif
5963 case GDK_KEY_Return0xff0d:
5964 case GDK_KEY_KP_Enter0xff8d:
5965 if ((event->state & GDK_SHIFT_MASK) != 0)
5966 {
5967 activate_selected_items_alternate (container, NULL((void*)0));
5968 }
5969 else
5970 {
5971 activate_selected_items (container);
5972 }
5973
5974 handled = TRUE(!(0));
5975 break;
5976 case GDK_KEY_Escape0xff1b:
5977 handled = undo_stretching (container);
5978 break;
5979 case GDK_KEY_plus0x02b:
5980 case GDK_KEY_minus0x02d:
5981 case GDK_KEY_equal0x03d:
5982 case GDK_KEY_KP_Add0xffab:
5983 case GDK_KEY_KP_Subtract0xffad:
5984 case GDK_KEY_00x030:
5985 case GDK_KEY_KP_00xffb0:
5986 if (event->state & GDK_CONTROL_MASK)
5987 {
5988 handled = keyboard_stretching (container, event);
5989 }
5990 break;
5991 case GDK_KEY_F100xffc7:
5992 /* handle Ctrl+F10 because we want to display the
5993 * background popup even if something is selected.
5994 * The other cases are handled by popup_menu().
5995 */
5996 if (event->state & GDK_CONTROL_MASK)
5997 {
5998 handled = handle_popups (container, event,
5999 "context_click_background");
6000 }
6001 break;
6002 case GDK_KEY_v0x076:
6003 /* Eat Control + v to not enable type ahead */
6004 if ((event->state & GDK_CONTROL_MASK) != 0)
6005 {
6006 handled = TRUE(!(0));
6007 }
6008 break;
6009 default:
6010 break;
6011 }
6012 }
6013
6014 if (!handled)
6015 {
6016 handled = GTK_WIDGET_CLASS (caja_icon_container_parent_class)((((GtkWidgetClass*) (void *) ((caja_icon_container_parent_class
)))))
->key_press_event (widget, event);
6017 }
6018
6019 /* We pass the event to the search_entry. If its text changes, then we
6020 * start the typeahead find capabilities.
6021 * Copied from CajaIconContainer */
6022 if (!handled &&
6023 event->keyval != GDK_KEY_slash0x02f /* don't steal slash key event, used for "go to" */ &&
6024 event->keyval != GDK_KEY_BackSpace0xff08 &&
6025 event->keyval != GDK_KEY_Delete0xffff)
6026 {
6027 GdkEvent *new_event;
6028 GdkWindow *window;
6029 char *old_text;
6030 const char *new_text;
6031 gboolean retval;
6032 GdkScreen *screen;
6033 gboolean text_modified;
6034 gulong popup_menu_id;
6035 gint scale;
6036
6037 caja_icon_container_ensure_interactive_directory (container);
6038
6039 /* Make a copy of the current text */
6040 old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (container->details->search_entry)))g_strdup_inline (gtk_entry_get_text (((((GtkEntry*) (void *) (
(container->details->search_entry)))))))
;
6041 new_event = gdk_event_copy ((GdkEvent *) event);
6042 window = ((GdkEventKey *) new_event)->window;
6043 ((GdkEventKey *) new_event)->window = gtk_widget_get_window (container->details->search_entry);
6044 gtk_widget_realize (container->details->search_window);
6045
6046 popup_menu_id = g_signal_connect (container->details->search_entry,g_signal_connect_data ((container->details->search_entry
), ("popup_menu"), (((GCallback) (gtk_true))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
6047 "popup_menu", G_CALLBACK (gtk_true), NULL)g_signal_connect_data ((container->details->search_entry
), ("popup_menu"), (((GCallback) (gtk_true))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
;
6048
6049 /* Move the entry off screen */
6050 screen = gtk_widget_get_screen (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
6051 scale = gtk_widget_get_scale_factor (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
6052 gtk_window_move (GTK_WINDOW (container->details->search_window)((((GtkWindow*) (void *) ((container->details->search_window
)))))
,
6053 WidthOfScreen (gdk_x11_screen_get_xscreen (screen))((gdk_x11_screen_get_xscreen (screen))->width) / scale + 1,
6054 HeightOfScreen (gdk_x11_screen_get_xscreen (screen))((gdk_x11_screen_get_xscreen (screen))->height) / scale + 1);
6055 gtk_widget_show (container->details->search_window);
6056
6057 /* Send the event to the window. If the preedit_changed signal is emitted
6058 * during this event, we will set priv->imcontext_changed */
6059 container->details->imcontext_changed = FALSE(0);
6060 retval = gtk_widget_event (container->details->search_entry, new_event);
6061 gtk_widget_hide (container->details->search_window);
6062
6063 g_signal_handler_disconnect (container->details->search_entry,
6064 popup_menu_id);
6065
6066 /* We check to make sure that the entry tried to handle the text, and that
6067 * the text has changed. */
6068 new_text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry)((((GtkEntry*) (void *) ((container->details->search_entry
)))))
);
6069 text_modified = strcmp (old_text, new_text) != 0;
6070 g_free (old_text);
6071 if (container->details->imcontext_changed || /* we're in a preedit */
6072 (retval && text_modified)) /* ...or the text was modified */
6073 {
6074 if (caja_icon_container_real_start_interactive_search (container, FALSE(0)))
6075 {
6076 gtk_widget_grab_focus (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
6077 return TRUE(!(0));
6078 }
6079 else
6080 {
6081 gtk_entry_set_text (GTK_ENTRY (container->details->search_entry)((((GtkEntry*) (void *) ((container->details->search_entry
)))))
, "");
6082 return FALSE(0);
6083 }
6084 }
6085
6086 ((GdkEventKey *) new_event)->window = window;
6087 gdk_event_free (new_event);
6088 }
6089
6090 return handled;
6091}
6092
6093static gboolean
6094popup_menu (GtkWidget *widget)
6095{
6096 CajaIconContainer *container;
6097
6098 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
6099
6100 if (has_selection (container))
6101 {
6102 handle_popups (container, NULL((void*)0),
6103 "context_click_selection");
6104 }
6105 else
6106 {
6107 handle_popups (container, NULL((void*)0),
6108 "context_click_background");
6109 }
6110
6111 return TRUE(!(0));
6112}
6113
6114static void
6115draw_canvas_background (EelCanvas *canvas,
6116 cairo_t *cr)
6117{
6118 /* Don't chain up to the parent to avoid clearing and redrawing */
6119}
6120
6121static void
6122grab_notify_cb (GtkWidget *widget,
6123 gboolean was_grabbed)
6124{
6125 CajaIconContainer *container;
6126
6127 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
6128
6129 if (container->details->rubberband_info.active &&
6130 !was_grabbed)
6131 {
6132 /* we got a (un)grab-notify during rubberband.
6133 * This happens when a new modal dialog shows
6134 * up (e.g. authentication or an error). Stop
6135 * the rubberbanding so that we can handle the
6136 * dialog. */
6137 stop_rubberbanding (container);
6138 }
6139}
6140
6141static void
6142text_ellipsis_limit_changed_container_callback (gpointer callback_data)
6143{
6144 CajaIconContainer *container;
6145
6146 container = CAJA_ICON_CONTAINER (callback_data)((((CajaIconContainer*) (void *) ((callback_data)))));
6147 invalidate_label_sizes (container);
6148 schedule_redo_layout (container);
6149}
6150
6151static GObject*
6152caja_icon_container_constructor (GType type,
6153 guint n_construct_params,
6154 GObjectConstructParam *construct_params)
6155{
6156 CajaIconContainer *container;
6157 GObject *object;
6158
6159 object = G_OBJECT_CLASS (caja_icon_container_parent_class)((((GObjectClass*) (void *) ((caja_icon_container_parent_class
)))))
->constructor
6160 (type,
6161 n_construct_params,
6162 construct_params);
6163
6164 container = CAJA_ICON_CONTAINER (object)((((CajaIconContainer*) (void *) ((object)))));
6165 if (caja_icon_container_get_is_desktop (container))
6166 {
6167 g_signal_connect_swapped (caja_desktop_preferences,g_signal_connect_data ((caja_desktop_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
6168 "changed::" CAJA_PREFERENCES_DESKTOP_TEXT_ELLIPSIS_LIMIT,g_signal_connect_data ((caja_desktop_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
6169 G_CALLBACK (text_ellipsis_limit_changed_container_callback),g_signal_connect_data ((caja_desktop_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
6170 container)g_signal_connect_data ((caja_desktop_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
;
6171 }
6172 else
6173 {
6174 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
6175 "changed::" CAJA_PREFERENCES_ICON_VIEW_TEXT_ELLIPSIS_LIMIT,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
6176 G_CALLBACK (text_ellipsis_limit_changed_container_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
6177 container)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_container_callback
))), (container), ((void*)0), G_CONNECT_SWAPPED)
;
6178 }
6179
6180 return object;
6181}
6182
6183/* Initialization. */
6184
6185static void
6186caja_icon_container_class_init (CajaIconContainerClass *class)
6187{
6188 GtkWidgetClass *widget_class;
6189 EelCanvasClass *canvas_class;
6190 GtkBindingSet *binding_set;
6191
6192 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->constructor = caja_icon_container_constructor;
6193 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = finalize;
6194
6195 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->destroy = destroy;
6196
6197 /* Signals. */
6198
6199 signals[SELECTION_CHANGED]
6200 = g_signal_new ("selection_changed",
6201 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6202 G_SIGNAL_RUN_LAST,
6203 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, selection_changed
))
6204 selection_changed)((glong) __builtin_offsetof(CajaIconContainerClass, selection_changed
))
,
6205 NULL((void*)0), NULL((void*)0),
6206 g_cclosure_marshal_VOID__VOID,
6207 G_TYPE_NONE((GType) ((1) << (2))), 0);
6208 signals[BUTTON_PRESS]
6209 = g_signal_new ("button_press",
6210 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6211 G_SIGNAL_RUN_LAST,
6212 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, button_press
))
6213 button_press)((glong) __builtin_offsetof(CajaIconContainerClass, button_press
))
,
6214 NULL((void*)0), NULL((void*)0),
6215 caja_marshal_BOOLEAN__POINTER,
6216 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1,
6217 GDK_TYPE_EVENT(gdk_event_get_type ()));
6218 signals[ACTIVATE]
6219 = g_signal_new ("activate",
6220 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6221 G_SIGNAL_RUN_LAST,
6222 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, activate)
)
6223 activate)((glong) __builtin_offsetof(CajaIconContainerClass, activate)
)
,
6224 NULL((void*)0), NULL((void*)0),
6225 g_cclosure_marshal_VOID__POINTER,
6226 G_TYPE_NONE((GType) ((1) << (2))), 1,
6227 G_TYPE_POINTER((GType) ((17) << (2))));
6228 signals[ACTIVATE_ALTERNATE]
6229 = g_signal_new ("activate_alternate",
6230 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6231 G_SIGNAL_RUN_LAST,
6232 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, activate_alternate
))
6233 activate_alternate)((glong) __builtin_offsetof(CajaIconContainerClass, activate_alternate
))
,
6234 NULL((void*)0), NULL((void*)0),
6235 g_cclosure_marshal_VOID__POINTER,
6236 G_TYPE_NONE((GType) ((1) << (2))), 1,
6237 G_TYPE_POINTER((GType) ((17) << (2))));
6238 signals[CONTEXT_CLICK_SELECTION]
6239 = g_signal_new ("context_click_selection",
6240 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6241 G_SIGNAL_RUN_LAST,
6242 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, context_click_selection
))
6243 context_click_selection)((glong) __builtin_offsetof(CajaIconContainerClass, context_click_selection
))
,
6244 NULL((void*)0), NULL((void*)0),
6245 g_cclosure_marshal_VOID__POINTER,
6246 G_TYPE_NONE((GType) ((1) << (2))), 1,
6247 G_TYPE_POINTER((GType) ((17) << (2))));
6248 signals[CONTEXT_CLICK_BACKGROUND]
6249 = g_signal_new ("context_click_background",
6250 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6251 G_SIGNAL_RUN_LAST,
6252 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, context_click_background
))
6253 context_click_background)((glong) __builtin_offsetof(CajaIconContainerClass, context_click_background
))
,
6254 NULL((void*)0), NULL((void*)0),
6255 g_cclosure_marshal_VOID__POINTER,
6256 G_TYPE_NONE((GType) ((1) << (2))), 1,
6257 G_TYPE_POINTER((GType) ((17) << (2))));
6258 signals[MIDDLE_CLICK]
6259 = g_signal_new ("middle_click",
6260 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6261 G_SIGNAL_RUN_LAST,
6262 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, middle_click
))
6263 middle_click)((glong) __builtin_offsetof(CajaIconContainerClass, middle_click
))
,
6264 NULL((void*)0), NULL((void*)0),
6265 g_cclosure_marshal_VOID__POINTER,
6266 G_TYPE_NONE((GType) ((1) << (2))), 1,
6267 G_TYPE_POINTER((GType) ((17) << (2))));
6268 signals[ICON_POSITION_CHANGED]
6269 = g_signal_new ("icon_position_changed",
6270 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6271 G_SIGNAL_RUN_LAST,
6272 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, icon_position_changed
))
6273 icon_position_changed)((glong) __builtin_offsetof(CajaIconContainerClass, icon_position_changed
))
,
6274 NULL((void*)0), NULL((void*)0),
6275 caja_marshal_VOID__POINTER_POINTER,
6276 G_TYPE_NONE((GType) ((1) << (2))), 2,
6277 G_TYPE_POINTER((GType) ((17) << (2))),
6278 G_TYPE_POINTER((GType) ((17) << (2))));
6279 signals[ICON_TEXT_CHANGED]
6280 = g_signal_new ("icon_text_changed",
6281 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6282 G_SIGNAL_RUN_LAST,
6283 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, icon_text_changed
))
6284 icon_text_changed)((glong) __builtin_offsetof(CajaIconContainerClass, icon_text_changed
))
,
6285 NULL((void*)0), NULL((void*)0),
6286 caja_marshal_VOID__POINTER_STRING,
6287 G_TYPE_NONE((GType) ((1) << (2))), 2,
6288 G_TYPE_POINTER((GType) ((17) << (2))),
6289 G_TYPE_STRING((GType) ((16) << (2))));
6290 signals[ICON_STRETCH_STARTED]
6291 = g_signal_new ("icon_stretch_started",
6292 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6293 G_SIGNAL_RUN_LAST,
6294 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, icon_stretch_started
))
6295 icon_stretch_started)((glong) __builtin_offsetof(CajaIconContainerClass, icon_stretch_started
))
,
6296 NULL((void*)0), NULL((void*)0),
6297 g_cclosure_marshal_VOID__POINTER,
6298 G_TYPE_NONE((GType) ((1) << (2))), 1,
6299 G_TYPE_POINTER((GType) ((17) << (2))));
6300 signals[ICON_STRETCH_ENDED]
6301 = g_signal_new ("icon_stretch_ended",
6302 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6303 G_SIGNAL_RUN_LAST,
6304 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, icon_stretch_ended
))
6305 icon_stretch_ended)((glong) __builtin_offsetof(CajaIconContainerClass, icon_stretch_ended
))
,
6306 NULL((void*)0), NULL((void*)0),
6307 g_cclosure_marshal_VOID__POINTER,
6308 G_TYPE_NONE((GType) ((1) << (2))), 1,
6309 G_TYPE_POINTER((GType) ((17) << (2))));
6310 signals[RENAMING_ICON]
6311 = g_signal_new ("renaming_icon",
6312 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6313 G_SIGNAL_RUN_LAST,
6314 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, renaming_icon
))
6315 renaming_icon)((glong) __builtin_offsetof(CajaIconContainerClass, renaming_icon
))
,
6316 NULL((void*)0), NULL((void*)0),
6317 g_cclosure_marshal_VOID__POINTER,
6318 G_TYPE_NONE((GType) ((1) << (2))), 1,
6319 G_TYPE_POINTER((GType) ((17) << (2))));
6320 signals[GET_ICON_URI]
6321 = g_signal_new ("get_icon_uri",
6322 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6323 G_SIGNAL_RUN_LAST,
6324 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, get_icon_uri
))
6325 get_icon_uri)((glong) __builtin_offsetof(CajaIconContainerClass, get_icon_uri
))
,
6326 NULL((void*)0), NULL((void*)0),
6327 caja_marshal_STRING__POINTER,
6328 G_TYPE_STRING((GType) ((16) << (2))), 1,
6329 G_TYPE_POINTER((GType) ((17) << (2))));
6330 signals[GET_ICON_DROP_TARGET_URI]
6331 = g_signal_new ("get_icon_drop_target_uri",
6332 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6333 G_SIGNAL_RUN_LAST,
6334 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, get_icon_drop_target_uri
))
6335 get_icon_drop_target_uri)((glong) __builtin_offsetof(CajaIconContainerClass, get_icon_drop_target_uri
))
,
6336 NULL((void*)0), NULL((void*)0),
6337 caja_marshal_STRING__POINTER,
6338 G_TYPE_STRING((GType) ((16) << (2))), 1,
6339 G_TYPE_POINTER((GType) ((17) << (2))));
6340 signals[MOVE_COPY_ITEMS]
6341 = g_signal_new ("move_copy_items",
6342 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6343 G_SIGNAL_RUN_LAST,
6344 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, move_copy_items
))
6345 move_copy_items)((glong) __builtin_offsetof(CajaIconContainerClass, move_copy_items
))
,
6346 NULL((void*)0), NULL((void*)0),
6347 caja_marshal_VOID__POINTER_POINTER_POINTER_ENUM_INT_INT,
6348 G_TYPE_NONE((GType) ((1) << (2))), 6,
6349 G_TYPE_POINTER((GType) ((17) << (2))),
6350 G_TYPE_POINTER((GType) ((17) << (2))),
6351 G_TYPE_POINTER((GType) ((17) << (2))),
6352 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
6353 G_TYPE_INT((GType) ((6) << (2))),
6354 G_TYPE_INT((GType) ((6) << (2))));
6355 signals[HANDLE_NETSCAPE_URL]
6356 = g_signal_new ("handle_netscape_url",
6357 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6358 G_SIGNAL_RUN_LAST,
6359 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, handle_netscape_url
))
6360 handle_netscape_url)((glong) __builtin_offsetof(CajaIconContainerClass, handle_netscape_url
))
,
6361 NULL((void*)0), NULL((void*)0),
6362 caja_marshal_VOID__STRING_STRING_ENUM_INT_INT,
6363 G_TYPE_NONE((GType) ((1) << (2))), 5,
6364 G_TYPE_STRING((GType) ((16) << (2))),
6365 G_TYPE_STRING((GType) ((16) << (2))),
6366 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
6367 G_TYPE_INT((GType) ((6) << (2))),
6368 G_TYPE_INT((GType) ((6) << (2))));
6369 signals[HANDLE_URI_LIST]
6370 = g_signal_new ("handle_uri_list",
6371 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6372 G_SIGNAL_RUN_LAST,
6373 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, handle_uri_list
))
6374 handle_uri_list)((glong) __builtin_offsetof(CajaIconContainerClass, handle_uri_list
))
,
6375 NULL((void*)0), NULL((void*)0),
6376 caja_marshal_VOID__STRING_STRING_ENUM_INT_INT,
6377 G_TYPE_NONE((GType) ((1) << (2))), 5,
6378 G_TYPE_STRING((GType) ((16) << (2))),
6379 G_TYPE_STRING((GType) ((16) << (2))),
6380 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
6381 G_TYPE_INT((GType) ((6) << (2))),
6382 G_TYPE_INT((GType) ((6) << (2))));
6383 signals[HANDLE_TEXT]
6384 = g_signal_new ("handle_text",
6385 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6386 G_SIGNAL_RUN_LAST,
6387 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, handle_text
))
6388 handle_text)((glong) __builtin_offsetof(CajaIconContainerClass, handle_text
))
,
6389 NULL((void*)0), NULL((void*)0),
6390 caja_marshal_VOID__STRING_STRING_ENUM_INT_INT,
6391 G_TYPE_NONE((GType) ((1) << (2))), 5,
6392 G_TYPE_STRING((GType) ((16) << (2))),
6393 G_TYPE_STRING((GType) ((16) << (2))),
6394 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
6395 G_TYPE_INT((GType) ((6) << (2))),
6396 G_TYPE_INT((GType) ((6) << (2))));
6397 signals[HANDLE_RAW]
6398 = g_signal_new ("handle_raw",
6399 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6400 G_SIGNAL_RUN_LAST,
6401 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, handle_raw
))
6402 handle_raw)((glong) __builtin_offsetof(CajaIconContainerClass, handle_raw
))
,
6403 NULL((void*)0), NULL((void*)0),
6404 caja_marshal_VOID__POINTER_INT_STRING_STRING_ENUM_INT_INT,
6405 G_TYPE_NONE((GType) ((1) << (2))), 7,
6406 G_TYPE_POINTER((GType) ((17) << (2))),
6407 G_TYPE_INT((GType) ((6) << (2))),
6408 G_TYPE_STRING((GType) ((16) << (2))),
6409 G_TYPE_STRING((GType) ((16) << (2))),
6410 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
6411 G_TYPE_INT((GType) ((6) << (2))),
6412 G_TYPE_INT((GType) ((6) << (2))));
6413 signals[GET_CONTAINER_URI]
6414 = g_signal_new ("get_container_uri",
6415 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6416 G_SIGNAL_RUN_LAST,
6417 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, get_container_uri
))
6418 get_container_uri)((glong) __builtin_offsetof(CajaIconContainerClass, get_container_uri
))
,
6419 NULL((void*)0), NULL((void*)0),
6420 caja_marshal_STRING__VOID,
6421 G_TYPE_STRING((GType) ((16) << (2))), 0);
6422 signals[CAN_ACCEPT_ITEM]
6423 = g_signal_new ("can_accept_item",
6424 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6425 G_SIGNAL_RUN_LAST,
6426 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, can_accept_item
))
6427 can_accept_item)((glong) __builtin_offsetof(CajaIconContainerClass, can_accept_item
))
,
6428 NULL((void*)0), NULL((void*)0),
6429 caja_marshal_INT__POINTER_STRING,
6430 G_TYPE_INT((GType) ((6) << (2))), 2,
6431 G_TYPE_POINTER((GType) ((17) << (2))),
6432 G_TYPE_STRING((GType) ((16) << (2))));
6433 signals[GET_STORED_ICON_POSITION]
6434 = g_signal_new ("get_stored_icon_position",
6435 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6436 G_SIGNAL_RUN_LAST,
6437 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, get_stored_icon_position
))
6438 get_stored_icon_position)((glong) __builtin_offsetof(CajaIconContainerClass, get_stored_icon_position
))
,
6439 NULL((void*)0), NULL((void*)0),
6440 caja_marshal_BOOLEAN__POINTER_POINTER,
6441 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
6442 G_TYPE_POINTER((GType) ((17) << (2))),
6443 G_TYPE_POINTER((GType) ((17) << (2))));
6444 signals[GET_STORED_LAYOUT_TIMESTAMP]
6445 = g_signal_new ("get_stored_layout_timestamp",
6446 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6447 G_SIGNAL_RUN_LAST,
6448 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, get_stored_layout_timestamp
))
6449 get_stored_layout_timestamp)((glong) __builtin_offsetof(CajaIconContainerClass, get_stored_layout_timestamp
))
,
6450 NULL((void*)0), NULL((void*)0),
6451 caja_marshal_BOOLEAN__POINTER_POINTER,
6452 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
6453 G_TYPE_POINTER((GType) ((17) << (2))),
6454 G_TYPE_POINTER((GType) ((17) << (2))));
6455 signals[STORE_LAYOUT_TIMESTAMP]
6456 = g_signal_new ("store_layout_timestamp",
6457 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6458 G_SIGNAL_RUN_LAST,
6459 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, store_layout_timestamp
))
6460 store_layout_timestamp)((glong) __builtin_offsetof(CajaIconContainerClass, store_layout_timestamp
))
,
6461 NULL((void*)0), NULL((void*)0),
6462 caja_marshal_BOOLEAN__POINTER_POINTER,
6463 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
6464 G_TYPE_POINTER((GType) ((17) << (2))),
6465 G_TYPE_POINTER((GType) ((17) << (2))));
6466 signals[LAYOUT_CHANGED]
6467 = g_signal_new ("layout_changed",
6468 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6469 G_SIGNAL_RUN_LAST,
6470 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, layout_changed
))
6471 layout_changed)((glong) __builtin_offsetof(CajaIconContainerClass, layout_changed
))
,
6472 NULL((void*)0), NULL((void*)0),
6473 g_cclosure_marshal_VOID__VOID,
6474 G_TYPE_NONE((GType) ((1) << (2))), 0);
6475 signals[PREVIEW]
6476 = g_signal_new ("preview",
6477 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6478 G_SIGNAL_RUN_LAST,
6479 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, preview))
6480 preview)((glong) __builtin_offsetof(CajaIconContainerClass, preview)),
6481 NULL((void*)0), NULL((void*)0),
6482 caja_marshal_INT__POINTER_BOOLEAN,
6483 G_TYPE_INT((GType) ((6) << (2))), 2,
6484 G_TYPE_POINTER((GType) ((17) << (2))),
6485 G_TYPE_BOOLEAN((GType) ((5) << (2))));
6486 signals[BAND_SELECT_STARTED]
6487 = g_signal_new ("band_select_started",
6488 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6489 G_SIGNAL_RUN_LAST,
6490 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, band_select_started
))
6491 band_select_started)((glong) __builtin_offsetof(CajaIconContainerClass, band_select_started
))
,
6492 NULL((void*)0), NULL((void*)0),
6493 g_cclosure_marshal_VOID__VOID,
6494 G_TYPE_NONE((GType) ((1) << (2))), 0);
6495 signals[BAND_SELECT_ENDED]
6496 = g_signal_new ("band_select_ended",
6497 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6498 G_SIGNAL_RUN_LAST,
6499 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, band_select_ended
))
6500 band_select_ended)((glong) __builtin_offsetof(CajaIconContainerClass, band_select_ended
))
,
6501 NULL((void*)0), NULL((void*)0),
6502 g_cclosure_marshal_VOID__VOID,
6503 G_TYPE_NONE((GType) ((1) << (2))), 0);
6504 signals[ICON_ADDED]
6505 = g_signal_new ("icon_added",
6506 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6507 G_SIGNAL_RUN_LAST,
6508 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, icon_added
))
6509 icon_added)((glong) __builtin_offsetof(CajaIconContainerClass, icon_added
))
,
6510 NULL((void*)0), NULL((void*)0),
6511 g_cclosure_marshal_VOID__POINTER,
6512 G_TYPE_NONE((GType) ((1) << (2))), 1, G_TYPE_POINTER((GType) ((17) << (2))));
6513 signals[ICON_REMOVED]
6514 = g_signal_new ("icon_removed",
6515 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6516 G_SIGNAL_RUN_LAST,
6517 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, icon_removed
))
6518 icon_removed)((glong) __builtin_offsetof(CajaIconContainerClass, icon_removed
))
,
6519 NULL((void*)0), NULL((void*)0),
6520 g_cclosure_marshal_VOID__POINTER,
6521 G_TYPE_NONE((GType) ((1) << (2))), 1, G_TYPE_POINTER((GType) ((17) << (2))));
6522
6523 signals[CLEARED]
6524 = g_signal_new ("cleared",
6525 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6526 G_SIGNAL_RUN_LAST,
6527 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, cleared))
6528 cleared)((glong) __builtin_offsetof(CajaIconContainerClass, cleared)),
6529 NULL((void*)0), NULL((void*)0),
6530 g_cclosure_marshal_VOID__VOID,
6531 G_TYPE_NONE((GType) ((1) << (2))), 0);
6532
6533 signals[START_INTERACTIVE_SEARCH]
6534 = g_signal_new ("start_interactive_search",
6535 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
6536 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
6537 G_STRUCT_OFFSET (CajaIconContainerClass,((glong) __builtin_offsetof(CajaIconContainerClass, start_interactive_search
))
6538 start_interactive_search)((glong) __builtin_offsetof(CajaIconContainerClass, start_interactive_search
))
,
6539 NULL((void*)0), NULL((void*)0),
6540 caja_marshal_BOOLEAN__VOID,
6541 G_TYPE_BOOLEAN((GType) ((5) << (2))), 0);
6542
6543 /* GtkWidget class. */
6544
6545 widget_class = GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))));
6546 widget_class->size_allocate = size_allocate;
6547 widget_class->get_request_mode = get_request_mode;
6548 widget_class->get_preferred_width = get_prefered_width;
6549 widget_class->get_preferred_height = get_prefered_height;
6550 widget_class->draw = draw;
6551 widget_class->realize = realize;
6552 widget_class->unrealize = unrealize;
6553 widget_class->button_press_event = button_press_event;
6554 widget_class->button_release_event = button_release_event;
6555 widget_class->motion_notify_event = motion_notify_event;
6556 widget_class->key_press_event = key_press_event;
6557 widget_class->popup_menu = popup_menu;
6558 widget_class->style_updated = style_updated;
6559 widget_class->grab_notify = grab_notify_cb;
6560
6561 gtk_widget_class_set_accessible_type (widget_class, caja_icon_container_accessible_get_type ());
6562
6563 canvas_class = EEL_CANVAS_CLASS (class)((((EelCanvasClass*) (void *) ((class)))));
6564 canvas_class->draw_background = draw_canvas_background;
6565 class->start_interactive_search = caja_icon_container_start_interactive_search;
6566
6567 gtk_widget_class_install_style_property (widget_class,
6568 g_param_spec_boxed ("selection_box_rgba",
6569 "Selection Box RGBA",
6570 "Color of the selection box",
6571 GDK_TYPE_RGBA(gdk_rgba_get_type ()),
6572 G_PARAM_READABLE));
6573 gtk_widget_class_install_style_property (widget_class,
6574 g_param_spec_boxed ("light_info_rgba",
6575 "Light Info RGBA",
6576 "Color used for information text against a dark background",
6577 GDK_TYPE_RGBA(gdk_rgba_get_type ()),
6578 G_PARAM_READABLE));
6579 gtk_widget_class_install_style_property (widget_class,
6580 g_param_spec_boxed ("dark_info_rgba",
6581 "Dark Info RGBA",
6582 "Color used for information text against a light background",
6583 GDK_TYPE_RGBA(gdk_rgba_get_type ()),
6584 G_PARAM_READABLE));
6585 gtk_widget_class_install_style_property (widget_class,
6586 g_param_spec_boolean ("activate_prelight_icon_label",
6587 "Activate Prelight Icon Label",
6588 "Whether icon labels should make use of its prelight color in prelight state",
6589 FALSE(0),
6590 G_PARAM_READABLE));
6591
6592
6593 binding_set = gtk_binding_set_by_class (class);
6594
6595 gtk_binding_entry_add_signal (binding_set, GDK_KEY_f0x066, GDK_CONTROL_MASK, "start_interactive_search", 0);
6596 gtk_binding_entry_add_signal (binding_set, GDK_KEY_F0x046, GDK_CONTROL_MASK, "start_interactive_search", 0);
6597}
6598
6599static void
6600update_selected (CajaIconContainer *container)
6601{
6602 GList *node;
6603 CajaIcon *icon = NULL((void*)0);
6604
6605 for (node = container->details->icons; node != NULL((void*)0); node = node->next)
6606 {
6607 icon = node->data;
6608 if (icon->is_selected)
6609 {
6610 eel_canvas_item_request_update (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))));
6611 }
6612 }
6613}
6614
6615static gboolean
6616handle_focus_in_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
6617{
6618 update_selected (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))));
6619
6620 return FALSE(0);
6621}
6622
6623static gboolean
6624handle_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
6625{
6626 /* End renaming and commit change. */
6627 end_renaming_mode (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))), TRUE(!(0)));
6628 update_selected (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))));
6629
6630 return FALSE(0);
6631}
6632
6633static void
6634handle_scale_factor_changed (GObject *object,
6635 GParamSpec *pspec,
6636 gpointer user_data)
6637{
6638 invalidate_labels (CAJA_ICON_CONTAINER (object)((((CajaIconContainer*) (void *) ((object))))));
6639 caja_icon_container_request_update_all (CAJA_ICON_CONTAINER (object)((((CajaIconContainer*) (void *) ((object))))));
6640}
6641
6642
6643static int text_ellipsis_limits[CAJA_ZOOM_LEVEL_N_ENTRIES(CAJA_ZOOM_LEVEL_LARGEST + 1)];
6644static int desktop_text_ellipsis_limit;
6645
6646static gboolean
6647get_text_ellipsis_limit_for_zoom (char **strs,
6648 const char *zoom_level,
6649 int *limit)
6650{
6651 char *str;
6652 gboolean success;
6653
6654 success = FALSE(0);
6655
6656 /* default */
6657 *limit = 3;
6658
6659 if (zoom_level != NULL((void*)0))
6660 {
6661 str = g_strdup_printf ("%s:%%d", zoom_level);
6662 }
6663 else
6664 {
6665 str = g_strdup ("%d")g_strdup_inline ("%d");
6666 }
6667
6668 if (strs != NULL((void*)0))
6669 {
6670 char **p;
6671
6672 for (p = strs; *p != NULL((void*)0); p++)
6673 {
6674 if (sscanf (*p, str, limit))
6675 {
6676 success = TRUE(!(0));
6677 }
6678 }
6679 }
6680
6681 g_free (str);
6682
6683 return success;
6684}
6685
6686static const char * zoom_level_names[] = {
6687 "smallest",
6688 "smaller",
6689 "small",
6690 "standard",
6691 "large",
6692 "larger",
6693 "largest"
6694};
6695
6696static void
6697text_ellipsis_limit_changed_callback (gpointer callback_data)
6698{
6699 char **pref;
6700 unsigned int i;
6701 int one_limit;
6702
6703 pref = g_settings_get_strv (caja_icon_view_preferences, CAJA_PREFERENCES_ICON_VIEW_TEXT_ELLIPSIS_LIMIT"text-ellipsis-limit");
6704
6705 /* set default */
6706 get_text_ellipsis_limit_for_zoom (pref, NULL((void*)0), &one_limit);
6707 for (i = 0; i < CAJA_ZOOM_LEVEL_N_ENTRIES(CAJA_ZOOM_LEVEL_LARGEST + 1); i++)
6708 {
6709 text_ellipsis_limits[i] = one_limit;
6710 }
6711
6712 /* override for each zoom level */
6713 for (i = 0; i < G_N_ELEMENTS(zoom_level_names)(sizeof (zoom_level_names) / sizeof ((zoom_level_names)[0])); i++) {
6714 if (get_text_ellipsis_limit_for_zoom (pref,
6715 zoom_level_names[i],
6716 &one_limit)) {
6717 text_ellipsis_limits[i] = one_limit;
6718 }
6719 }
6720
6721 g_strfreev (pref);
6722}
6723
6724static void
6725desktop_text_ellipsis_limit_changed_callback (gpointer callback_data)
6726{
6727 int pref;
6728
6729 pref = g_settings_get_int (caja_desktop_preferences, CAJA_PREFERENCES_DESKTOP_TEXT_ELLIPSIS_LIMIT"text-ellipsis-limit");
6730 desktop_text_ellipsis_limit = pref;
6731}
6732
6733static void
6734caja_icon_container_init (CajaIconContainer *container)
6735{
6736 CajaIconContainerDetails *details;
6737 EelBackground *background;
6738 static gboolean setup_prefs = FALSE(0);
6739
6740 details = g_new0 (CajaIconContainerDetails, 1)(CajaIconContainerDetails *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (CajaIconContainerDetails); 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; }))
;
6741
6742 details->icon_set = g_hash_table_new (g_direct_hash, g_direct_equal);
6743 details->layout_timestamp = UNDEFINED_TIME((time_t) (-1));
6744
6745 details->zoom_level = CAJA_ZOOM_LEVEL_STANDARD;
6746
6747 details->font_size_table[CAJA_ZOOM_LEVEL_SMALLEST] = -2 * PANGO_SCALE1024;
6748 details->font_size_table[CAJA_ZOOM_LEVEL_SMALLER] = -2 * PANGO_SCALE1024;
6749 details->font_size_table[CAJA_ZOOM_LEVEL_SMALL] = -0 * PANGO_SCALE1024;
6750 details->font_size_table[CAJA_ZOOM_LEVEL_STANDARD] = 0 * PANGO_SCALE1024;
6751 details->font_size_table[CAJA_ZOOM_LEVEL_LARGE] = 0 * PANGO_SCALE1024;
6752 details->font_size_table[CAJA_ZOOM_LEVEL_LARGER] = 0 * PANGO_SCALE1024;
6753 details->font_size_table[CAJA_ZOOM_LEVEL_LARGEST] = 0 * PANGO_SCALE1024;
6754
6755 container->details = details;
6756
6757 /* when the background changes, we must set up the label text color */
6758 background = eel_get_widget_background (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
6759
6760 g_signal_connect (container, "focus-in-event",g_signal_connect_data ((container), ("focus-in-event"), (((GCallback
) (handle_focus_in_event))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
6761 G_CALLBACK (handle_focus_in_event), NULL)g_signal_connect_data ((container), ("focus-in-event"), (((GCallback
) (handle_focus_in_event))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
6762 g_signal_connect (container, "focus-out-event",g_signal_connect_data ((container), ("focus-out-event"), (((GCallback
) (handle_focus_out_event))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
6763 G_CALLBACK (handle_focus_out_event), NULL)g_signal_connect_data ((container), ("focus-out-event"), (((GCallback
) (handle_focus_out_event))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
6764
6765 g_signal_connect (container, "notify::scale-factor",g_signal_connect_data ((container), ("notify::scale-factor"),
(((GCallback) (handle_scale_factor_changed))), (((void*)0)),
((void*)0), (GConnectFlags) 0)
6766 G_CALLBACK (handle_scale_factor_changed), NULL)g_signal_connect_data ((container), ("notify::scale-factor"),
(((GCallback) (handle_scale_factor_changed))), (((void*)0)),
((void*)0), (GConnectFlags) 0)
;
6767
6768 eel_background_set_use_base (background, TRUE(!(0)));
6769
6770 if (!setup_prefs)
6771 {
6772 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
6773 "changed::" CAJA_PREFERENCES_ICON_VIEW_TEXT_ELLIPSIS_LIMIT,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
6774 G_CALLBACK (text_ellipsis_limit_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
6775 NULL)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
6776 text_ellipsis_limit_changed_callback (NULL((void*)0));
6777
6778 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (desktop_text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
6779 "changed::" CAJA_PREFERENCES_DESKTOP_TEXT_ELLIPSIS_LIMIT,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (desktop_text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
6780 G_CALLBACK (desktop_text_ellipsis_limit_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (desktop_text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
6781 NULL)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"text-ellipsis-limit"), (((GCallback) (desktop_text_ellipsis_limit_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
6782 desktop_text_ellipsis_limit_changed_callback (NULL((void*)0));
6783
6784 setup_prefs = TRUE(!(0));
6785 }
6786}
6787
6788typedef struct
6789{
6790 CajaIconContainer *container;
6791 GdkEventButton *event;
6792} ContextMenuParameters;
6793
6794static gboolean
6795handle_icon_double_click (CajaIconContainer *container,
6796 CajaIcon *icon,
6797 GdkEventButton *event)
6798{
6799 CajaIconContainerDetails *details;
6800
6801 if (event->button != DRAG_BUTTON1)
6802 {
6803 return FALSE(0);
6804 }
6805
6806 details = container->details;
6807
6808 if (!details->single_click_mode &&
6809 clicked_within_double_click_interval (container) &&
6810 details->double_click_icon[0] == details->double_click_icon[1] &&
6811 details->double_click_button[0] == details->double_click_button[1])
6812 {
6813 if (!button_event_modifies_selection (event))
6814 {
6815 activate_selected_items (container);
6816 return TRUE(!(0));
6817 }
6818 else if ((event->state & GDK_CONTROL_MASK) == 0 &&
6819 (event->state & GDK_SHIFT_MASK) != 0)
6820 {
6821 activate_selected_items_alternate (container, icon);
6822 return TRUE(!(0));
6823 }
6824 }
6825
6826 return FALSE(0);
6827}
6828
6829/* CajaIcon event handling. */
6830
6831/* Conceptually, pressing button 1 together with CTRL or SHIFT toggles
6832 * selection of a single icon without affecting the other icons;
6833 * without CTRL or SHIFT, it selects a single icon and un-selects all
6834 * the other icons. But in this latter case, the de-selection should
6835 * only happen when the button is released if the icon is already
6836 * selected, because the user might select multiple icons and drag all
6837 * of them by doing a simple click-drag.
6838*/
6839
6840static gboolean
6841handle_icon_button_press (CajaIconContainer *container,
6842 CajaIcon *icon,
6843 GdkEventButton *event)
6844{
6845 CajaIconContainerDetails *details;
6846
6847 details = container->details;
6848
6849 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
6850 {
6851 return TRUE(!(0));
6852 }
6853
6854 if (event->button != DRAG_BUTTON1
6855 && event->button != CONTEXTUAL_MENU_BUTTON3
6856 && event->button != DRAG_MENU_BUTTON2)
6857 {
6858 return TRUE(!(0));
6859 }
6860
6861 if ((event->button == DRAG_BUTTON1) &&
6862 event->type == GDK_BUTTON_PRESS)
6863 {
6864 /* The next double click has to be on this icon */
6865 details->double_click_icon[1] = details->double_click_icon[0];
6866 details->double_click_icon[0] = icon;
6867
6868 details->double_click_button[1] = details->double_click_button[0];
6869 details->double_click_button[0] = event->button;
6870 }
6871
6872 if (handle_icon_double_click (container, icon, event))
6873 {
6874 /* Double clicking does not trigger a D&D action. */
6875 details->drag_button = 0;
6876 details->drag_icon = NULL((void*)0);
6877 return TRUE(!(0));
6878 }
6879
6880 if (event->button == DRAG_BUTTON1
6881 || event->button == DRAG_MENU_BUTTON2)
6882 {
6883 details->drag_button = event->button;
6884 details->drag_icon = icon;
6885 details->drag_x = event->x;
6886 details->drag_y = event->y;
6887 details->drag_state = DRAG_STATE_MOVE_OR_COPY;
6888 details->drag_started = FALSE(0);
6889
6890 /* Check to see if this is a click on the stretch handles.
6891 * If so, it won't modify the selection.
6892 */
6893 if (icon == container->details->stretch_icon)
6894 {
6895 if (start_stretching (container, (GdkEvent *)event))
6896 {
6897 return TRUE(!(0));
6898 }
6899 }
6900 }
6901
6902 /* Modify the selection as appropriate. Selection is modified
6903 * the same way for contextual menu as it would be without.
6904 */
6905 details->icon_selected_on_button_down = icon->is_selected;
6906
6907 if ((event->button == DRAG_BUTTON1 || event->button == MIDDLE_BUTTON2) &&
6908 (event->state & GDK_SHIFT_MASK) != 0)
6909 {
6910 CajaIcon *start_icon;
6911
6912 start_icon = details->range_selection_base_icon;
6913 if (start_icon == NULL((void*)0) || !start_icon->is_selected)
6914 {
6915 start_icon = icon;
6916 details->range_selection_base_icon = icon;
6917 }
6918 if (select_range (container, start_icon, icon,
6919 (event->state & GDK_CONTROL_MASK) == 0))
6920 {
6921 g_signal_emit (container,
6922 signals[SELECTION_CHANGED], 0);
6923 }
6924 }
6925 else if (!details->icon_selected_on_button_down)
6926 {
6927 details->range_selection_base_icon = icon;
6928 if (button_event_modifies_selection (event))
6929 {
6930 icon_toggle_selected (container, icon);
6931 g_signal_emit (container,
6932 signals[SELECTION_CHANGED], 0);
6933 }
6934 else
6935 {
6936 select_one_unselect_others (container, icon);
6937 g_signal_emit (container,
6938 signals[SELECTION_CHANGED], 0);
6939 }
6940 }
6941
6942 if (event->button == CONTEXTUAL_MENU_BUTTON3)
6943 {
6944 g_signal_emit (container,
6945 signals[CONTEXT_CLICK_SELECTION], 0,
6946 event);
6947 }
6948
6949
6950 return TRUE(!(0));
6951}
6952
6953static int
6954item_event_callback (EelCanvasItem *item,
6955 GdkEvent *event,
6956 gpointer data)
6957{
6958 CajaIconContainer *container;
6959 CajaIcon *icon;
6960
6961 container = CAJA_ICON_CONTAINER (data)((((CajaIconContainer*) (void *) ((data)))));
6962
6963 icon = CAJA_ICON_CANVAS_ITEM (item)((((CajaIconCanvasItem*) (void *) ((item)))))->user_data;
6964 g_assert (icon != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if (icon != ((void*)0)) _g_boolean_var_161 = 1; else _g_boolean_var_161
= 0; _g_boolean_var_161; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 6964, ((const char*)
(__func__)), "icon != NULL"); } while (0)
;
6965
6966 switch (event->type)
6967 {
6968 case GDK_BUTTON_PRESS:
6969 if (handle_icon_button_press (container, icon, &event->button))
6970 {
6971 /* Stop the event from being passed along further. Returning
6972 * TRUE ain't enough.
6973 */
6974 return TRUE(!(0));
6975 }
6976 return FALSE(0);
6977 default:
6978 return FALSE(0);
6979 }
6980}
6981
6982GtkWidget *
6983caja_icon_container_new (void)
6984{
6985 return gtk_widget_new (CAJA_TYPE_ICON_CONTAINERcaja_icon_container_get_type(), NULL((void*)0));
6986}
6987
6988/* Clear all of the icons in the container. */
6989void
6990caja_icon_container_clear (CajaIconContainer *container)
6991{
6992 CajaIconContainerDetails *details;
6993 GList *p;
6994 CajaIcon *icon = NULL((void*)0);
6995
6996 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
6997
6998 details = container->details;
6999 details->layout_timestamp = UNDEFINED_TIME((time_t) (-1));
7000 details->store_layout_timestamps_when_finishing_new_icons = FALSE(0);
7001
7002 if (details->icons == NULL((void*)0))
7003 {
7004 return;
7005 }
7006
7007 end_renaming_mode (container, TRUE(!(0)));
7008
7009 clear_keyboard_focus (container);
7010 clear_keyboard_rubberband_start (container);
7011 unschedule_keyboard_icon_reveal (container);
7012 set_pending_icon_to_reveal (container, NULL((void*)0));
7013 details->stretch_icon = NULL((void*)0);
7014 details->drop_target = NULL((void*)0);
7015
7016 for (p = details->icons; p != NULL((void*)0); p = p->next)
7017 {
7018 icon = p->data;
7019 if (icon->is_monitored)
7020 {
7021 caja_icon_container_stop_monitor_top_left (container,
7022 icon->data,
7023 icon);
7024 }
7025 icon_free (p->data);
7026 }
7027 g_list_free (details->icons);
7028 details->icons = NULL((void*)0);
7029 g_list_free (details->new_icons);
7030 details->new_icons = NULL((void*)0);
7031
7032 g_hash_table_destroy (details->icon_set);
7033 details->icon_set = g_hash_table_new (g_direct_hash, g_direct_equal);
7034
7035 caja_icon_container_update_scroll_region (container);
7036}
7037
7038gboolean
7039caja_icon_container_is_empty (CajaIconContainer *container)
7040{
7041 return container->details->icons == NULL((void*)0);
7042}
7043
7044CajaIconData *
7045caja_icon_container_get_first_visible_icon (CajaIconContainer *container)
7046{
7047 GList *l;
7048 CajaIcon *icon, *best_icon;
7049 double x, y;
7050 double x1, y1, x2, y2;
7051 double *pos, best_pos;
7052 double hadj_v, vadj_v, h_page_size;
7053 gboolean better_icon;
7054 gboolean compare_lt;
7055
7056 hadj_v = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
7057 vadj_v = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
7058 h_page_size = gtk_adjustment_get_page_size (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
7059
7060 if (caja_icon_container_is_layout_rtl (container))
7061 {
7062 x = hadj_v + h_page_size - ICON_PAD_LEFT4 - 1;
7063 y = vadj_v;
7064 }
7065 else
7066 {
7067 x = hadj_v;
7068 y = vadj_v;
7069 }
7070
7071 eel_canvas_c2w (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
7072 x, y,
7073 &x, &y);
7074
7075 l = container->details->icons;
7076 best_icon = NULL((void*)0);
7077 best_pos = 0;
7078 while (l != NULL((void*)0))
7079 {
7080 icon = l->data;
7081
7082 if (icon_is_positioned (icon))
7083 {
7084 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
7085 &x1, &y1, &x2, &y2);
7086
7087 compare_lt = FALSE(0);
7088 if (caja_icon_container_is_layout_vertical (container))
7089 {
7090 pos = &x1;
7091 if (caja_icon_container_is_layout_rtl (container))
7092 {
7093 compare_lt = TRUE(!(0));
7094 better_icon = x1 < x + ICON_PAD_LEFT4;
7095 }
7096 else
7097 {
7098 better_icon = x2 > x + ICON_PAD_LEFT4;
7099 }
7100 }
7101 else
7102 {
7103 pos = &y1;
7104 better_icon = y2 > y + ICON_PAD_TOP4;
7105 }
7106 if (better_icon)
7107 {
7108 if (best_icon == NULL((void*)0))
7109 {
7110 better_icon = TRUE(!(0));
7111 }
7112 else if (compare_lt)
7113 {
7114 better_icon = best_pos < *pos;
7115 }
7116 else
7117 {
7118 better_icon = best_pos > *pos;
7119 }
7120
7121 if (better_icon)
7122 {
7123 best_icon = icon;
7124 best_pos = *pos;
7125 }
7126 }
7127 }
7128
7129 l = l->next;
7130 }
7131
7132 return best_icon ? best_icon->data : NULL((void*)0);
7133}
7134
7135/* puts the icon at the top of the screen */
7136void
7137caja_icon_container_scroll_to_icon (CajaIconContainer *container,
7138 CajaIconData *data)
7139{
7140 GList *l;
7141 GtkAdjustment *hadj, *vadj;
7142 EelIRect bounds;
7143 GtkAllocation allocation;
7144 CajaIcon *icon = NULL((void*)0);
7145
7146 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
7147 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
7148 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
7149
7150 /* We need to force a relayout now if there are updates queued
7151 * since we need the final positions */
7152 caja_icon_container_layout_now (container);
7153
7154 l = container->details->icons;
7155 while (l != NULL((void*)0)) {
7156 icon = l->data;
7157
7158 if (icon->data == data &&
7159 icon_is_positioned (icon)) {
7160
7161 if (caja_icon_container_is_auto_layout (container)) {
7162 /* ensure that we reveal the entire row/column */
7163 icon_get_row_and_column_bounds (container, icon, &bounds, TRUE(!(0)));
7164 } else {
7165 item_get_canvas_bounds (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))), &bounds, TRUE(!(0)));
7166 }
7167
7168 if (caja_icon_container_is_layout_vertical (container)) {
7169 if (caja_icon_container_is_layout_rtl (container)) {
7170 gtk_adjustment_set_value (hadj, bounds.x1 - allocation.width);
7171 } else {
7172 gtk_adjustment_set_value (hadj, bounds.x0);
7173 }
7174 } else {
7175 gtk_adjustment_set_value (vadj, bounds.y0);
7176 }
7177 }
7178
7179 l = l->next;
7180 }
7181}
7182
7183/* Call a function for all the icons. */
7184typedef struct
7185{
7186 CajaIconCallback callback;
7187 gpointer callback_data;
7188} CallbackAndData;
7189
7190static void
7191call_icon_callback (gpointer data, gpointer callback_data)
7192{
7193 CajaIcon *icon;
7194 CallbackAndData *callback_and_data;
7195
7196 icon = data;
7197 callback_and_data = callback_data;
7198 (* callback_and_data->callback) (icon->data, callback_and_data->callback_data);
7199}
7200
7201void
7202caja_icon_container_for_each (CajaIconContainer *container,
7203 CajaIconCallback callback,
7204 gpointer callback_data)
7205{
7206 CallbackAndData callback_and_data;
7207
7208 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_163 = 1; else _g_boolean_var_163 =
0; _g_boolean_var_163; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
7209
7210 callback_and_data.callback = callback;
7211 callback_and_data.callback_data = callback_data;
7212
7213 g_list_foreach (container->details->icons,
7214 call_icon_callback, &callback_and_data);
7215}
7216
7217static int
7218selection_changed_at_idle_callback (gpointer data)
7219{
7220 CajaIconContainer *container;
7221
7222 container = CAJA_ICON_CONTAINER (data)((((CajaIconContainer*) (void *) ((data)))));
7223
7224 g_signal_emit (container,
7225 signals[SELECTION_CHANGED], 0);
7226
7227 container->details->selection_changed_id = 0;
7228 return FALSE(0);
7229}
7230
7231/* utility routine to remove a single icon from the container */
7232
7233static void
7234icon_destroy (CajaIconContainer *container,
7235 CajaIcon *icon)
7236{
7237 CajaIconContainerDetails *details;
7238 gboolean was_selected;
7239 CajaIcon *icon_to_focus;
7240 GList *item;
7241
7242 details = container->details;
7243
7244 item = g_list_find (details->icons, icon);
7245 item = item->next ? item->next : item->prev;
7246 icon_to_focus = (item != NULL((void*)0)) ? item->data : NULL((void*)0);
7247
7248 details->icons = g_list_remove (details->icons, icon);
7249 details->new_icons = g_list_remove (details->new_icons, icon);
7250 g_hash_table_remove (details->icon_set, icon->data);
7251
7252 was_selected = icon->is_selected;
7253
7254 if (details->keyboard_focus == icon ||
7255 details->keyboard_focus == NULL((void*)0))
7256 {
7257 if (icon_to_focus != NULL((void*)0))
7258 {
7259 set_keyboard_focus (container, icon_to_focus);
7260 }
7261 else
7262 {
7263 clear_keyboard_focus (container);
7264 }
7265 }
7266
7267 if (details->keyboard_rubberband_start == icon)
7268 {
7269 clear_keyboard_rubberband_start (container);
7270 }
7271
7272 if (details->keyboard_icon_to_reveal == icon)
7273 {
7274 unschedule_keyboard_icon_reveal (container);
7275 }
7276 if (details->drag_icon == icon)
7277 {
7278 clear_drag_state (container);
7279 }
7280 if (details->drop_target == icon)
7281 {
7282 details->drop_target = NULL((void*)0);
7283 }
7284 if (details->range_selection_base_icon == icon)
7285 {
7286 details->range_selection_base_icon = NULL((void*)0);
7287 }
7288 if (details->pending_icon_to_reveal == icon)
7289 {
7290 set_pending_icon_to_reveal (container, NULL((void*)0));
7291 }
7292 if (details->stretch_icon == icon)
7293 {
7294 details->stretch_icon = NULL((void*)0);
7295 }
7296
7297 if (icon->is_monitored)
7298 {
7299 caja_icon_container_stop_monitor_top_left (container,
7300 icon->data,
7301 icon);
7302 }
7303 icon_free (icon);
7304
7305 if (was_selected)
7306 {
7307 /* Coalesce multiple removals causing multiple selection_changed events */
7308 details->selection_changed_id = g_idle_add (selection_changed_at_idle_callback, container);
7309 }
7310}
7311
7312/* activate any selected items in the container */
7313static void
7314activate_selected_items (CajaIconContainer *container)
7315{
7316 GList *selection;
7317
7318 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_164 = 1; else _g_boolean_var_164 =
0; _g_boolean_var_164; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
7319
7320 selection = caja_icon_container_get_selection (container);
7321 if (selection != NULL((void*)0))
7322 {
7323 g_signal_emit (container,
7324 signals[ACTIVATE], 0,
7325 selection);
7326 }
7327 g_list_free (selection);
7328}
7329
7330static void
7331activate_selected_items_alternate (CajaIconContainer *container,
7332 CajaIcon *icon)
7333{
7334 GList *selection;
7335
7336 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 7336, ((const char*)
(__func__)), "CAJA_IS_ICON_CONTAINER (container)"); } while (
0)
;
7337
7338 if (icon != NULL((void*)0))
7339 {
7340 selection = g_list_prepend (NULL((void*)0), icon->data);
7341 }
7342 else
7343 {
7344 selection = caja_icon_container_get_selection (container);
7345 }
7346 if (selection != NULL((void*)0))
7347 {
7348 g_signal_emit (container,
7349 signals[ACTIVATE_ALTERNATE], 0,
7350 selection);
7351 }
7352 g_list_free (selection);
7353}
7354
7355static CajaIcon *
7356get_icon_being_renamed (CajaIconContainer *container)
7357{
7358 CajaIcon *rename_icon;
7359
7360 if (!is_renaming (container))
7361 {
7362 return NULL((void*)0);
7363 }
7364
7365 g_assert (!has_multiple_selection (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if (!has_multiple_selection (container)) _g_boolean_var_166
= 1; else _g_boolean_var_166 = 0; _g_boolean_var_166; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7365, ((const char*) (__func__)), "!has_multiple_selection (container)"
); } while (0)
;
7366
7367 rename_icon = get_first_selected_icon (container);
7368 g_assert (rename_icon != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if (rename_icon != ((void*)0)) _g_boolean_var_167 = 1; else
_g_boolean_var_167 = 0; _g_boolean_var_167; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 7368, ((const char*)
(__func__)), "rename_icon != NULL"); } while (0)
;
7369
7370 return rename_icon;
7371}
7372
7373static CajaIconInfo *
7374caja_icon_container_get_icon_images (CajaIconContainer *container,
7375 CajaIconData *data,
7376 int size,
7377 GList **emblem_pixbufs,
7378 char **embedded_text,
7379 gboolean for_drag_accept,
7380 gboolean need_large_embeddded_text,
7381 gboolean *embedded_text_needs_loading,
7382 gboolean *has_open_window)
7383{
7384 CajaIconContainerClass *klass;
7385
7386 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
7387 g_assert (klass->get_icon_images != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if (klass->get_icon_images != ((void*)0)) _g_boolean_var_168
= 1; else _g_boolean_var_168 = 0; _g_boolean_var_168; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7387, ((const char*) (__func__)), "klass->get_icon_images != NULL"
); } while (0)
;
7388
7389 return klass->get_icon_images (container, data, size, emblem_pixbufs, embedded_text, for_drag_accept, need_large_embeddded_text, embedded_text_needs_loading, has_open_window);
7390}
7391
7392static void
7393caja_icon_container_freeze_updates (CajaIconContainer *container)
7394{
7395 CajaIconContainerClass *klass;
7396
7397 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
7398 g_assert (klass->freeze_updates != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if (klass->freeze_updates != ((void*)0)) _g_boolean_var_169
= 1; else _g_boolean_var_169 = 0; _g_boolean_var_169; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7398, ((const char*) (__func__)), "klass->freeze_updates != NULL"
); } while (0)
;
7399
7400 klass->freeze_updates (container);
7401}
7402
7403static void
7404caja_icon_container_unfreeze_updates (CajaIconContainer *container)
7405{
7406 CajaIconContainerClass *klass;
7407
7408 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
7409 g_assert (klass->unfreeze_updates != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if (klass->unfreeze_updates != ((void*)0)) _g_boolean_var_170
= 1; else _g_boolean_var_170 = 0; _g_boolean_var_170; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7409, ((const char*) (__func__)), "klass->unfreeze_updates != NULL"
); } while (0)
;
7410
7411 klass->unfreeze_updates (container);
7412}
7413
7414static void
7415caja_icon_container_start_monitor_top_left (CajaIconContainer *container,
7416 CajaIconData *data,
7417 gconstpointer client,
7418 gboolean large_text)
7419{
7420 CajaIconContainerClass *klass;
7421
7422 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
7423 g_assert (klass->start_monitor_top_left != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if (klass->start_monitor_top_left != ((void*)0)) _g_boolean_var_171
= 1; else _g_boolean_var_171 = 0; _g_boolean_var_171; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7423, ((const char*) (__func__)), "klass->start_monitor_top_left != NULL"
); } while (0)
;
7424
7425 klass->start_monitor_top_left (container, data, client, large_text);
7426}
7427
7428static void
7429caja_icon_container_stop_monitor_top_left (CajaIconContainer *container,
7430 CajaIconData *data,
7431 gconstpointer client)
7432{
7433 CajaIconContainerClass *klass;
7434
7435 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
7436 g_return_if_fail (klass->stop_monitor_top_left != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if (klass->stop_monitor_top_left != ((void*)0)) _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__)), "klass->stop_monitor_top_left != NULL"
); return; } } while (0)
;
7437
7438 klass->stop_monitor_top_left (container, data, client);
7439}
7440
7441
7442static void
7443caja_icon_container_prioritize_thumbnailing (CajaIconContainer *container,
7444 CajaIcon *icon)
7445{
7446 CajaIconContainerClass *klass;
7447
7448 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
7449 g_assert (klass->prioritize_thumbnailing != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if (klass->prioritize_thumbnailing != ((void*)0)) _g_boolean_var_173
= 1; else _g_boolean_var_173 = 0; _g_boolean_var_173; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7449, ((const char*) (__func__)), "klass->prioritize_thumbnailing != NULL"
); } while (0)
;
7450
7451 klass->prioritize_thumbnailing (container, icon->data);
7452}
7453
7454static void
7455caja_icon_container_update_visible_icons (CajaIconContainer *container)
7456{
7457 GtkAdjustment *vadj, *hadj;
7458 double min_y, max_y;
7459 double min_x, max_x;
7460 double x0, y0, x1, y1;
7461 GList *node;
7462 gboolean visible;
7463 GtkAllocation allocation;
7464 CajaIcon *icon = NULL((void*)0);
7465
7466 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
7467 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))));
7468 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
7469
7470 min_x = gtk_adjustment_get_value (hadj);
7471 max_x = min_x + allocation.width;
7472
7473 min_y = gtk_adjustment_get_value (vadj);
7474 max_y = min_y + allocation.height;
7475
7476 eel_canvas_c2w (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
7477 min_x, min_y, &min_x, &min_y);
7478 eel_canvas_c2w (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
7479 max_x, max_y, &max_x, &max_y);
7480
7481 /* Do the iteration in reverse to get the render-order from top to
7482 * bottom for the prioritized thumbnails.
7483 */
7484 for (node = g_list_last (container->details->icons); node != NULL((void*)0); node = node->prev)
7485 {
7486 icon = node->data;
7487
7488 if (icon_is_positioned (icon))
7489 {
7490 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
7491 &x0,
7492 &y0,
7493 &x1,
7494 &y1);
7495 eel_canvas_item_i2w (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))))->parent,
7496 &x0,
7497 &y0);
7498 eel_canvas_item_i2w (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))))->parent,
7499 &x1,
7500 &y1);
7501
7502 if (caja_icon_container_is_layout_vertical (container))
7503 {
7504 visible = x1 >= min_x && x0 <= max_x;
7505 }
7506 else
7507 {
7508 visible = y1 >= min_y && y0 <= max_y;
7509 }
7510
7511 if (visible)
7512 {
7513 caja_icon_canvas_item_set_is_visible (icon->item, TRUE(!(0)));
7514 caja_icon_container_prioritize_thumbnailing (container,
7515 icon);
7516 }
7517 else
7518 {
7519 caja_icon_canvas_item_set_is_visible (icon->item, FALSE(0));
7520 }
7521 }
7522 }
7523}
7524
7525static void
7526handle_vadjustment_changed (GtkAdjustment *adjustment,
7527 CajaIconContainer *container)
7528{
7529 if (!caja_icon_container_is_layout_vertical (container))
7530 {
7531 caja_icon_container_update_visible_icons (container);
7532 }
7533}
7534
7535static void
7536handle_hadjustment_changed (GtkAdjustment *adjustment,
7537 CajaIconContainer *container)
7538{
7539 if (caja_icon_container_is_layout_vertical (container))
7540 {
7541 caja_icon_container_update_visible_icons (container);
7542 }
7543}
7544
7545
7546void
7547caja_icon_container_update_icon (CajaIconContainer *container,
7548 CajaIcon *icon)
7549{
7550 CajaIconContainerDetails *details;
7551 guint icon_size;
7552 guint min_image_size, max_image_size;
7553 CajaIconInfo *icon_info;
7554 GdkPoint *attach_points;
7555 int n_attach_points;
7556 gboolean has_embedded_text_rect;
7557 GdkPixbuf *pixbuf;
7558 GList *emblem_pixbufs;
7559 char *editable_text, *additional_text;
7560 char *embedded_text;
7561 GdkRectangle embedded_text_rect;
7562 gboolean large_embedded_text;
7563 gboolean embedded_text_needs_loading;
7564 gboolean has_open_window;
7565
7566 if (icon == NULL((void*)0))
7567 {
7568 return;
7569 }
7570
7571 details = container->details;
7572
7573 /* compute the maximum size based on the scale factor */
7574 min_image_size = MINIMUM_IMAGE_SIZE24 * EEL_CANVAS (container)((((EelCanvas*) (void *) ((container)))))->pixels_per_unit;
7575 max_image_size = MAX (MAXIMUM_IMAGE_SIZE * EEL_CANVAS (container)->pixels_per_unit, CAJA_ICON_MAXIMUM_SIZE)(((96 * ((((EelCanvas*) (void *) ((container)))))->pixels_per_unit
) > (320)) ? (96 * ((((EelCanvas*) (void *) ((container)))
))->pixels_per_unit) : (320))
;
7576
7577 /* Get the appropriate images for the file. */
7578 if (container->details->forced_icon_size > 0)
7579 {
7580 icon_size = container->details->forced_icon_size;
7581 }
7582 else
7583 {
7584 icon_get_size (container, icon, &icon_size);
7585 }
7586
7587
7588 icon_size = MAX (icon_size, min_image_size)(((icon_size) > (min_image_size)) ? (icon_size) : (min_image_size
))
;
7589 icon_size = MIN (icon_size, max_image_size)(((icon_size) < (max_image_size)) ? (icon_size) : (max_image_size
))
;
7590
7591 /* Get the icons. */
7592 emblem_pixbufs = NULL((void*)0);
7593 embedded_text = NULL((void*)0);
7594 large_embedded_text = icon_size > ICON_SIZE_FOR_LARGE_EMBEDDED_TEXT55;
7595 icon_info = caja_icon_container_get_icon_images (container, icon->data, icon_size,
7596 &emblem_pixbufs,
7597 &embedded_text,
7598 icon == details->drop_target,
7599 large_embedded_text, &embedded_text_needs_loading,
7600 &has_open_window);
7601
7602
7603 if (container->details->forced_icon_size > 0)
7604 pixbuf = caja_icon_info_get_pixbuf_at_size (icon_info, icon_size);
7605 else
7606 pixbuf = caja_icon_info_get_pixbuf (icon_info);
7607 caja_icon_info_get_attach_points (icon_info, &attach_points, &n_attach_points);
7608 has_embedded_text_rect = caja_icon_info_get_embedded_rect (icon_info,
7609 &embedded_text_rect);
7610
7611 if (has_embedded_text_rect && embedded_text_needs_loading)
7612 {
7613 icon->is_monitored = TRUE(!(0));
7614 caja_icon_container_start_monitor_top_left (container, icon->data, icon, large_embedded_text);
7615 }
7616
7617 caja_icon_container_get_icon_text (container,
7618 icon->data,
7619 &editable_text,
7620 &additional_text,
7621 FALSE(0));
7622
7623 /* If name of icon being renamed was changed from elsewhere, end renaming mode.
7624 * Alternatively, we could replace the characters in the editable text widget
7625 * with the new name, but that could cause timing problems if the user just
7626 * happened to be typing at that moment.
7627 */
7628 if (icon == get_icon_being_renamed (container) &&
7629 g_strcmp0 (editable_text,
7630 caja_icon_canvas_item_get_editable_text (icon->item)) != 0)
7631 {
7632 end_renaming_mode (container, FALSE(0));
7633 }
7634
7635 eel_canvas_item_set (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
7636 "editable_text", editable_text,
7637 "additional_text", additional_text,
7638 "highlighted_for_drop", icon == details->drop_target,
7639 NULL((void*)0));
7640
7641 caja_icon_canvas_item_set_image (icon->item, pixbuf);
7642 caja_icon_canvas_item_set_attach_points (icon->item, attach_points, n_attach_points);
7643 caja_icon_canvas_item_set_emblems (icon->item, emblem_pixbufs);
7644 caja_icon_canvas_item_set_embedded_text_rect (icon->item, &embedded_text_rect);
7645 caja_icon_canvas_item_set_embedded_text (icon->item, embedded_text);
7646
7647 /* Let the pixbufs go. */
7648 g_object_unref (pixbuf);
7649 g_list_free_full (emblem_pixbufs, g_object_unref);
7650
7651 g_free (editable_text);
7652 g_free (additional_text);
7653
7654 g_object_unref (icon_info);
7655}
7656
7657static gboolean
7658assign_icon_position (CajaIconContainer *container,
7659 CajaIcon *icon)
7660{
7661 gboolean have_stored_position;
7662 CajaIconPosition position;
7663
7664 /* Get the stored position. */
7665 have_stored_position = FALSE(0);
7666 position.scale = 1.0;
7667 g_signal_emit (container,
7668 signals[GET_STORED_ICON_POSITION], 0,
7669 icon->data,
7670 &position,
7671 &have_stored_position);
7672 icon->scale = position.scale;
7673 if (!container->details->auto_layout)
7674 {
7675 if (have_stored_position)
7676 {
7677 icon_set_position (icon, position.x, position.y);
7678 icon->saved_ltr_x = icon->x;
7679 }
7680 else
7681 {
7682 return FALSE(0);
7683 }
7684 }
7685 return TRUE(!(0));
7686}
7687
7688static void
7689finish_adding_icon (CajaIconContainer *container,
7690 CajaIcon *icon)
7691{
7692 caja_icon_container_update_icon (container, icon);
7693 eel_canvas_item_show (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))));
7694
7695 g_signal_connect_object (icon->item, "event",
7696 G_CALLBACK (item_event_callback)((GCallback) (item_event_callback)), container, 0);
7697
7698 g_signal_emit (container, signals[ICON_ADDED], 0, icon->data);
7699}
7700
7701static void
7702finish_adding_new_icons (CajaIconContainer *container)
7703{
7704 GList *p, *new_icons, *no_position_icons, *semi_position_icons;
7705 CajaIcon *icon;
7706 double bottom;
7707
7708 new_icons = container->details->new_icons;
7709 container->details->new_icons = NULL((void*)0);
7710 container->details->is_populating_container =
7711 g_list_length(new_icons) == g_hash_table_size(container->details->icon_set);
7712
7713 /* Position most icons (not unpositioned manual-layout icons). */
7714 new_icons = g_list_reverse (new_icons);
7715 no_position_icons = semi_position_icons = NULL((void*)0);
7716 for (p = new_icons; p != NULL((void*)0); p = p->next)
7717 {
7718 icon = p->data;
7719 if (icon->has_lazy_position)
7720 {
7721 assign_icon_position (container, icon);
7722 semi_position_icons = g_list_prepend (semi_position_icons, icon);
7723 }
7724 else if (!assign_icon_position (container, icon))
7725 {
7726 no_position_icons = g_list_prepend (no_position_icons, icon);
7727 }
7728
7729 finish_adding_icon (container, icon);
7730 }
7731 g_list_free (new_icons);
7732
7733 if (semi_position_icons != NULL((void*)0))
7734 {
7735 PlacementGrid *grid;
7736 time_t now;
7737 gboolean dummy;
7738
7739 g_assert (!container->details->auto_layout)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if (!container->details->auto_layout) _g_boolean_var_174
= 1; else _g_boolean_var_174 = 0; _g_boolean_var_174; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7739, ((const char*) (__func__)), "!container->details->auto_layout"
); } while (0)
;
7740
7741 semi_position_icons = g_list_reverse (semi_position_icons);
7742
7743 /* This is currently only used on the desktop.
7744 * Thus, we pass FALSE for tight, like lay_down_icons_tblr */
7745 grid = placement_grid_new (container, FALSE(0));
7746
7747 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
7748 {
7749 icon = p->data;
7750
7751 if (icon_is_positioned (icon) && !icon->has_lazy_position)
7752 {
7753 placement_grid_mark_icon (grid, icon);
7754 }
7755 }
7756
7757 now = time (NULL((void*)0));
7758
7759 for (p = semi_position_icons; p != NULL((void*)0); p = p->next)
7760 {
7761 CajaIcon *icon;
7762 CajaIconPosition position;
7763 int x, y;
7764
7765 icon = p->data;
7766 x = icon->x;
7767 y = icon->y;
7768
7769 find_empty_location (container, grid,
7770 icon, x, y, &x, &y);
7771
7772 icon_set_position (icon, x, y);
7773
7774 position.x = icon->x;
7775 position.y = icon->y;
7776 position.scale = icon->scale;
7777 placement_grid_mark_icon (grid, icon);
7778 g_signal_emit (container, signals[ICON_POSITION_CHANGED], 0,
7779 icon->data, &position);
7780 g_signal_emit (container, signals[STORE_LAYOUT_TIMESTAMP], 0,
7781 icon->data, &now, &dummy);
7782
7783 /* ensure that next time we run this code, the formerly semi-positioned
7784 * icons are treated as being positioned. */
7785 icon->has_lazy_position = FALSE(0);
7786 }
7787
7788 placement_grid_free (grid);
7789
7790 g_list_free (semi_position_icons);
7791 }
7792
7793 /* Position the unpositioned manual layout icons. */
7794 if (no_position_icons != NULL((void*)0))
7795 {
7796 g_assert (!container->details->auto_layout)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if (!container->details->auto_layout) _g_boolean_var_175
= 1; else _g_boolean_var_175 = 0; _g_boolean_var_175; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 7796, ((const char*) (__func__)), "!container->details->auto_layout"
); } while (0)
;
7797
7798 sort_icons (container, &no_position_icons);
7799 if (caja_icon_container_get_is_desktop (container))
7800 {
7801 lay_down_icons (container, no_position_icons, CONTAINER_PAD_TOP4);
7802 }
7803 else
7804 {
7805 get_all_icon_bounds (container, NULL((void*)0), NULL((void*)0), NULL((void*)0), &bottom, BOUNDS_USAGE_FOR_LAYOUT);
7806 lay_down_icons (container, no_position_icons, bottom + ICON_PAD_BOTTOM4);
7807 }
7808 g_list_free (no_position_icons);
7809 }
7810
7811 if (container->details->store_layout_timestamps_when_finishing_new_icons)
7812 {
7813 store_layout_timestamps_now (container);
7814 container->details->store_layout_timestamps_when_finishing_new_icons = FALSE(0);
7815 }
7816}
7817
7818static gboolean
7819is_old_or_unknown_icon_data (CajaIconContainer *container,
7820 CajaIconData *data)
7821{
7822 time_t timestamp;
7823 gboolean success;
7824
7825 if (container->details->layout_timestamp == UNDEFINED_TIME((time_t) (-1)))
7826 {
7827 /* don't know */
7828 return FALSE(0);
7829 }
7830
7831 g_signal_emit (container,
7832 signals[GET_STORED_LAYOUT_TIMESTAMP], 0,
7833 data, &timestamp, &success);
7834 return (!success || timestamp < container->details->layout_timestamp);
7835}
7836
7837/**
7838 * caja_icon_container_add:
7839 * @container: A CajaIconContainer
7840 * @data: Icon data.
7841 *
7842 * Add icon to represent @data to container.
7843 * Returns FALSE if there was already such an icon.
7844 **/
7845gboolean
7846caja_icon_container_add (CajaIconContainer *container,
7847 CajaIconData *data)
7848{
7849 CajaIconContainerDetails *details;
7850 CajaIcon *icon;
7851 EelCanvasItem *band, *item;
7852
7853 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
7854 g_return_val_if_fail (data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if (data != ((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__)), "data != NULL"); return
((0)); } } while (0)
;
7855
7856 details = container->details;
7857
7858 if (g_hash_table_lookup (details->icon_set, data) != NULL((void*)0))
7859 {
7860 return FALSE(0);
7861 }
7862
7863 /* Create the new icon, including the canvas item. */
7864 icon = g_new0 (CajaIcon, 1)(CajaIcon *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (CajaIcon); 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
; }))
;
7865 icon->data = data;
7866 icon->x = ICON_UNPOSITIONED_VALUE-1;
7867 icon->y = ICON_UNPOSITIONED_VALUE-1;
7868
7869 /* Whether the saved icon position should only be used
7870 * if the previous icon position is free. If the position
7871 * is occupied, another position near the last one will
7872 */
7873 icon->has_lazy_position = is_old_or_unknown_icon_data (container, data);
7874 icon->scale = 1.0;
7875 icon->item = CAJA_ICON_CANVAS_ITEM((((CajaIconCanvasItem*) (void *) ((eel_canvas_item_new (((((
EelCanvasGroup*) (void *) ((((((EelCanvas*) (void *) ((container
)))))->root))))), caja_icon_canvas_item_get_type (), "visible"
, (0), ((void*)0)))))))
7876 (eel_canvas_item_new (EEL_CANVAS_GROUP (EEL_CANVAS (container)->root),((((CajaIconCanvasItem*) (void *) ((eel_canvas_item_new (((((
EelCanvasGroup*) (void *) ((((((EelCanvas*) (void *) ((container
)))))->root))))), caja_icon_canvas_item_get_type (), "visible"
, (0), ((void*)0)))))))
7877 caja_icon_canvas_item_get_type (),((((CajaIconCanvasItem*) (void *) ((eel_canvas_item_new (((((
EelCanvasGroup*) (void *) ((((((EelCanvas*) (void *) ((container
)))))->root))))), caja_icon_canvas_item_get_type (), "visible"
, (0), ((void*)0)))))))
7878 "visible", FALSE,((((CajaIconCanvasItem*) (void *) ((eel_canvas_item_new (((((
EelCanvasGroup*) (void *) ((((((EelCanvas*) (void *) ((container
)))))->root))))), caja_icon_canvas_item_get_type (), "visible"
, (0), ((void*)0)))))))
7879 NULL))((((CajaIconCanvasItem*) (void *) ((eel_canvas_item_new (((((
EelCanvasGroup*) (void *) ((((((EelCanvas*) (void *) ((container
)))))->root))))), caja_icon_canvas_item_get_type (), "visible"
, (0), ((void*)0)))))))
;
7880 icon->item->user_data = icon;
7881
7882 /* Make sure the icon is under the selection_rectangle */
7883 item = EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))));
7884 band = CAJA_ICON_CONTAINER (item->canvas)((((CajaIconContainer*) (void *) ((item->canvas)))))->details->rubberband_info.selection_rectangle;
7885 if (band)
7886 {
7887 eel_canvas_item_send_behind (item, band);
7888 }
7889
7890 /* Put it on both lists. */
7891 details->icons = g_list_prepend (details->icons, icon);
7892 details->new_icons = g_list_prepend (details->new_icons, icon);
7893
7894 g_hash_table_insert (details->icon_set, data, icon);
7895
7896 /* Run an idle function to add the icons. */
7897 schedule_redo_layout (container);
7898
7899 return TRUE(!(0));
7900}
7901
7902void
7903caja_icon_container_layout_now (CajaIconContainer *container)
7904{
7905 if (container->details->idle_id != 0)
7906 {
7907 unschedule_redo_layout (container);
7908 redo_layout_internal (container);
7909 }
7910
7911 /* Also need to make sure we're properly resized, for instance
7912 * newly added files may trigger a change in the size allocation and
7913 * thus toggle scrollbars on */
7914 gtk_container_check_resize (GTK_CONTAINER (gtk_widget_get_parent (GTK_WIDGET (container)))((((GtkContainer*) (void *) ((gtk_widget_get_parent (((((GtkWidget
*) (void *) ((container)))))))))))
);
7915}
7916
7917/**
7918 * caja_icon_container_remove:
7919 * @container: A CajaIconContainer.
7920 * @data: Icon data.
7921 *
7922 * Remove the icon with this data.
7923 **/
7924gboolean
7925caja_icon_container_remove (CajaIconContainer *container,
7926 CajaIconData *data)
7927{
7928 CajaIcon *icon;
7929
7930 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_178 = 1; else _g_boolean_var_178 =
0; _g_boolean_var_178; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
7931 g_return_val_if_fail (data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (data != ((void*)0)) _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__)), "data != NULL"); return
((0)); } } while (0)
;
7932
7933 end_renaming_mode (container, FALSE(0));
7934
7935 icon = g_hash_table_lookup (container->details->icon_set, data);
7936
7937 if (icon == NULL((void*)0))
7938 {
7939 return FALSE(0);
7940 }
7941
7942 g_signal_emit (container, signals[ICON_REMOVED], 0, icon);
7943
7944 icon_destroy (container, icon);
7945 schedule_redo_layout (container);
7946
7947 return TRUE(!(0));
7948}
7949
7950/**
7951 * caja_icon_container_request_update:
7952 * @container: A CajaIconContainer.
7953 * @data: Icon data.
7954 *
7955 * Update the icon with this data.
7956 **/
7957void
7958caja_icon_container_request_update (CajaIconContainer *container,
7959 CajaIconData *data)
7960{
7961 CajaIcon *icon;
7962
7963 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_180 = 1; else _g_boolean_var_180 =
0; _g_boolean_var_180; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
7964 g_return_if_fail (data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if (data != ((void*)0)) _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__)), "data != NULL"); return
; } } while (0)
;
7965
7966 icon = g_hash_table_lookup (container->details->icon_set, data);
7967
7968 if (icon != NULL((void*)0))
7969 {
7970 caja_icon_container_update_icon (container, icon);
7971 schedule_redo_layout (container);
7972 }
7973}
7974
7975/* zooming */
7976
7977CajaZoomLevel
7978caja_icon_container_get_zoom_level (CajaIconContainer *container)
7979{
7980 return container->details->zoom_level;
7981}
7982
7983void
7984caja_icon_container_set_zoom_level (CajaIconContainer *container, int new_level)
7985{
7986 CajaIconContainerDetails *details;
7987 int pinned_level;
7988 double pixels_per_unit;
7989
7990 details = container->details;
7991
7992 end_renaming_mode (container, TRUE(!(0)));
7993
7994 pinned_level = new_level;
7995 if (pinned_level < CAJA_ZOOM_LEVEL_SMALLEST)
7996 {
7997 pinned_level = CAJA_ZOOM_LEVEL_SMALLEST;
7998 }
7999 else if (pinned_level > CAJA_ZOOM_LEVEL_LARGEST)
8000 {
8001 pinned_level = CAJA_ZOOM_LEVEL_LARGEST;
8002 }
8003
8004 if (pinned_level == details->zoom_level)
8005 {
8006 return;
8007 }
8008
8009 details->zoom_level = pinned_level;
8010
8011 pixels_per_unit = (double) caja_get_icon_size_for_zoom_level (pinned_level)
8012 / CAJA_ICON_SIZE_STANDARD48;
8013 eel_canvas_set_pixels_per_unit (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), pixels_per_unit);
8014
8015 invalidate_labels (container);
8016 caja_icon_container_request_update_all (container);
8017}
8018
8019/**
8020 * caja_icon_container_request_update_all:
8021 * For each icon, synchronizes the displayed information (image, text) with the
8022 * information from the model.
8023 *
8024 * @container: An icon container.
8025 **/
8026void
8027caja_icon_container_request_update_all (CajaIconContainer *container)
8028{
8029 GList *node;
8030 CajaIcon *icon = NULL((void*)0);
8031
8032 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_182 = 1; else _g_boolean_var_182 =
0; _g_boolean_var_182; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8033
8034 container->details->is_loading = TRUE(!(0));
8035 for (node = container->details->icons; node != NULL((void*)0); node = node->next)
8036 {
8037 icon = node->data;
8038 caja_icon_container_update_icon (container, icon);
8039 }
8040
8041 redo_layout (container);
8042 container->details->is_loading = FALSE(0);
8043}
8044
8045/**
8046 * caja_icon_container_reveal:
8047 * Change scroll position as necessary to reveal the specified item.
8048 */
8049void
8050caja_icon_container_reveal (CajaIconContainer *container, CajaIconData *data)
8051{
8052 CajaIcon *icon;
8053
8054 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_183 = 1; else _g_boolean_var_183 =
0; _g_boolean_var_183; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8055 g_return_if_fail (data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (data != ((void*)0)) _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__)), "data != NULL"); return
; } } while (0)
;
8056
8057 icon = g_hash_table_lookup (container->details->icon_set, data);
8058
8059 if (icon != NULL((void*)0))
8060 {
8061 reveal_icon (container, icon);
8062 }
8063}
8064
8065/**
8066 * caja_icon_container_get_selection:
8067 * @container: An icon container.
8068 *
8069 * Get a list of the icons currently selected in @container.
8070 *
8071 * Return value: A GList of the programmer-specified data associated to each
8072 * selected icon, or NULL if no icon is selected. The caller is expected to
8073 * free the list when it is not needed anymore.
8074 **/
8075GList *
8076caja_icon_container_get_selection (CajaIconContainer *container)
8077{
8078 GList *list, *p;
8079
8080 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_185 = 1; else _g_boolean_var_185 =
0; _g_boolean_var_185; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return (((void*)0)); } } while (0)
;
8081
8082 list = NULL((void*)0);
8083 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8084 {
8085 CajaIcon *icon;
8086
8087 icon = p->data;
8088 if (icon->is_selected)
8089 {
8090 list = g_list_prepend (list, icon->data);
8091 }
8092 }
8093
8094 return g_list_reverse (list);
8095}
8096
8097static GList *
8098caja_icon_container_get_selected_icons (CajaIconContainer *container)
8099{
8100 GList *list, *p;
8101
8102 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return (((void*)0)); } } while (0)
;
8103
8104 list = NULL((void*)0);
8105 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8106 {
8107 CajaIcon *icon;
8108
8109 icon = p->data;
8110 if (icon->is_selected)
8111 {
8112 list = g_list_prepend (list, icon);
8113 }
8114 }
8115
8116 return g_list_reverse (list);
8117}
8118
8119/**
8120 * caja_icon_container_invert_selection:
8121 * @container: An icon container.
8122 *
8123 * Inverts the selection in @container.
8124 *
8125 **/
8126void
8127caja_icon_container_invert_selection (CajaIconContainer *container)
8128{
8129 GList *p;
8130
8131 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8132
8133 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8134 {
8135 CajaIcon *icon;
8136
8137 icon = p->data;
8138 icon_toggle_selected (container, icon);
8139 }
8140
8141 g_signal_emit (container, signals[SELECTION_CHANGED], 0);
8142}
8143
8144
8145/* Returns an array of GdkPoints of locations of the icons. */
8146static GArray *
8147caja_icon_container_get_icon_locations (CajaIconContainer *container,
8148 GList *icons)
8149{
8150 GArray *result;
8151 GList *node;
8152 int index;
8153
8154 result = g_array_new (FALSE(0), TRUE(!(0)), sizeof (GdkPoint));
8155 result = g_array_set_size (result, g_list_length (icons));
8156
8157 for (index = 0, node = icons; node != NULL((void*)0); index++, node = node->next)
8158 {
8159 g_array_index (result, GdkPoint, index)(((GdkPoint*) (void *) (result)->data) [(index)]).x =
8160 ((CajaIcon *)node->data)->x;
8161 g_array_index (result, GdkPoint, index)(((GdkPoint*) (void *) (result)->data) [(index)]).y =
8162 ((CajaIcon *)node->data)->y;
8163 }
8164
8165 return result;
8166}
8167
8168/**
8169 * caja_icon_container_get_selected_icon_locations:
8170 * @container: An icon container widget.
8171 *
8172 * Returns an array of GdkPoints of locations of the selected icons.
8173 **/
8174GArray *
8175caja_icon_container_get_selected_icon_locations (CajaIconContainer *container)
8176{
8177 GArray *result;
8178 GList *icons;
8179
8180 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return (((void*)0)); } } while (0)
;
8181
8182 icons = caja_icon_container_get_selected_icons (container);
8183 result = caja_icon_container_get_icon_locations (container, icons);
8184 g_list_free (icons);
8185
8186 return result;
8187}
8188
8189/**
8190 * caja_icon_container_select_all:
8191 * @container: An icon container widget.
8192 *
8193 * Select all the icons in @container at once.
8194 **/
8195void
8196caja_icon_container_select_all (CajaIconContainer *container)
8197{
8198 gboolean selection_changed;
8199 GList *p;
8200 CajaIcon *icon = NULL((void*)0);
8201
8202 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_189 = 1; else _g_boolean_var_189 =
0; _g_boolean_var_189; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8203
8204 selection_changed = FALSE(0);
8205
8206 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8207 {
8208 icon = p->data;
8209
8210 selection_changed |= icon_set_selected (container, icon, TRUE(!(0)));
8211 }
8212
8213 if (selection_changed)
8214 {
8215 g_signal_emit (container,
8216 signals[SELECTION_CHANGED], 0);
8217 }
8218}
8219
8220/**
8221 * caja_icon_container_set_selection:
8222 * @container: An icon container widget.
8223 * @selection: A list of CajaIconData *.
8224 *
8225 * Set the selection to exactly the icons in @container which have
8226 * programmer data matching one of the items in @selection.
8227 **/
8228void
8229caja_icon_container_set_selection (CajaIconContainer *container,
8230 GList *selection)
8231{
8232 gboolean selection_changed;
8233 GHashTable *hash;
8234 GList *p;
8235 CajaIcon *icon = NULL((void*)0);
8236
8237 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8238
8239 selection_changed = FALSE(0);
8240
8241 hash = g_hash_table_new (NULL((void*)0), NULL((void*)0));
8242 for (p = selection; p != NULL((void*)0); p = p->next)
8243 {
8244 g_hash_table_insert (hash, p->data, p->data);
8245 }
8246 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8247 {
8248 icon = p->data;
8249
8250 selection_changed |= icon_set_selected
8251 (container, icon,
8252 g_hash_table_lookup (hash, icon->data) != NULL((void*)0));
8253 }
8254 g_hash_table_destroy (hash);
8255
8256 if (selection_changed)
8257 {
8258 g_signal_emit (container,
8259 signals[SELECTION_CHANGED], 0);
8260 }
8261}
8262
8263/**
8264 * caja_icon_container_select_list_unselect_others.
8265 * @container: An icon container widget.
8266 * @selection: A list of CajaIcon *.
8267 *
8268 * Set the selection to exactly the icons in @selection.
8269 **/
8270void
8271caja_icon_container_select_list_unselect_others (CajaIconContainer *container,
8272 GList *selection)
8273{
8274 gboolean selection_changed;
8275 GHashTable *hash;
8276 GList *p;
8277 CajaIcon *icon = NULL((void*)0);
8278
8279 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_191 = 1; else _g_boolean_var_191 =
0; _g_boolean_var_191; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8280
8281 selection_changed = FALSE(0);
8282
8283 hash = g_hash_table_new (NULL((void*)0), NULL((void*)0));
8284 for (p = selection; p != NULL((void*)0); p = p->next)
8285 {
8286 g_hash_table_insert (hash, p->data, p->data);
8287 }
8288 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8289 {
8290 icon = p->data;
8291
8292 selection_changed |= icon_set_selected
8293 (container, icon,
8294 g_hash_table_lookup (hash, icon) != NULL((void*)0));
8295 }
8296 g_hash_table_destroy (hash);
8297
8298 if (selection_changed)
8299 {
8300 g_signal_emit (container,
8301 signals[SELECTION_CHANGED], 0);
8302 }
8303}
8304
8305/**
8306 * caja_icon_container_unselect_all:
8307 * @container: An icon container widget.
8308 *
8309 * Deselect all the icons in @container.
8310 **/
8311void
8312caja_icon_container_unselect_all (CajaIconContainer *container)
8313{
8314 if (unselect_all (container))
8315 {
8316 g_signal_emit (container,
8317 signals[SELECTION_CHANGED], 0);
8318 }
8319}
8320
8321/**
8322 * caja_icon_container_get_icon_by_uri:
8323 * @container: An icon container widget.
8324 * @uri: The uri of an icon to find.
8325 *
8326 * Locate an icon, given the URI. The URI must match exactly.
8327 * Later we may have to have some way of figuring out if the
8328 * URI specifies the same object that does not require an exact match.
8329 **/
8330CajaIcon *
8331caja_icon_container_get_icon_by_uri (CajaIconContainer *container,
8332 const char *uri)
8333{
8334 CajaIconContainerDetails *details;
8335 GList *p;
8336
8337 /* Eventually, we must avoid searching the entire icon list,
8338 but it's OK for now.
8339 A hash table mapping uri to icon is one possibility.
8340 */
8341
8342 details = container->details;
8343
8344 for (p = details->icons; p != NULL((void*)0); p = p->next)
8345 {
8346 CajaIcon *icon;
8347 char *icon_uri;
8348 gboolean is_match;
8349
8350 icon = p->data;
8351
8352 icon_uri = caja_icon_container_get_icon_uri
8353 (container, icon);
8354 is_match = strcmp (uri, icon_uri) == 0;
8355 g_free (icon_uri);
8356
8357 if (is_match)
8358 {
8359 return icon;
8360 }
8361 }
8362
8363 return NULL((void*)0);
8364}
8365
8366static CajaIcon *
8367get_nth_selected_icon (CajaIconContainer *container, int index)
8368{
8369 GList *p;
8370 int selection_count;
8371 CajaIcon *icon = NULL((void*)0);
8372
8373 g_assert (index > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if (index > 0) _g_boolean_var_192 = 1; else _g_boolean_var_192
= 0; _g_boolean_var_192; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 8373, ((const char*)
(__func__)), "index > 0"); } while (0)
;
8374
8375 /* Find the nth selected icon. */
8376 selection_count = 0;
8377 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8378 {
8379 icon = p->data;
8380 if (icon->is_selected)
8381 {
8382 if (++selection_count == index)
8383 {
8384 return icon;
8385 }
8386 }
8387 }
8388 return NULL((void*)0);
8389}
8390
8391static CajaIcon *
8392get_first_selected_icon (CajaIconContainer *container)
8393{
8394 return get_nth_selected_icon (container, 1);
8395}
8396
8397static gboolean
8398has_multiple_selection (CajaIconContainer *container)
8399{
8400 return get_nth_selected_icon (container, 2) != NULL((void*)0);
8401}
8402
8403static gboolean
8404all_selected (CajaIconContainer *container)
8405{
8406 GList *p;
8407 CajaIcon *icon = NULL((void*)0);
8408
8409 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8410 {
8411 icon = p->data;
8412 if (!icon->is_selected)
8413 {
8414 return FALSE(0);
8415 }
8416 }
8417 return TRUE(!(0));
8418}
8419
8420static gboolean
8421has_selection (CajaIconContainer *container)
8422{
8423 return get_nth_selected_icon (container, 1) != NULL((void*)0);
8424}
8425
8426/**
8427 * caja_icon_container_show_stretch_handles:
8428 * @container: An icon container widget.
8429 *
8430 * Makes stretch handles visible on the first selected icon.
8431 **/
8432void
8433caja_icon_container_show_stretch_handles (CajaIconContainer *container)
8434{
8435 CajaIconContainerDetails *details;
8436 CajaIcon *icon;
8437 guint initial_size;
8438
8439 icon = get_first_selected_icon (container);
8440 if (icon == NULL((void*)0))
8441 {
8442 return;
8443 }
8444
8445 /* Check if it already has stretch handles. */
8446 details = container->details;
8447 if (details->stretch_icon == icon)
8448 {
8449 return;
8450 }
8451
8452 /* Get rid of the existing stretch handles and put them on the new icon. */
8453 if (details->stretch_icon != NULL((void*)0))
8454 {
8455 caja_icon_canvas_item_set_show_stretch_handles
8456 (details->stretch_icon->item, FALSE(0));
8457 ungrab_stretch_icon (container);
8458 emit_stretch_ended (container, details->stretch_icon);
8459 }
8460 caja_icon_canvas_item_set_show_stretch_handles (icon->item, TRUE(!(0)));
8461 details->stretch_icon = icon;
8462
8463 icon_get_size (container, icon, &initial_size);
8464
8465 /* only need to keep size in one dimension, since they are constrained to be the same */
8466 container->details->stretch_initial_x = icon->x;
8467 container->details->stretch_initial_y = icon->y;
8468 container->details->stretch_initial_size = initial_size;
8469
8470 emit_stretch_started (container, icon);
8471}
8472
8473/**
8474 * caja_icon_container_has_stretch_handles
8475 * @container: An icon container widget.
8476 *
8477 * Returns true if the first selected item has stretch handles.
8478 **/
8479gboolean
8480caja_icon_container_has_stretch_handles (CajaIconContainer *container)
8481{
8482 CajaIcon *icon;
8483
8484 icon = get_first_selected_icon (container);
8485 if (icon == NULL((void*)0))
8486 {
8487 return FALSE(0);
8488 }
8489
8490 return icon == container->details->stretch_icon;
8491}
8492
8493/**
8494 * caja_icon_container_is_stretched
8495 * @container: An icon container widget.
8496 *
8497 * Returns true if the any selected item is stretched to a size other than 1.0.
8498 **/
8499gboolean
8500caja_icon_container_is_stretched (CajaIconContainer *container)
8501{
8502 GList *p;
8503 CajaIcon *icon = NULL((void*)0);
8504
8505 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8506 {
8507 icon = p->data;
8508 if (icon->is_selected && icon->scale != 1.0)
8509 {
8510 return TRUE(!(0));
8511 }
8512 }
8513 return FALSE(0);
8514}
8515
8516/**
8517 * caja_icon_container_unstretch
8518 * @container: An icon container widget.
8519 *
8520 * Gets rid of any icon stretching.
8521 **/
8522void
8523caja_icon_container_unstretch (CajaIconContainer *container)
8524{
8525 GList *p;
8526 CajaIcon *icon = NULL((void*)0);
8527
8528 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8529 {
8530 icon = p->data;
8531 if (icon->is_selected)
8532 {
8533 caja_icon_container_move_icon (container, icon,
8534 icon->x, icon->y,
8535 1.0,
8536 FALSE(0), TRUE(!(0)), TRUE(!(0)));
8537 }
8538 }
8539}
8540
8541static void
8542compute_stretch (StretchState *start,
8543 StretchState *current)
8544{
8545 gboolean right, bottom;
8546 int x_stretch, y_stretch;
8547
8548 /* FIXME bugzilla.gnome.org 45390: This doesn't correspond to
8549 * the way the handles are drawn.
8550 */
8551 /* Figure out which handle we are dragging. */
8552 right = start->pointer_x > start->icon_x + (int) start->icon_size / 2;
8553 bottom = start->pointer_y > start->icon_y + (int) start->icon_size / 2;
8554
8555 /* Figure out how big we should stretch. */
8556 x_stretch = start->pointer_x - current->pointer_x;
8557 y_stretch = start->pointer_y - current->pointer_y;
8558 if (right)
8559 {
8560 x_stretch = - x_stretch;
8561 }
8562 if (bottom)
8563 {
8564 y_stretch = - y_stretch;
8565 }
8566 current->icon_size = MAX ((int) start->icon_size + MIN (x_stretch, y_stretch),((((int) start->icon_size + (((x_stretch) < (y_stretch)
) ? (x_stretch) : (y_stretch))) > ((int) 16)) ? ((int) start
->icon_size + (((x_stretch) < (y_stretch)) ? (x_stretch
) : (y_stretch))) : ((int) 16))
8567 (int) CAJA_ICON_SIZE_SMALLEST)((((int) start->icon_size + (((x_stretch) < (y_stretch)
) ? (x_stretch) : (y_stretch))) > ((int) 16)) ? ((int) start
->icon_size + (((x_stretch) < (y_stretch)) ? (x_stretch
) : (y_stretch))) : ((int) 16))
;
8568
8569 /* Figure out where the corner of the icon should be. */
8570 current->icon_x = start->icon_x;
8571 if (!right)
8572 {
8573 current->icon_x += start->icon_size - current->icon_size;
8574 }
8575 current->icon_y = start->icon_y;
8576 if (!bottom)
8577 {
8578 current->icon_y += start->icon_size - current->icon_size;
8579 }
8580}
8581
8582char *
8583caja_icon_container_get_icon_uri (CajaIconContainer *container,
8584 CajaIcon *icon)
8585{
8586 char *uri;
8587
8588 uri = NULL((void*)0);
8589 g_signal_emit (container,
8590 signals[GET_ICON_URI], 0,
8591 icon->data,
8592 &uri);
8593 return uri;
8594}
8595
8596char *
8597caja_icon_container_get_icon_drop_target_uri (CajaIconContainer *container,
8598 CajaIcon *icon)
8599{
8600 char *uri;
8601
8602 uri = NULL((void*)0);
8603 g_signal_emit (container,
8604 signals[GET_ICON_DROP_TARGET_URI], 0,
8605 icon->data,
8606 &uri);
8607 return uri;
8608}
8609
8610/* Call to reset the scroll region only if the container is not empty,
8611 * to avoid having the flag linger until the next file is added.
8612 */
8613static void
8614reset_scroll_region_if_not_empty (CajaIconContainer *container)
8615{
8616 if (!caja_icon_container_is_empty (container))
8617 {
8618 caja_icon_container_reset_scroll_region (container);
8619 }
8620}
8621
8622/* Switch from automatic layout to manual or vice versa.
8623 * If we switch to manual layout, we restore the icon positions from the
8624 * last manual layout.
8625 */
8626void
8627caja_icon_container_set_auto_layout (CajaIconContainer *container,
8628 gboolean auto_layout)
8629{
8630 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_193 = 1; else _g_boolean_var_193 =
0; _g_boolean_var_193; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8631 g_return_if_fail (auto_layout == FALSE || auto_layout == TRUE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (auto_layout == (0) || auto_layout == (!(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__)), "auto_layout == FALSE || auto_layout == TRUE"
); return; } } while (0)
;
8632
8633 if (container->details->auto_layout == auto_layout)
8634 {
8635 return;
8636 }
8637
8638 reset_scroll_region_if_not_empty (container);
8639 container->details->auto_layout = auto_layout;
8640
8641 if (!auto_layout)
8642 {
8643 reload_icon_positions (container);
8644 caja_icon_container_freeze_icon_positions (container);
8645 }
8646
8647 redo_layout (container);
8648
8649 g_signal_emit (container, signals[LAYOUT_CHANGED], 0);
8650}
8651
8652
8653/* Toggle the tighter layout boolean. */
8654void
8655caja_icon_container_set_tighter_layout (CajaIconContainer *container,
8656 gboolean tighter_layout)
8657{
8658 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8659 g_return_if_fail (tighter_layout == FALSE || tighter_layout == TRUE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if (tighter_layout == (0) || tighter_layout == (!(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__)), "tighter_layout == FALSE || tighter_layout == TRUE"
); return; } } while (0)
;
8660
8661 if (container->details->tighter_layout == tighter_layout)
8662 {
8663 return;
8664 }
8665
8666 container->details->tighter_layout = tighter_layout;
8667
8668 if (container->details->auto_layout)
8669 {
8670 invalidate_label_sizes (container);
8671 redo_layout (container);
8672
8673 g_signal_emit (container, signals[LAYOUT_CHANGED], 0);
8674 }
8675 else
8676 {
8677 /* in manual layout, label sizes still change, even though
8678 * the icons don't move.
8679 */
8680 invalidate_label_sizes (container);
8681 caja_icon_container_request_update_all (container);
8682 }
8683}
8684
8685gboolean
8686caja_icon_container_is_keep_aligned (CajaIconContainer *container)
8687{
8688 return container->details->keep_aligned;
8689}
8690
8691gboolean
8692caja_icon_container_is_lock_icons_position (CajaIconContainer *container)
8693{
8694 return container->details->lock_icons_position;
8695}
8696
8697static gboolean
8698align_icons_callback (gpointer callback_data)
8699{
8700 CajaIconContainer *container;
8701
8702 container = CAJA_ICON_CONTAINER (callback_data)((((CajaIconContainer*) (void *) ((callback_data)))));
8703 align_icons (container);
8704 container->details->align_idle_id = 0;
8705
8706 return FALSE(0);
8707}
8708
8709static void
8710unschedule_align_icons (CajaIconContainer *container)
8711{
8712 if (container->details->align_idle_id != 0)
8713 {
8714 g_source_remove (container->details->align_idle_id);
8715 container->details->align_idle_id = 0;
8716 }
8717}
8718
8719static void
8720schedule_align_icons (CajaIconContainer *container)
8721{
8722 if (container->details->align_idle_id == 0
8723 && container->details->has_been_allocated)
8724 {
8725 container->details->align_idle_id = g_idle_add
8726 (align_icons_callback, container);
8727 }
8728}
8729
8730void
8731caja_icon_container_set_keep_aligned (CajaIconContainer *container,
8732 gboolean keep_aligned)
8733{
8734 if (container->details->keep_aligned != keep_aligned)
8735 {
8736 container->details->keep_aligned = keep_aligned;
8737
8738 if (keep_aligned && !container->details->auto_layout)
8739 {
8740 schedule_align_icons (container);
8741 }
8742 else
8743 {
8744 unschedule_align_icons (container);
8745 }
8746 }
8747}
8748
8749void
8750caja_icon_container_set_lock_icons_position (CajaIconContainer *container,
8751 gboolean lock_icons_position)
8752{
8753 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_197 = 1; else _g_boolean_var_197 =
0; _g_boolean_var_197; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8754
8755 container->details->lock_icons_position = lock_icons_position;
8756}
8757
8758void
8759caja_icon_container_set_layout_mode (CajaIconContainer *container,
8760 CajaIconLayoutMode mode)
8761{
8762 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8763
8764 container->details->layout_mode = mode;
8765 invalidate_labels (container);
8766
8767 redo_layout (container);
8768
8769 g_signal_emit (container, signals[LAYOUT_CHANGED], 0);
8770}
8771
8772void
8773caja_icon_container_set_label_position (CajaIconContainer *container,
8774 CajaIconLabelPosition position)
8775{
8776 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_199 = 1; else _g_boolean_var_199 =
0; _g_boolean_var_199; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
8777
8778 if (container->details->label_position != position)
8779 {
8780 container->details->label_position = position;
8781
8782 invalidate_labels (container);
8783 caja_icon_container_request_update_all (container);
8784
8785 schedule_redo_layout (container);
8786 }
8787}
8788
8789/* Switch from automatic to manual layout, freezing all the icons in their
8790 * current positions instead of restoring icon positions from the last manual
8791 * layout as set_auto_layout does.
8792 */
8793void
8794caja_icon_container_freeze_icon_positions (CajaIconContainer *container)
8795{
8796 gboolean changed;
8797 GList *p;
8798 CajaIcon *icon;
8799 CajaIconPosition position;
8800
8801 changed = container->details->auto_layout;
8802 container->details->auto_layout = FALSE(0);
8803
8804 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
8805 {
8806 icon = p->data;
8807
8808 position.x = icon->saved_ltr_x;
8809 position.y = icon->y;
8810 position.scale = icon->scale;
8811 g_signal_emit (container, signals[ICON_POSITION_CHANGED], 0,
8812 icon->data, &position);
8813 }
8814
8815 if (changed)
8816 {
8817 g_signal_emit (container, signals[LAYOUT_CHANGED], 0);
8818 }
8819}
8820
8821/* Re-sort, switching to automatic layout if it was in manual layout. */
8822void
8823caja_icon_container_sort (CajaIconContainer *container)
8824{
8825 gboolean changed;
8826
8827 changed = !container->details->auto_layout;
8828 container->details->auto_layout = TRUE(!(0));
8829
8830 reset_scroll_region_if_not_empty (container);
8831 redo_layout (container);
8832
8833 if (changed)
8834 {
8835 g_signal_emit (container, signals[LAYOUT_CHANGED], 0);
8836 }
8837}
8838
8839gboolean
8840caja_icon_container_is_auto_layout (CajaIconContainer *container)
8841{
8842 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_200 = 1; else _g_boolean_var_200 =
0; _g_boolean_var_200; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
8843
8844 return container->details->auto_layout;
8845}
8846
8847gboolean
8848caja_icon_container_is_tighter_layout (CajaIconContainer *container)
8849{
8850 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
8851
8852 return container->details->tighter_layout;
8853}
8854
8855static void
8856pending_icon_to_rename_destroy_callback (CajaIconCanvasItem *item, CajaIconContainer *container)
8857{
8858 g_assert (container->details->pending_icon_to_rename != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (container->details->pending_icon_to_rename != ((void
*)0)) _g_boolean_var_202 = 1; else _g_boolean_var_202 = 0; _g_boolean_var_202
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 8858, ((const char*) (__func__)), "container->details->pending_icon_to_rename != NULL"
); } while (0)
;
8859 g_assert (container->details->pending_icon_to_rename->item == item)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if (container->details->pending_icon_to_rename->item
== item) _g_boolean_var_203 = 1; else _g_boolean_var_203 = 0
; _g_boolean_var_203; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 8859, ((const char*)
(__func__)), "container->details->pending_icon_to_rename->item == item"
); } while (0)
;
8860 container->details->pending_icon_to_rename = NULL((void*)0);
8861}
8862
8863static CajaIcon*
8864get_pending_icon_to_rename (CajaIconContainer *container)
8865{
8866 return container->details->pending_icon_to_rename;
8867}
8868
8869static void
8870set_pending_icon_to_rename (CajaIconContainer *container, CajaIcon *icon)
8871{
8872 CajaIcon *old_icon;
8873
8874 old_icon = container->details->pending_icon_to_rename;
8875
8876 if (icon == old_icon)
8877 {
8878 return;
8879 }
8880
8881 if (old_icon != NULL((void*)0))
8882 {
8883 g_signal_handlers_disconnect_by_funcg_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_rename_destroy_callback)))
, (container))
8884 (old_icon->item,g_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_rename_destroy_callback)))
, (container))
8885 G_CALLBACK (pending_icon_to_rename_destroy_callback),g_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_rename_destroy_callback)))
, (container))
8886 container)g_signal_handlers_disconnect_matched ((old_icon->item), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (pending_icon_to_rename_destroy_callback)))
, (container))
;
8887 }
8888
8889 if (icon != NULL((void*)0))
8890 {
8891 g_signal_connect (icon->item, "destroy",g_signal_connect_data ((icon->item), ("destroy"), (((GCallback
) (pending_icon_to_rename_destroy_callback))), (container), (
(void*)0), (GConnectFlags) 0)
8892 G_CALLBACK (pending_icon_to_rename_destroy_callback), container)g_signal_connect_data ((icon->item), ("destroy"), (((GCallback
) (pending_icon_to_rename_destroy_callback))), (container), (
(void*)0), (GConnectFlags) 0)
;
8893 }
8894
8895 container->details->pending_icon_to_rename = icon;
8896}
8897
8898static void
8899process_pending_icon_to_rename (CajaIconContainer *container)
8900{
8901 CajaIcon *pending_icon_to_rename;
8902
8903 pending_icon_to_rename = get_pending_icon_to_rename (container);
8904
8905 if (pending_icon_to_rename != NULL((void*)0))
8906 {
8907 if (pending_icon_to_rename->is_selected && !has_multiple_selection (container))
8908 {
8909 caja_icon_container_start_renaming_selected_item (container, FALSE(0));
8910 }
8911 else
8912 {
8913 set_pending_icon_to_rename (container, NULL((void*)0));
8914 }
8915 }
8916}
8917
8918static gboolean
8919is_renaming_pending (CajaIconContainer *container)
8920{
8921 return get_pending_icon_to_rename (container) != NULL((void*)0);
8922}
8923
8924static gboolean
8925is_renaming (CajaIconContainer *container)
8926{
8927 return container->details->renaming;
8928}
8929
8930/**
8931 * caja_icon_container_start_renaming_selected_item
8932 * @container: An icon container widget.
8933 * @select_all: Whether the whole file should initially be selected, or
8934 * only its basename (i.e. everything except its extension).
8935 *
8936 * Displays the edit name widget on the first selected icon
8937 **/
8938void
8939caja_icon_container_start_renaming_selected_item (CajaIconContainer *container,
8940 gboolean select_all)
8941{
8942 CajaIconContainerDetails *details;
8943 CajaIcon *icon;
8944 EelDRect icon_rect;
8945 EelDRect text_rect;
8946 PangoFontDescription *desc;
8947 const char *editable_text;
8948 int x, y, width;
8949 int start_offset, end_offset;
8950
8951 /* Check if it already in renaming mode, if so - select all */
8952 details = container->details;
8953 if (details->renaming)
8954 {
8955 eel_editable_label_select_region (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
,
8956 0,
8957 -1);
8958 return;
8959 }
8960
8961 /* Find selected icon */
8962 icon = get_first_selected_icon (container);
8963 if (icon == NULL((void*)0))
8964 {
8965 return;
8966 }
8967
8968 g_assert (!has_multiple_selection (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if (!has_multiple_selection (container)) _g_boolean_var_204
= 1; else _g_boolean_var_204 = 0; _g_boolean_var_204; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-icon-container.c"
, 8968, ((const char*) (__func__)), "!has_multiple_selection (container)"
); } while (0)
;
8969
8970
8971 if (!icon_is_positioned (icon))
8972 {
8973 set_pending_icon_to_rename (container, icon);
8974 return;
8975 }
8976
8977 set_pending_icon_to_rename (container, NULL((void*)0));
8978
8979 /* Make a copy of the original editable text for a later compare */
8980 editable_text = caja_icon_canvas_item_get_editable_text (icon->item);
8981
8982 /* This could conceivably be NULL if a rename was triggered really early. */
8983 if (editable_text == NULL((void*)0))
8984 {
8985 return;
8986 }
8987
8988 details->original_text = g_strdup (editable_text)g_strdup_inline (editable_text);
8989
8990 /* Freeze updates so files added while renaming don't cause rename to loose focus, bug #318373 */
8991 caja_icon_container_freeze_updates (container);
8992
8993 /* Create text renaming widget, if it hasn't been created already.
8994 * We deal with the broken icon text item widget by keeping it around
8995 * so its contents can still be cut and pasted as part of the clipboard
8996 */
8997 if (details->rename_widget == NULL((void*)0))
8998 {
8999 details->rename_widget = eel_editable_label_new ("Test text");
9000 eel_editable_label_set_line_wrap (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
, TRUE(!(0)));
9001 eel_editable_label_set_line_wrap_mode (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
, PANGO_WRAP_WORD_CHAR);
9002 eel_editable_label_set_draw_outline (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
, TRUE(!(0)));
9003
9004 if (details->label_position != CAJA_ICON_LABEL_POSITION_BESIDE)
9005 {
9006 eel_editable_label_set_justify (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
, GTK_JUSTIFY_CENTER);
9007 }
9008
9009 gtk_widget_set_margin_start (details->rename_widget, 1);
9010 gtk_widget_set_margin_end (details->rename_widget, 1);
9011 gtk_widget_set_margin_top (details->rename_widget, 1);
9012 gtk_widget_set_margin_bottom (details->rename_widget, 1);
9013 gtk_layout_put (GTK_LAYOUT (container)((((GtkLayout*) (void *) ((container))))),
9014 details->rename_widget, 0, 0);
9015 }
9016
9017 /* Set the right font */
9018 if (details->font)
9019 {
9020 desc = pango_font_description_from_string (details->font);
9021 }
9022 else
9023 {
9024 PangoContext *context;
9025
9026 context = gtk_widget_get_pango_context (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
9027 desc = pango_font_description_copy (pango_context_get_font_description (context));
9028 pango_font_description_set_size (desc,
9029 pango_font_description_get_size (desc) +
9030 container->details->font_size_table [container->details->zoom_level]);
9031 }
9032 eel_editable_label_set_font_description (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
,
9033 desc);
9034 pango_font_description_free (desc);
9035
9036 icon_rect = caja_icon_canvas_item_get_icon_rectangle (icon->item);
9037 text_rect = caja_icon_canvas_item_get_text_rectangle (icon->item, TRUE(!(0)));
9038
9039 if (caja_icon_container_is_layout_vertical (container) &&
9040 container->details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
9041 {
9042 /* for one-line editables, the width changes dynamically */
9043 width = -1;
9044 }
9045 else
9046 {
9047 width = caja_icon_canvas_item_get_max_text_width (icon->item);
9048 }
9049
9050 if (details->label_position == CAJA_ICON_LABEL_POSITION_BESIDE)
9051 {
9052 eel_canvas_w2c (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))))->canvas,
9053 text_rect.x0,
9054 text_rect.y0,
9055 &x, &y);
9056 }
9057 else
9058 {
9059 eel_canvas_w2c (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item)))))->canvas,
9060 (icon_rect.x0 + icon_rect.x1) / 2,
9061 icon_rect.y1,
9062 &x, &y);
9063 x = x - width / 2 - 1;
9064 }
9065
9066 gtk_layout_move (GTK_LAYOUT (container)((((GtkLayout*) (void *) ((container))))),
9067 details->rename_widget,
9068 x, y);
9069
9070 gtk_widget_set_size_request (details->rename_widget,
9071 width, -1);
9072 eel_editable_label_set_text (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
,
9073 editable_text);
9074 if (select_all)
9075 {
9076 start_offset = 0;
9077 end_offset = -1;
9078 }
9079 else
9080 {
9081 eel_filename_get_rename_region (editable_text, &start_offset, &end_offset);
9082 }
9083 gtk_widget_show (details->rename_widget);
9084 gtk_widget_grab_focus (details->rename_widget);
9085
9086 eel_editable_label_select_region (EEL_EDITABLE_LABEL (details->rename_widget)((((EelEditableLabel*) (void *) ((details->rename_widget))
)))
,
9087 start_offset,
9088 end_offset);
9089 g_signal_emit (container,
9090 signals[RENAMING_ICON], 0,
9091 GTK_EDITABLE (details->rename_widget)((((GtkEditable*) (void *) ((details->rename_widget))))));
9092
9093 caja_icon_container_update_icon (container, icon);
9094
9095 /* We are in renaming mode */
9096 details->renaming = TRUE(!(0));
9097 caja_icon_canvas_item_set_renaming (icon->item, TRUE(!(0)));
9098}
9099
9100static void
9101end_renaming_mode (CajaIconContainer *container, gboolean commit)
9102{
9103 CajaIcon *icon;
9104
9105 set_pending_icon_to_rename (container, NULL((void*)0));
9106
9107 icon = get_icon_being_renamed (container);
9108 if (icon == NULL((void*)0))
9109 {
9110 return;
9111 }
9112
9113 /* We are not in renaming mode */
9114 container->details->renaming = FALSE(0);
9115 caja_icon_canvas_item_set_renaming (icon->item, FALSE(0));
9116
9117 caja_icon_container_unfreeze_updates (container);
9118
9119 if (commit)
9120 {
9121 set_pending_icon_to_reveal (container, icon);
9122 }
9123
9124 gtk_widget_grab_focus (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
9125
9126 if (commit)
9127 {
9128 const char *changed_text;
9129
9130 /* Verify that text has been modified before signalling change. */
9131 changed_text = eel_editable_label_get_text (EEL_EDITABLE_LABEL (container->details->rename_widget)((((EelEditableLabel*) (void *) ((container->details->rename_widget
)))))
);
9132 if (strcmp (container->details->original_text, changed_text) != 0)
9133 {
9134 AtkObject *accessible_icon;
9135
9136 g_signal_emit (container,
9137 signals[ICON_TEXT_CHANGED], 0,
9138 icon->data,
9139 changed_text);
9140
9141 accessible_icon = atk_gobject_accessible_for_object (G_OBJECT(icon->item)((((GObject*) (void *) ((icon->item))))));
9142 g_object_notify (G_OBJECT(accessible_icon)((((GObject*) (void *) ((accessible_icon))))), "accessible-name");
9143 }
9144 }
9145
9146 gtk_widget_hide (container->details->rename_widget);
9147
9148 g_free (container->details->original_text);
9149
9150}
9151
9152/* emit preview signal, called by the canvas item */
9153gboolean
9154caja_icon_container_emit_preview_signal (CajaIconContainer *icon_container,
9155 CajaIcon *icon,
9156 gboolean start_flag)
9157{
9158 gboolean result;
9159
9160 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (icon_container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((icon_container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (icon_container)"
); return ((0)); } } while (0)
;
9161 g_return_val_if_fail (icon != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (icon != ((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__)), "icon != NULL"); return
((0)); } } while (0)
;
9162 g_return_val_if_fail (start_flag == FALSE || start_flag == TRUE, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if (start_flag == (0) || start_flag == (!(0))) _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__)), "start_flag == FALSE || start_flag == TRUE"
); return ((0)); } } while (0)
;
9163
9164 result = FALSE(0);
9165 g_signal_emit (icon_container,
9166 signals[PREVIEW], 0,
9167 icon->data,
9168 start_flag,
9169 &result);
9170
9171 return result;
9172}
9173
9174gboolean
9175caja_icon_container_has_stored_icon_positions (CajaIconContainer *container)
9176{
9177 GList *p;
9178 gboolean have_stored_position;
9179 CajaIconPosition position;
9180 CajaIcon *icon = NULL((void*)0);
9181
9182 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
9183 {
9184 icon = p->data;
9185
9186 have_stored_position = FALSE(0);
9187 g_signal_emit (container,
9188 signals[GET_STORED_ICON_POSITION], 0,
9189 icon->data,
9190 &position,
9191 &have_stored_position);
9192 if (have_stored_position)
9193 {
9194 return TRUE(!(0));
9195 }
9196 }
9197 return FALSE(0);
9198}
9199
9200void
9201caja_icon_container_set_single_click_mode (CajaIconContainer *container,
9202 gboolean single_click_mode)
9203{
9204 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_208 = 1; else _g_boolean_var_208 =
0; _g_boolean_var_208; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9205
9206 container->details->single_click_mode = single_click_mode;
9207}
9208
9209/* Return if the icon container is a fixed size */
9210gboolean
9211caja_icon_container_get_is_fixed_size (CajaIconContainer *container)
9212{
9213 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
9214
9215 return container->details->is_fixed_size;
9216}
9217
9218/* Set the icon container to be a fixed size */
9219void
9220caja_icon_container_set_is_fixed_size (CajaIconContainer *container,
9221 gboolean is_fixed_size)
9222{
9223 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_210 = 1; else _g_boolean_var_210 =
0; _g_boolean_var_210; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9224
9225 container->details->is_fixed_size = is_fixed_size;
9226}
9227
9228gboolean
9229caja_icon_container_get_is_desktop (CajaIconContainer *container)
9230{
9231 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_211 = 1; else _g_boolean_var_211 =
0; _g_boolean_var_211; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
9232
9233 return container->details->is_desktop;
9234}
9235
9236void
9237caja_icon_container_set_is_desktop (CajaIconContainer *container,
9238 gboolean is_desktop)
9239{
9240 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_212 = 1; else _g_boolean_var_212 =
0; _g_boolean_var_212; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9241
9242 container->details->is_desktop = is_desktop;
9243
9244 if (is_desktop) {
9245 GtkStyleContext *context;
9246
9247 context = gtk_widget_get_style_context (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
9248 gtk_style_context_add_class (context, "caja-desktop");
9249 }
9250}
9251
9252void
9253caja_icon_container_set_margins (CajaIconContainer *container,
9254 int left_margin,
9255 int right_margin,
9256 int top_margin,
9257 int bottom_margin)
9258{
9259 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9260
9261 container->details->left_margin = left_margin;
9262 container->details->right_margin = right_margin;
9263 container->details->top_margin = top_margin;
9264 container->details->bottom_margin = bottom_margin;
9265
9266 /* redo layout of icons as the margins have changed */
9267 schedule_redo_layout (container);
9268}
9269
9270void
9271caja_icon_container_set_use_drop_shadows (CajaIconContainer *container,
9272 gboolean use_drop_shadows)
9273{
9274 if (container->details->drop_shadows_requested == use_drop_shadows)
9275 {
9276 return;
9277 }
9278
9279 container->details->drop_shadows_requested = use_drop_shadows;
9280 container->details->use_drop_shadows = use_drop_shadows;
9281
9282 gtk_widget_queue_draw (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
9283}
9284
9285/* handle theme changes */
9286
9287void
9288caja_icon_container_set_font (CajaIconContainer *container,
9289 const char *font)
9290{
9291 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_214 = 1; else _g_boolean_var_214 =
0; _g_boolean_var_214; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9292
9293 if (g_strcmp0 (container->details->font, font) == 0)
9294 {
9295 return;
9296 }
9297
9298 g_free (container->details->font);
9299 container->details->font = g_strdup (font)g_strdup_inline (font);
9300
9301 invalidate_labels (container);
9302 caja_icon_container_request_update_all (container);
9303 gtk_widget_queue_draw (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
9304}
9305
9306void
9307caja_icon_container_set_font_size_table (CajaIconContainer *container,
9308 const int font_size_table[CAJA_ZOOM_LEVEL_LARGEST + 1])
9309{
9310 int old_font_size;
9311 int i;
9312
9313 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9314 g_return_if_fail (font_size_table != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if (font_size_table != ((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__
)), "font_size_table != NULL"); return; } } while (0)
;
9315
9316 old_font_size = container->details->font_size_table[container->details->zoom_level];
9317
9318 for (i = 0; i <= CAJA_ZOOM_LEVEL_LARGEST; i++)
9319 {
9320 if (container->details->font_size_table[i] != font_size_table[i])
9321 {
9322 container->details->font_size_table[i] = font_size_table[i];
9323 }
9324 }
9325
9326 if (old_font_size != container->details->font_size_table[container->details->zoom_level])
9327 {
9328 invalidate_labels (container);
9329 caja_icon_container_request_update_all (container);
9330 }
9331}
9332
9333/**
9334 * caja_icon_container_get_icon_description
9335 * @container: An icon container widget.
9336 * @data: Icon data
9337 *
9338 * Gets the description for the icon. This function may return NULL.
9339 **/
9340char*
9341caja_icon_container_get_icon_description (CajaIconContainer *container,
9342 CajaIconData *data)
9343{
9344 CajaIconContainerClass *klass;
9345
9346 klass = CAJA_ICON_CONTAINER_GET_CLASS (container)((((CajaIconContainerClass*) (((GTypeInstance*) ((container))
)->g_class))))
;
9347
9348 if (klass->get_icon_description)
9349 {
9350 return klass->get_icon_description (container, data);
9351 }
9352 else
9353 {
9354 return NULL((void*)0);
9355 }
9356}
9357
9358gboolean
9359caja_icon_container_get_allow_moves (CajaIconContainer *container)
9360{
9361 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_217 = 1; else _g_boolean_var_217 =
0; _g_boolean_var_217; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
9362
9363 return container->details->drag_allow_moves;
9364}
9365
9366void
9367caja_icon_container_set_allow_moves (CajaIconContainer *container,
9368 gboolean allow_moves)
9369{
9370 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_218
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_218 = 1; else _g_boolean_var_218 =
0; _g_boolean_var_218; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9371
9372 container->details->drag_allow_moves = allow_moves;
9373}
9374
9375void
9376caja_icon_container_set_forced_icon_size (CajaIconContainer *container,
9377 int forced_icon_size)
9378{
9379 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_219
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_219 = 1; else _g_boolean_var_219 =
0; _g_boolean_var_219; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9380
9381 if (forced_icon_size != container->details->forced_icon_size)
9382 {
9383 container->details->forced_icon_size = forced_icon_size;
9384
9385 invalidate_label_sizes (container);
9386 caja_icon_container_request_update_all (container);
9387 }
9388}
9389
9390void
9391caja_icon_container_set_all_columns_same_width (CajaIconContainer *container,
9392 gboolean all_columns_same_width)
9393{
9394 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_220
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_220 = 1; else _g_boolean_var_220 =
0; _g_boolean_var_220; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9395
9396 if (all_columns_same_width != container->details->all_columns_same_width)
9397 {
9398 container->details->all_columns_same_width = all_columns_same_width;
9399
9400 invalidate_labels (container);
9401 caja_icon_container_request_update_all (container);
9402 }
9403}
9404
9405/**
9406 * caja_icon_container_set_highlighted_for_clipboard
9407 * @container: An icon container widget.
9408 * @data: Icon Data associated with all icons that should be highlighted.
9409 * Others will be unhighlighted.
9410 **/
9411void
9412caja_icon_container_set_highlighted_for_clipboard (CajaIconContainer *container,
9413 GList *clipboard_icon_data)
9414{
9415 GList *l;
9416 gboolean highlighted_for_clipboard;
9417 CajaIcon *icon = NULL((void*)0);
9418
9419 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_221
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
9420
9421 for (l = container->details->icons; l != NULL((void*)0); l = l->next)
9422 {
9423 icon = l->data;
9424 highlighted_for_clipboard = (g_list_find (clipboard_icon_data, icon->data) != NULL((void*)0));
9425
9426 eel_canvas_item_set (EEL_CANVAS_ITEM (icon->item)((((EelCanvasItem*) (void *) ((icon->item))))),
9427 "highlighted-for-clipboard", highlighted_for_clipboard,
9428 NULL((void*)0));
9429 }
9430
9431}
9432
9433/* CajaIconContainerAccessible */
9434
9435static CajaIconContainerAccessiblePrivate *
9436accessible_get_priv (AtkObject *accessible)
9437{
9438 CajaIconContainerAccessiblePrivate *priv;
9439
9440 priv = g_object_get_qdata (G_OBJECT (accessible)((((GObject*) (void *) ((accessible))))),
9441 accessible_private_data_quark);
9442
9443 return priv;
9444}
9445
9446/* AtkAction interface */
9447
9448static gboolean
9449caja_icon_container_accessible_do_action (AtkAction *accessible, int i)
9450{
9451 GtkWidget *widget;
9452 CajaIconContainer *container;
9453 GList *selection;
9454
9455 g_return_val_if_fail (i < LAST_ACTION, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if (i < LAST_ACTION) _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__)), "i < LAST_ACTION"
); return ((0)); } } while (0)
;
9456
9457 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9458 if (!widget)
9459 {
9460 return FALSE(0);
9461 }
9462
9463 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9464 switch (i)
9465 {
9466 case ACTION_ACTIVATE :
9467 selection = caja_icon_container_get_selection (container);
9468
9469 if (selection)
9470 {
9471 g_signal_emit_by_name (container, "activate", selection);
9472 g_list_free (selection);
9473 }
9474 break;
9475 case ACTION_MENU :
9476 handle_popups (container, NULL((void*)0),"context_click_background");
9477 break;
9478 default :
9479 g_warning ("Invalid action passed to CajaIconContainerAccessible::do_action");
9480 return FALSE(0);
9481 }
9482 return TRUE(!(0));
9483}
9484
9485static int
9486caja_icon_container_accessible_get_n_actions (AtkAction *accessible)
9487{
9488 return LAST_ACTION;
9489}
9490
9491static const char *
9492caja_icon_container_accessible_action_get_description (AtkAction *accessible,
9493 int i)
9494{
9495 CajaIconContainerAccessiblePrivate *priv;
9496
9497 g_assert (i < LAST_ACTION)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_223
; if (i < LAST_ACTION) _g_boolean_var_223 = 1; else _g_boolean_var_223
= 0; _g_boolean_var_223; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 9497, ((const char*)
(__func__)), "i < LAST_ACTION"); } while (0)
;
9498
9499 priv = accessible_get_priv (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9500
9501 if (priv->action_descriptions[i])
9502 {
9503 return priv->action_descriptions[i];
9504 }
9505 else
9506 {
9507 return caja_icon_container_accessible_action_descriptions[i];
9508 }
9509}
9510
9511static const char *
9512caja_icon_container_accessible_action_get_name (AtkAction *accessible, int i)
9513{
9514 g_assert (i < LAST_ACTION)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_224
; if (i < LAST_ACTION) _g_boolean_var_224 = 1; else _g_boolean_var_224
= 0; _g_boolean_var_224; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 9514, ((const char*)
(__func__)), "i < LAST_ACTION"); } while (0)
;
9515
9516 return caja_icon_container_accessible_action_names[i];
9517}
9518
9519static const char *
9520caja_icon_container_accessible_action_get_keybinding (AtkAction *accessible,
9521 int i)
9522{
9523 g_assert (i < LAST_ACTION)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_225
; if (i < LAST_ACTION) _g_boolean_var_225 = 1; else _g_boolean_var_225
= 0; _g_boolean_var_225; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 9523, ((const char*)
(__func__)), "i < LAST_ACTION"); } while (0)
;
9524
9525 return NULL((void*)0);
9526}
9527
9528static gboolean
9529caja_icon_container_accessible_action_set_description (AtkAction *accessible,
9530 int i,
9531 const char *description)
9532{
9533 CajaIconContainerAccessiblePrivate *priv;
9534
9535 g_assert (i < LAST_ACTION)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_226
; if (i < LAST_ACTION) _g_boolean_var_226 = 1; else _g_boolean_var_226
= 0; _g_boolean_var_226; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-container.c", 9535, ((const char*)
(__func__)), "i < LAST_ACTION"); } while (0)
;
9536
9537 priv = accessible_get_priv (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9538
9539 if (priv->action_descriptions[i])
9540 {
9541 g_free (priv->action_descriptions[i]);
9542 }
9543 priv->action_descriptions[i] = g_strdup (description)g_strdup_inline (description);
9544
9545 return FALSE(0);
9546}
9547
9548static void
9549caja_icon_container_accessible_action_interface_init (AtkActionIface *iface)
9550{
9551 iface->do_action = caja_icon_container_accessible_do_action;
9552 iface->get_n_actions = caja_icon_container_accessible_get_n_actions;
9553 iface->get_description = caja_icon_container_accessible_action_get_description;
9554 iface->get_name = caja_icon_container_accessible_action_get_name;
9555 iface->get_keybinding = caja_icon_container_accessible_action_get_keybinding;
9556 iface->set_description = caja_icon_container_accessible_action_set_description;
9557}
9558
9559/* AtkSelection interface */
9560
9561static void
9562caja_icon_container_accessible_update_selection (AtkObject *accessible)
9563{
9564 CajaIconContainer *container;
9565 CajaIconContainerAccessiblePrivate *priv;
9566 GList *l;
9567 CajaIcon *icon = NULL((void*)0);
9568
9569 container = CAJA_ICON_CONTAINER (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)))((((CajaIconContainer*) (void *) ((gtk_accessible_get_widget (
((((GtkAccessible*) (void *) ((accessible)))))))))))
;
9570
9571 priv = accessible_get_priv (accessible);
9572
9573 if (priv->selection)
9574 {
9575 g_list_free (priv->selection);
9576 priv->selection = NULL((void*)0);
9577 }
9578
9579 for (l = container->details->icons; l != NULL((void*)0); l = l->next)
9580 {
9581 icon = l->data;
9582 if (icon->is_selected)
9583 {
9584 priv->selection = g_list_prepend (priv->selection,
9585 icon);
9586 }
9587 }
9588
9589 priv->selection = g_list_reverse (priv->selection);
9590}
9591
9592static void
9593caja_icon_container_accessible_selection_changed_cb (CajaIconContainer *container,
9594 gpointer data)
9595{
9596 g_signal_emit_by_name (data, "selection_changed");
9597}
9598
9599static void
9600caja_icon_container_accessible_icon_added_cb (CajaIconContainer *container,
9601 CajaIconData *icon_data,
9602 gpointer data)
9603{
9604 CajaIcon *icon;
9605
9606 // We don't want to emit children_changed signals during any type of load.
9607 if (container->details->is_loading || container->details->is_populating_container)
9608 return;
9609
9610 icon = g_hash_table_lookup (container->details->icon_set, icon_data);
9611 if (icon)
9612 {
9613 AtkObject *atk_parent;
9614 AtkObject *atk_child;
9615 int index;
9616
9617 atk_parent = ATK_OBJECT (data)((((AtkObject*) (void *) ((data)))));
9618 atk_child = atk_gobject_accessible_for_object
9619 (G_OBJECT (icon->item)((((GObject*) (void *) ((icon->item))))));
9620 index = g_list_index (container->details->icons, icon);
9621
9622 g_signal_emit_by_name (atk_parent, "children_changed::add",
9623 index, atk_child, NULL((void*)0));
9624 }
9625}
9626
9627static void
9628caja_icon_container_accessible_icon_removed_cb (CajaIconContainer *container,
9629 CajaIconData *icon_data,
9630 gpointer data)
9631{
9632 CajaIcon *icon;
9633
9634 icon = g_hash_table_lookup (container->details->icon_set, icon_data);
9635 if (icon)
9636 {
9637 AtkObject *atk_parent;
9638 AtkObject *atk_child;
9639 int index;
9640
9641 atk_parent = ATK_OBJECT (data)((((AtkObject*) (void *) ((data)))));
9642 atk_child = atk_gobject_accessible_for_object
9643 (G_OBJECT (icon->item)((((GObject*) (void *) ((icon->item))))));
9644 index = g_list_index (container->details->icons, icon);
9645
9646 g_signal_emit_by_name (atk_parent, "children_changed::remove",
9647 index, atk_child, NULL((void*)0));
9648 }
9649}
9650
9651static void
9652caja_icon_container_accessible_cleared_cb (CajaIconContainer *container,
9653 gpointer data)
9654{
9655 g_signal_emit_by_name (data, "children_changed", 0, NULL((void*)0), NULL((void*)0));
9656}
9657
9658
9659static gboolean
9660caja_icon_container_accessible_add_selection (AtkSelection *accessible,
9661 int i)
9662{
9663 GtkWidget *widget;
9664 CajaIconContainer *container;
9665 CajaIcon *icon;
9666
9667 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9668 if (!widget)
9669 {
9670 return FALSE(0);
9671 }
9672
9673 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9674
9675 icon = g_list_nth_data (container->details->icons, i);
9676 if (icon)
9677 {
9678 GList *selection;
9679
9680 selection = caja_icon_container_get_selection (container);
9681 selection = g_list_prepend (selection,
9682 icon->data);
9683 caja_icon_container_set_selection (container, selection);
9684
9685 g_list_free (selection);
9686 return TRUE(!(0));
9687 }
9688
9689 return FALSE(0);
9690}
9691
9692static gboolean
9693caja_icon_container_accessible_clear_selection (AtkSelection *accessible)
9694{
9695 GtkWidget *widget;
9696 CajaIconContainer *container;
9697
9698 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9699 if (!widget)
9700 {
9701 return FALSE(0);
9702 }
9703
9704 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9705
9706 caja_icon_container_unselect_all (container);
9707
9708 return TRUE(!(0));
9709}
9710
9711static AtkObject *
9712caja_icon_container_accessible_ref_selection (AtkSelection *accessible,
9713 int i)
9714{
9715 CajaIconContainerAccessiblePrivate *priv;
9716 CajaIcon *icon;
9717
9718 caja_icon_container_accessible_update_selection (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9719 priv = accessible_get_priv (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9720
9721 icon = g_list_nth_data (priv->selection, i);
9722 if (icon)
9723 {
9724 AtkObject *atk_object;
9725
9726 atk_object = atk_gobject_accessible_for_object (G_OBJECT (icon->item)((((GObject*) (void *) ((icon->item))))));
9727 if (atk_object)
9728 {
9729 g_object_ref (atk_object)((__typeof__ (atk_object)) (g_object_ref) (atk_object));
9730 }
9731
9732 return atk_object;
9733 }
9734 else
9735 {
9736 return NULL((void*)0);
9737 }
9738}
9739
9740static int
9741caja_icon_container_accessible_get_selection_count (AtkSelection *accessible)
9742{
9743 int count;
9744 CajaIconContainerAccessiblePrivate *priv;
9745
9746 caja_icon_container_accessible_update_selection (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9747 priv = accessible_get_priv (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9748
9749 count = g_list_length (priv->selection);
9750
9751 return count;
9752}
9753
9754static gboolean
9755caja_icon_container_accessible_is_child_selected (AtkSelection *accessible,
9756 int i)
9757{
9758 CajaIconContainer *container;
9759 CajaIcon *icon;
9760 GtkWidget *widget;
9761
9762 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9763 if (!widget)
9764 {
9765 return FALSE(0);
9766 }
9767
9768 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9769
9770 icon = g_list_nth_data (container->details->icons, i);
9771 return icon ? icon->is_selected : FALSE(0);
9772}
9773
9774static gboolean
9775caja_icon_container_accessible_remove_selection (AtkSelection *accessible,
9776 int i)
9777{
9778 CajaIconContainer *container;
9779 CajaIconContainerAccessiblePrivate *priv;
9780 CajaIcon *icon;
9781 GtkWidget *widget;
9782
9783 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9784 if (!widget)
9785 {
9786 return FALSE(0);
9787 }
9788
9789 caja_icon_container_accessible_update_selection (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9790 priv = accessible_get_priv (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9791
9792 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9793
9794 icon = g_list_nth_data (priv->selection, i);
9795 if (icon)
9796 {
9797 GList *selection;
9798
9799 selection = caja_icon_container_get_selection (container);
9800 selection = g_list_remove (selection, icon->data);
9801 caja_icon_container_set_selection (container, selection);
9802
9803 g_list_free (selection);
9804 return TRUE(!(0));
9805 }
9806
9807 return FALSE(0);
9808}
9809
9810static gboolean
9811caja_icon_container_accessible_select_all_selection (AtkSelection *accessible)
9812{
9813 CajaIconContainer *container;
9814 GtkWidget *widget;
9815
9816 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9817 if (!widget)
9818 {
9819 return FALSE(0);
9820 }
9821
9822 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9823
9824 caja_icon_container_select_all (container);
9825
9826 return TRUE(!(0));
9827}
9828
9829void
9830caja_icon_container_widget_to_file_operation_position (CajaIconContainer *container,
9831 GdkPoint *position)
9832{
9833 double x, y;
9834
9835 g_return_if_fail (position != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if (position != ((void*)0)) _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__)), "position != NULL"
); return; } } while (0)
;
9836
9837 x = position->x;
9838 y = position->y;
9839
9840 eel_canvas_window_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), x, y, &x, &y);
9841
9842 position->x = (int) x;
9843 position->y = (int) y;
9844
9845 /* ensure that we end up in the middle of the icon */
9846 position->x -= caja_get_icon_size_for_zoom_level (container->details->zoom_level) / 2;
9847 position->y -= caja_get_icon_size_for_zoom_level (container->details->zoom_level) / 2;
9848}
9849
9850static void
9851caja_icon_container_accessible_selection_interface_init (AtkSelectionIface *iface)
9852{
9853 iface->add_selection = caja_icon_container_accessible_add_selection;
9854 iface->clear_selection = caja_icon_container_accessible_clear_selection;
9855 iface->ref_selection = caja_icon_container_accessible_ref_selection;
9856 iface->get_selection_count = caja_icon_container_accessible_get_selection_count;
9857 iface->is_child_selected = caja_icon_container_accessible_is_child_selected;
9858 iface->remove_selection = caja_icon_container_accessible_remove_selection;
9859 iface->select_all_selection = caja_icon_container_accessible_select_all_selection;
9860}
9861
9862
9863static gint
9864caja_icon_container_accessible_get_n_children (AtkObject *accessible)
9865{
9866 CajaIconContainer *container;
9867 GtkWidget *widget;
9868 gint i;
9869
9870 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9871 if (!widget)
9872 {
9873 return FALSE(0);
9874 }
9875
9876 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9877
9878 i = g_hash_table_size (container->details->icon_set);
9879 if (container->details->rename_widget)
9880 {
9881 i++;
9882 }
9883 return i;
9884}
9885
9886static AtkObject*
9887caja_icon_container_accessible_ref_child (AtkObject *accessible, int i)
9888{
9889 AtkObject *atk_object;
9890 CajaIconContainer *container;
9891 CajaIcon *icon;
9892 GtkWidget *widget;
9893
9894 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)((((GtkAccessible*) (void *) ((accessible))))));
9895 if (!widget)
9896 {
9897 return NULL((void*)0);
9898 }
9899
9900 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
9901
9902 icon = g_list_nth_data (container->details->icons, i);
9903 if (icon)
9904 {
9905 atk_object = atk_gobject_accessible_for_object (G_OBJECT (icon->item)((((GObject*) (void *) ((icon->item))))));
9906 g_object_ref (atk_object)((__typeof__ (atk_object)) (g_object_ref) (atk_object));
9907
9908 return atk_object;
9909 }
9910 else
9911 {
9912 if (i == g_list_length (container->details->icons))
9913 {
9914 if (container->details->rename_widget)
9915 {
9916 atk_object = gtk_widget_get_accessible (container->details->rename_widget);
9917 g_object_ref (atk_object)((__typeof__ (atk_object)) (g_object_ref) (atk_object));
9918
9919 return atk_object;
9920 }
9921 }
9922 return NULL((void*)0);
9923 }
9924}
9925
9926static void
9927caja_icon_container_accessible_initialize (AtkObject *accessible,
9928 gpointer data)
9929{
9930 CajaIconContainerAccessiblePrivate *priv;
9931
9932 if (ATK_OBJECT_CLASS (accessible_parent_class)((((AtkObjectClass*) (void *) ((accessible_parent_class)))))->initialize)
9933 {
9934 ATK_OBJECT_CLASS (accessible_parent_class)((((AtkObjectClass*) (void *) ((accessible_parent_class)))))->initialize (accessible, data);
9935 }
9936
9937 priv = g_new0 (CajaIconContainerAccessiblePrivate, 1)(CajaIconContainerAccessiblePrivate *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (CajaIconContainerAccessiblePrivate
); 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; }))
;
9938 g_object_set_qdata (G_OBJECT (accessible)((((GObject*) (void *) ((accessible))))),
9939 accessible_private_data_quark,
9940 priv);
9941
9942 if (GTK_IS_ACCESSIBLE (accessible)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(accessible)); GType __t = ((gtk_accessible_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; }))))
)
9943 {
9944 CajaIconContainer *container;
9945
9946 caja_icon_container_accessible_update_selection
9947 (ATK_OBJECT (accessible)((((AtkObject*) (void *) ((accessible))))));
9948
9949 container = CAJA_ICON_CONTAINER (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)))((((CajaIconContainer*) (void *) ((gtk_accessible_get_widget (
((((GtkAccessible*) (void *) ((accessible)))))))))))
;
9950 g_signal_connect (G_OBJECT (container), "selection_changed",g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("selection_changed"), (((GCallback) (caja_icon_container_accessible_selection_changed_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9951 G_CALLBACK (caja_icon_container_accessible_selection_changed_cb),g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("selection_changed"), (((GCallback) (caja_icon_container_accessible_selection_changed_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9952 accessible)g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("selection_changed"), (((GCallback) (caja_icon_container_accessible_selection_changed_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
;
9953 g_signal_connect (G_OBJECT (container), "icon_added",g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("icon_added"), (((GCallback) (caja_icon_container_accessible_icon_added_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9954 G_CALLBACK (caja_icon_container_accessible_icon_added_cb),g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("icon_added"), (((GCallback) (caja_icon_container_accessible_icon_added_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9955 accessible)g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("icon_added"), (((GCallback) (caja_icon_container_accessible_icon_added_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
;
9956 g_signal_connect (G_OBJECT (container), "icon_removed",g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("icon_removed"), (((GCallback) (caja_icon_container_accessible_icon_removed_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9957 G_CALLBACK (caja_icon_container_accessible_icon_removed_cb),g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("icon_removed"), (((GCallback) (caja_icon_container_accessible_icon_removed_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9958 accessible)g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("icon_removed"), (((GCallback) (caja_icon_container_accessible_icon_removed_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
;
9959 g_signal_connect (G_OBJECT (container), "cleared",g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("cleared"), (((GCallback) (caja_icon_container_accessible_cleared_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9960 G_CALLBACK (caja_icon_container_accessible_cleared_cb),g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("cleared"), (((GCallback) (caja_icon_container_accessible_cleared_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
9961 accessible)g_signal_connect_data ((((((GObject*) (void *) ((container)))
))), ("cleared"), (((GCallback) (caja_icon_container_accessible_cleared_cb
))), (accessible), ((void*)0), (GConnectFlags) 0)
;
9962 }
9963}
9964
9965static void
9966caja_icon_container_accessible_finalize (GObject *object)
9967{
9968 CajaIconContainerAccessiblePrivate *priv;
9969 int i;
9970
9971 priv = accessible_get_priv (ATK_OBJECT (object)((((AtkObject*) (void *) ((object))))));
9972 if (priv->selection)
9973 {
9974 g_list_free (priv->selection);
9975 }
9976
9977 for (i = 0; i < LAST_ACTION; i++)
9978 {
9979 if (priv->action_descriptions[i])
9980 {
9981 g_free (priv->action_descriptions[i]);
9982 }
9983 }
9984
9985 g_free (priv);
9986
9987 G_OBJECT_CLASS (accessible_parent_class)((((GObjectClass*) (void *) ((accessible_parent_class)))))->finalize (object);
9988}
9989
9990G_DEFINE_TYPE_WITH_CODE (CajaIconContainerAccessible,static void caja_icon_container_accessible_init (CajaIconContainerAccessible
*self); static void caja_icon_container_accessible_class_init
(CajaIconContainerAccessibleClass *klass); static GType caja_icon_container_accessible_get_type_once
(void); static gpointer caja_icon_container_accessible_parent_class
= ((void*)0); static gint CajaIconContainerAccessible_private_offset
; static void caja_icon_container_accessible_class_intern_init
(gpointer klass) { caja_icon_container_accessible_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainerAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainerAccessible_private_offset
); caja_icon_container_accessible_class_init ((CajaIconContainerAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
caja_icon_container_accessible_get_instance_private (CajaIconContainerAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CajaIconContainerAccessible_private_offset
)))); } GType caja_icon_container_accessible_get_type (void) {
static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_icon_container_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(eel_canvas_accessible_get_type (), g_intern_static_string (
"CajaIconContainerAccessible"), sizeof (CajaIconContainerAccessibleClass
), (GClassInitFunc)(void (*)(void)) caja_icon_container_accessible_class_intern_init
, sizeof (CajaIconContainerAccessible), (GInstanceInitFunc)(void
(*)(void)) caja_icon_container_accessible_init, (GTypeFlags)
0); { {{ const GInterfaceInfo g_implement_interface_info = {
(GInterfaceInitFunc)(void (*)(void)) caja_icon_container_accessible_action_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_action_get_type ()), &g_implement_interface_info);
} { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) caja_icon_container_accessible_selection_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_selection_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
9991 caja_icon_container_accessible,static void caja_icon_container_accessible_init (CajaIconContainerAccessible
*self); static void caja_icon_container_accessible_class_init
(CajaIconContainerAccessibleClass *klass); static GType caja_icon_container_accessible_get_type_once
(void); static gpointer caja_icon_container_accessible_parent_class
= ((void*)0); static gint CajaIconContainerAccessible_private_offset
; static void caja_icon_container_accessible_class_intern_init
(gpointer klass) { caja_icon_container_accessible_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainerAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainerAccessible_private_offset
); caja_icon_container_accessible_class_init ((CajaIconContainerAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
caja_icon_container_accessible_get_instance_private (CajaIconContainerAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CajaIconContainerAccessible_private_offset
)))); } GType caja_icon_container_accessible_get_type (void) {
static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_icon_container_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(eel_canvas_accessible_get_type (), g_intern_static_string (
"CajaIconContainerAccessible"), sizeof (CajaIconContainerAccessibleClass
), (GClassInitFunc)(void (*)(void)) caja_icon_container_accessible_class_intern_init
, sizeof (CajaIconContainerAccessible), (GInstanceInitFunc)(void
(*)(void)) caja_icon_container_accessible_init, (GTypeFlags)
0); { {{ const GInterfaceInfo g_implement_interface_info = {
(GInterfaceInitFunc)(void (*)(void)) caja_icon_container_accessible_action_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_action_get_type ()), &g_implement_interface_info);
} { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) caja_icon_container_accessible_selection_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_selection_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
9992 eel_canvas_accessible_get_type (),static void caja_icon_container_accessible_init (CajaIconContainerAccessible
*self); static void caja_icon_container_accessible_class_init
(CajaIconContainerAccessibleClass *klass); static GType caja_icon_container_accessible_get_type_once
(void); static gpointer caja_icon_container_accessible_parent_class
= ((void*)0); static gint CajaIconContainerAccessible_private_offset
; static void caja_icon_container_accessible_class_intern_init
(gpointer klass) { caja_icon_container_accessible_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainerAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainerAccessible_private_offset
); caja_icon_container_accessible_class_init ((CajaIconContainerAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
caja_icon_container_accessible_get_instance_private (CajaIconContainerAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CajaIconContainerAccessible_private_offset
)))); } GType caja_icon_container_accessible_get_type (void) {
static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_icon_container_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(eel_canvas_accessible_get_type (), g_intern_static_string (
"CajaIconContainerAccessible"), sizeof (CajaIconContainerAccessibleClass
), (GClassInitFunc)(void (*)(void)) caja_icon_container_accessible_class_intern_init
, sizeof (CajaIconContainerAccessible), (GInstanceInitFunc)(void
(*)(void)) caja_icon_container_accessible_init, (GTypeFlags)
0); { {{ const GInterfaceInfo g_implement_interface_info = {
(GInterfaceInitFunc)(void (*)(void)) caja_icon_container_accessible_action_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_action_get_type ()), &g_implement_interface_info);
} { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) caja_icon_container_accessible_selection_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_selection_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
9993 G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION,static void caja_icon_container_accessible_init (CajaIconContainerAccessible
*self); static void caja_icon_container_accessible_class_init
(CajaIconContainerAccessibleClass *klass); static GType caja_icon_container_accessible_get_type_once
(void); static gpointer caja_icon_container_accessible_parent_class
= ((void*)0); static gint CajaIconContainerAccessible_private_offset
; static void caja_icon_container_accessible_class_intern_init
(gpointer klass) { caja_icon_container_accessible_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainerAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainerAccessible_private_offset
); caja_icon_container_accessible_class_init ((CajaIconContainerAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
caja_icon_container_accessible_get_instance_private (CajaIconContainerAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CajaIconContainerAccessible_private_offset
)))); } GType caja_icon_container_accessible_get_type (void) {
static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_icon_container_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(eel_canvas_accessible_get_type (), g_intern_static_string (
"CajaIconContainerAccessible"), sizeof (CajaIconContainerAccessibleClass
), (GClassInitFunc)(void (*)(void)) caja_icon_container_accessible_class_intern_init
, sizeof (CajaIconContainerAccessible), (GInstanceInitFunc)(void
(*)(void)) caja_icon_container_accessible_init, (GTypeFlags)
0); { {{ const GInterfaceInfo g_implement_interface_info = {
(GInterfaceInitFunc)(void (*)(void)) caja_icon_container_accessible_action_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_action_get_type ()), &g_implement_interface_info);
} { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) caja_icon_container_accessible_selection_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_selection_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
9994 caja_icon_container_accessible_action_interface_init)static void caja_icon_container_accessible_init (CajaIconContainerAccessible
*self); static void caja_icon_container_accessible_class_init
(CajaIconContainerAccessibleClass *klass); static GType caja_icon_container_accessible_get_type_once
(void); static gpointer caja_icon_container_accessible_parent_class
= ((void*)0); static gint CajaIconContainerAccessible_private_offset
; static void caja_icon_container_accessible_class_intern_init
(gpointer klass) { caja_icon_container_accessible_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainerAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainerAccessible_private_offset
); caja_icon_container_accessible_class_init ((CajaIconContainerAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
caja_icon_container_accessible_get_instance_private (CajaIconContainerAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CajaIconContainerAccessible_private_offset
)))); } GType caja_icon_container_accessible_get_type (void) {
static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_icon_container_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(eel_canvas_accessible_get_type (), g_intern_static_string (
"CajaIconContainerAccessible"), sizeof (CajaIconContainerAccessibleClass
), (GClassInitFunc)(void (*)(void)) caja_icon_container_accessible_class_intern_init
, sizeof (CajaIconContainerAccessible), (GInstanceInitFunc)(void
(*)(void)) caja_icon_container_accessible_init, (GTypeFlags)
0); { {{ const GInterfaceInfo g_implement_interface_info = {
(GInterfaceInitFunc)(void (*)(void)) caja_icon_container_accessible_action_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_action_get_type ()), &g_implement_interface_info);
} { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) caja_icon_container_accessible_selection_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_selection_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
9995 G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION,static void caja_icon_container_accessible_init (CajaIconContainerAccessible
*self); static void caja_icon_container_accessible_class_init
(CajaIconContainerAccessibleClass *klass); static GType caja_icon_container_accessible_get_type_once
(void); static gpointer caja_icon_container_accessible_parent_class
= ((void*)0); static gint CajaIconContainerAccessible_private_offset
; static void caja_icon_container_accessible_class_intern_init
(gpointer klass) { caja_icon_container_accessible_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainerAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainerAccessible_private_offset
); caja_icon_container_accessible_class_init ((CajaIconContainerAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
caja_icon_container_accessible_get_instance_private (CajaIconContainerAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CajaIconContainerAccessible_private_offset
)))); } GType caja_icon_container_accessible_get_type (void) {
static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_icon_container_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(eel_canvas_accessible_get_type (), g_intern_static_string (
"CajaIconContainerAccessible"), sizeof (CajaIconContainerAccessibleClass
), (GClassInitFunc)(void (*)(void)) caja_icon_container_accessible_class_intern_init
, sizeof (CajaIconContainerAccessible), (GInstanceInitFunc)(void
(*)(void)) caja_icon_container_accessible_init, (GTypeFlags)
0); { {{ const GInterfaceInfo g_implement_interface_info = {
(GInterfaceInitFunc)(void (*)(void)) caja_icon_container_accessible_action_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_action_get_type ()), &g_implement_interface_info);
} { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) caja_icon_container_accessible_selection_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_selection_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
9996 caja_icon_container_accessible_selection_interface_init))static void caja_icon_container_accessible_init (CajaIconContainerAccessible
*self); static void caja_icon_container_accessible_class_init
(CajaIconContainerAccessibleClass *klass); static GType caja_icon_container_accessible_get_type_once
(void); static gpointer caja_icon_container_accessible_parent_class
= ((void*)0); static gint CajaIconContainerAccessible_private_offset
; static void caja_icon_container_accessible_class_intern_init
(gpointer klass) { caja_icon_container_accessible_parent_class
= g_type_class_peek_parent (klass); if (CajaIconContainerAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaIconContainerAccessible_private_offset
); caja_icon_container_accessible_class_init ((CajaIconContainerAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
caja_icon_container_accessible_get_instance_private (CajaIconContainerAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CajaIconContainerAccessible_private_offset
)))); } GType caja_icon_container_accessible_get_type (void) {
static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_icon_container_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_icon_container_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(eel_canvas_accessible_get_type (), g_intern_static_string (
"CajaIconContainerAccessible"), sizeof (CajaIconContainerAccessibleClass
), (GClassInitFunc)(void (*)(void)) caja_icon_container_accessible_class_intern_init
, sizeof (CajaIconContainerAccessible), (GInstanceInitFunc)(void
(*)(void)) caja_icon_container_accessible_init, (GTypeFlags)
0); { {{ const GInterfaceInfo g_implement_interface_info = {
(GInterfaceInitFunc)(void (*)(void)) caja_icon_container_accessible_action_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_action_get_type ()), &g_implement_interface_info);
} { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) caja_icon_container_accessible_selection_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_selection_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
9997
9998static void
9999caja_icon_container_accessible_init (CajaIconContainerAccessible *accessible)
10000{
10001}
10002
10003static void
10004caja_icon_container_accessible_class_init (CajaIconContainerAccessibleClass *klass)
10005{
10006 GObjectClass *gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
10007 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
10008
10009 accessible_parent_class = g_type_class_peek_parent (klass);
10010
10011 gobject_class->finalize = caja_icon_container_accessible_finalize;
10012
10013 atk_class->get_n_children = caja_icon_container_accessible_get_n_children;
10014 atk_class->ref_child = caja_icon_container_accessible_ref_child;
10015 atk_class->initialize = caja_icon_container_accessible_initialize;
10016
10017 accessible_private_data_quark = g_quark_from_static_string ("icon-container-accessible-private-data");
10018}
10019
10020#if ! defined (CAJA_OMIT_SELF_CHECK)
10021
10022static char *
10023check_compute_stretch (int icon_x, int icon_y, int icon_size,
10024 int start_pointer_x, int start_pointer_y,
10025 int end_pointer_x, int end_pointer_y)
10026{
10027 StretchState start, current;
10028
10029 start.icon_x = icon_x;
10030 start.icon_y = icon_y;
10031 start.icon_size = icon_size;
10032 start.pointer_x = start_pointer_x;
10033 start.pointer_y = start_pointer_y;
10034 current.pointer_x = end_pointer_x;
10035 current.pointer_y = end_pointer_y;
10036
10037 compute_stretch (&start, &current);
10038
10039 return g_strdup_printf ("%d,%d:%d",
10040 current.icon_x,
10041 current.icon_y,
10042 current.icon_size);
10043}
10044
10045void
10046caja_self_check_icon_container (void)
10047{
10048 EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 16, 0, 0, 0, 0), "0,0:16")do { eel_before_check ("check_compute_stretch (0, 0, 16, 0, 0, 0, 0)"
, "caja-icon-container.c", 10048); eel_check_string_result (check_compute_stretch
(0, 0, 16, 0, 0, 0, 0), "0,0:16"); } while (0)
;
10049 EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 16, 16, 16, 17, 17), "0,0:17")do { eel_before_check ("check_compute_stretch (0, 0, 16, 16, 16, 17, 17)"
, "caja-icon-container.c", 10049); eel_check_string_result (check_compute_stretch
(0, 0, 16, 16, 16, 17, 17), "0,0:17"); } while (0)
;
10050 EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 16, 16, 16, 17, 16), "0,0:16")do { eel_before_check ("check_compute_stretch (0, 0, 16, 16, 16, 17, 16)"
, "caja-icon-container.c", 10050); eel_check_string_result (check_compute_stretch
(0, 0, 16, 16, 16, 17, 16), "0,0:16"); } while (0)
;
10051 EEL_CHECK_STRING_RESULT (check_compute_stretch (100, 100, 64, 105, 105, 40, 40), "35,35:129")do { eel_before_check ("check_compute_stretch (100, 100, 64, 105, 105, 40, 40)"
, "caja-icon-container.c", 10051); eel_check_string_result (check_compute_stretch
(100, 100, 64, 105, 105, 40, 40), "35,35:129"); } while (0)
;
10052}
10053#endif /* ! CAJA_OMIT_SELF_CHECK */
10054
10055gboolean
10056caja_icon_container_is_layout_rtl (CajaIconContainer *container)
10057{
10058 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_228 = 1; else _g_boolean_var_228 =
0; _g_boolean_var_228; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return (0); } } while (0)
;
10059
10060 return container->details->layout_mode == CAJA_ICON_LAYOUT_T_B_R_L ||
10061 container->details->layout_mode == CAJA_ICON_LAYOUT_R_L_T_B;
10062}
10063
10064gboolean
10065caja_icon_container_is_layout_vertical (CajaIconContainer *container)
10066{
10067 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_229 = 1; else _g_boolean_var_229 =
0; _g_boolean_var_229; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return ((0)); } } while (0)
;
10068
10069 return (container->details->layout_mode == CAJA_ICON_LAYOUT_T_B_L_R ||
10070 container->details->layout_mode == CAJA_ICON_LAYOUT_T_B_R_L);
10071}
10072
10073int
10074caja_icon_container_get_max_layout_lines_for_pango (CajaIconContainer *container)
10075{
10076 int limit;
10077
10078 if (caja_icon_container_get_is_desktop (container))
10079 {
10080 limit = desktop_text_ellipsis_limit;
10081 }
10082 else
10083 {
10084 limit = text_ellipsis_limits[container->details->zoom_level];
10085 }
10086
10087 if (limit <= 0)
10088 {
10089 return G_MININT(-2147483647 -1);
10090 }
10091
10092 return -limit;
10093}
10094
10095int
10096caja_icon_container_get_max_layout_lines (CajaIconContainer *container)
10097{
10098 int limit;
10099
10100 if (caja_icon_container_get_is_desktop (container))
10101 {
10102 limit = desktop_text_ellipsis_limit;
10103 }
10104 else
10105 {
10106 limit = text_ellipsis_limits[container->details->zoom_level];
10107 }
10108
10109 if (limit <= 0)
10110 {
10111 return G_MAXINT2147483647;
10112 }
10113
10114 return limit;
10115}
10116
10117void
10118caja_icon_container_begin_loading (CajaIconContainer *container)
10119{
10120 gboolean dummy;
10121
10122 if (caja_icon_container_get_store_layout_timestamps (container))
10123 {
10124 container->details->layout_timestamp = UNDEFINED_TIME((time_t) (-1));
10125 g_signal_emit (container,
10126 signals[GET_STORED_LAYOUT_TIMESTAMP], 0,
10127 NULL((void*)0), &container->details->layout_timestamp, &dummy);
10128 }
10129}
10130
10131static void
10132store_layout_timestamps_now (CajaIconContainer *container)
10133{
10134 GList *p;
10135 gboolean dummy;
10136 CajaIcon *icon = NULL((void*)0);
10137
10138 container->details->layout_timestamp = time (NULL((void*)0));
10139 g_signal_emit (container,
10140 signals[STORE_LAYOUT_TIMESTAMP], 0,
10141 NULL((void*)0), &container->details->layout_timestamp, &dummy);
10142
10143 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
10144 {
10145 icon = p->data;
10146
10147 g_signal_emit (container,
10148 signals[STORE_LAYOUT_TIMESTAMP], 0,
10149 icon->data, &container->details->layout_timestamp, &dummy);
10150 }
10151}
10152
10153void
10154caja_icon_container_end_loading (CajaIconContainer *container,
10155 gboolean all_icons_added)
10156{
10157 if (all_icons_added &&
10158 caja_icon_container_get_store_layout_timestamps (container))
10159 {
10160 if (container->details->new_icons == NULL((void*)0))
10161 {
10162 store_layout_timestamps_now (container);
10163 }
10164 else
10165 {
10166 container->details->store_layout_timestamps_when_finishing_new_icons = TRUE(!(0));
10167 }
10168 }
10169}
10170
10171gboolean
10172caja_icon_container_get_store_layout_timestamps (CajaIconContainer *container)
10173{
10174 return container->details->store_layout_timestamps;
10175}
10176
10177void
10178caja_icon_container_set_store_layout_timestamps (CajaIconContainer *container,
10179 gboolean store_layout_timestamps)
10180{
10181 container->details->store_layout_timestamps = store_layout_timestamps;
10182}
diff --git a/2024-07-29-023715-6438-1/report-554110.html b/2024-07-29-023715-6438-1/report-554110.html new file mode 100644 index 000000000..b10cb8070 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-554110.html @@ -0,0 +1,9582 @@ + + + +caja-file.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file.c
Warning:line 3089, column 2
Value stored to 'compare_result' 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 caja-file.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-file.c: Caja file model.
4
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <grp.h>
27#include <gtk/gtk.h>
28#include <glib/gi18n.h>
29#include <glib/gstdio.h>
30#include <gio/gio.h>
31#include <glib.h>
32#include <libxml/parser.h>
33#include <pwd.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <sys/time.h>
37#include <time.h>
38#include <unistd.h>
39#include <sys/stat.h>
40
41#include <eel/eel-debug.h>
42#include <eel/eel-glib-extensions.h>
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-vfs-extensions.h>
45#include <eel/eel-gtk-macros.h>
46#include <eel/eel-string.h>
47
48#include <libcaja-extension/caja-file-info.h>
49#include <libcaja-extension/caja-extension-private.h>
50#include <libcaja-private/caja-extensions.h>
51
52#include "caja-file.h"
53#include "caja-directory-notify.h"
54#include "caja-directory-private.h"
55#include "caja-signaller.h"
56#include "caja-desktop-directory.h"
57#include "caja-desktop-directory-file.h"
58#include "caja-desktop-icon-file.h"
59#include "caja-file-attributes.h"
60#include "caja-file-private.h"
61#include "caja-file-operations.h"
62#include "caja-file-utilities.h"
63#include "caja-global-preferences.h"
64#include "caja-lib-self-check-functions.h"
65#include "caja-link.h"
66#include "caja-metadata.h"
67#include "caja-module.h"
68#include "caja-search-directory.h"
69#include "caja-search-directory-file.h"
70#include "caja-thumbnails.h"
71#include "caja-ui-utilities.h"
72#include "caja-vfs-file.h"
73#include "caja-saved-search-file.h"
74
75#ifdef HAVE_SELINUX1
76#include <selinux/selinux.h>
77#endif
78
79#define ICON_NAME_THUMBNAIL_LOADING"image-loading" "image-loading"
80
81#undef CAJA_FILE_DEBUG_REF
82#undef CAJA_FILE_DEBUG_REF_VALGRIND
83
84#ifdef CAJA_FILE_DEBUG_REF_VALGRIND
85#include <valgrind/valgrind.h>
86#define DEBUG_REF_PRINTFprintf VALGRIND_PRINTF_BACKTRACE
87#else
88#define DEBUG_REF_PRINTFprintf printf
89#endif
90
91/* Files that start with these characters sort after files that don't. */
92#define SORT_LAST_CHAR1'.' '.'
93#define SORT_LAST_CHAR2'#' '#'
94
95#define METADATA_ID_IS_LIST_MASK(1U<<31) (1U<<31)
96
97#define SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3 3
98#define SORT_BY_EXTENSION_MAX_SEGMENTS3 3
99
100typedef enum {
101 SHOW_HIDDEN = 1 << 0,
102 SHOW_BACKUP = 1 << 1,
103} FilterOptions;
104
105typedef void (* ModifyListFunction) (GList **list, CajaFile *file);
106
107enum {
108 CHANGED,
109 UPDATED_DEEP_COUNT_IN_PROGRESS,
110 LAST_SIGNAL
111};
112
113static int date_format_pref;
114
115static guint signals[LAST_SIGNAL] = { 0 };
116
117static GHashTable *symbolic_links;
118
119static GQuark attribute_name_q,
120 attribute_size_q,
121 attribute_size_on_disk_q,
122 attribute_type_q,
123 attribute_creation_date_q,
124 attribute_date_created_q,
125 attribute_modification_date_q,
126 attribute_date_modified_q,
127 attribute_accessed_date_q,
128 attribute_date_accessed_q,
129 attribute_emblems_q,
130 attribute_extension_q,
131 attribute_mime_type_q,
132 attribute_size_detail_q,
133 attribute_size_on_disk_detail_q,
134 attribute_deep_size_q,
135 attribute_deep_size_on_disk_q,
136 attribute_deep_file_count_q,
137 attribute_deep_directory_count_q,
138 attribute_deep_total_count_q,
139 attribute_date_changed_q,
140 attribute_trashed_on_q,
141 attribute_trash_orig_path_q,
142 attribute_date_permissions_q,
143 attribute_permissions_q,
144 attribute_selinux_context_q,
145 attribute_octal_permissions_q,
146 attribute_owner_q,
147 attribute_group_q,
148 attribute_uri_q,
149 attribute_where_q,
150 attribute_link_target_q,
151 attribute_volume_q,
152 attribute_free_space_q;
153
154static void caja_file_info_iface_init (CajaFileInfoIface *iface);
155static char * caja_file_get_owner_as_string (CajaFile *file,
156 gboolean include_real_name);
157static char * caja_file_get_type_as_string (CajaFile *file);
158static gboolean update_info_and_name (CajaFile *file,
159 GFileInfo *info);
160static const char * caja_file_peek_display_name (CajaFile *file);
161static const char * caja_file_peek_display_name_collation_key (CajaFile *file);
162static void file_mount_unmounted (GMount *mount, gpointer data);
163static void metadata_hash_free (GHashTable *hash);
164
165G_DEFINE_TYPE_WITH_CODE (CajaFile, caja_file, G_TYPE_OBJECT,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
166 G_ADD_PRIVATE (CajaFile)static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
167 G_IMPLEMENT_INTERFACE (CAJA_TYPE_FILE_INFO,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
168 caja_file_info_iface_init))static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
169
170static void
171caja_file_init (CajaFile *file)
172{
173 file->details = caja_file_get_instance_private (file);
174
175 caja_file_clear_info (file);
176 caja_file_invalidate_extension_info_internal (file);
177}
178
179static GObject*
180caja_file_constructor (GType type,
181 guint n_construct_properties,
182 GObjectConstructParam *construct_params)
183{
184 GObject *object;
185 CajaFile *file;
186
187 object = (* G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->constructor) (type,
188 n_construct_properties,
189 construct_params);
190
191 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
192
193 /* Set to default type after full construction */
194 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type != G_FILE_TYPE_UNKNOWN) {
195 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
196 }
197
198 return object;
199}
200
201gboolean
202caja_file_set_display_name (CajaFile *file,
203 const char *display_name,
204 const char *edit_name,
205 gboolean custom)
206{
207 gboolean changed;
208
209 if (custom && display_name == NULL((void*)0)) {
210 /* We're re-setting a custom display name, invalidate it if
211 we already set it so that the old one is re-read */
212 if (file->details->got_custom_display_name) {
213 file->details->got_custom_display_name = FALSE(0);
214 caja_file_invalidate_attributes (file,
215 CAJA_FILE_ATTRIBUTE_INFO);
216 }
217 return FALSE(0);
218 }
219
220 if (display_name == NULL((void*)0) || *display_name == 0) {
221 return FALSE(0);
222 }
223
224 if (!custom && file->details->got_custom_display_name) {
225 return FALSE(0);
226 }
227
228 if (edit_name == NULL((void*)0)) {
229 edit_name = display_name;
230 }
231
232 changed = FALSE(0);
233
234 if (eel_strcmp (file->details->display_name, display_name) != 0) {
235 changed = TRUE(!(0));
236
237 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
238
239 if (eel_strcmp (file->details->name, display_name) == 0) {
240 file->details->display_name = g_ref_string_acquire (file->details->name);
241 } else {
242 file->details->display_name = g_ref_string_new (display_name);
243 }
244
245 g_free (file->details->display_name_collation_key);
246 file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
247 }
248
249 if (eel_strcmp (file->details->edit_name, edit_name) != 0) {
250 changed = TRUE(!(0));
251
252 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
253 if (eel_strcmp (file->details->display_name, edit_name) == 0) {
254 file->details->edit_name = g_ref_string_acquire (file->details->display_name);
255 } else {
256 file->details->edit_name = g_ref_string_new (edit_name);
257 }
258 }
259
260 file->details->got_custom_display_name = custom;
261 return changed;
262}
263
264static void
265caja_file_clear_display_name (CajaFile *file)
266{
267 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
268 file->details->display_name = NULL((void*)0);
269 g_free (file->details->display_name_collation_key);
270 file->details->display_name_collation_key = NULL((void*)0);
271 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
272 file->details->edit_name = NULL((void*)0);
273}
274
275static gboolean
276foreach_metadata_free (gpointer key,
277 gpointer value,
278 gpointer user_data)
279{
280 guint id;
281
282 id = GPOINTER_TO_UINT (key)((guint) (gulong) (key));
283
284 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
285 g_strfreev ((char **)value);
286 } else {
287 g_free ((char *)value);
288 }
289 return TRUE(!(0));
290}
291
292
293static void
294metadata_hash_free (GHashTable *hash)
295{
296 g_hash_table_foreach_remove (hash,
297 foreach_metadata_free,
298 NULL((void*)0));
299 g_hash_table_destroy (hash);
300}
301
302static gboolean
303metadata_hash_equal (GHashTable *hash1,
304 GHashTable *hash2)
305{
306 GHashTableIter iter;
307 gpointer key1, value1, value2;
308 guint id;
309
310 if (hash1 == NULL((void*)0) && hash2 == NULL((void*)0)) {
311 return TRUE(!(0));
312 }
313
314 if (hash1 == NULL((void*)0) || hash2 == NULL((void*)0)) {
315 return FALSE(0);
316 }
317
318 if (g_hash_table_size (hash1) !=
319 g_hash_table_size (hash2)) {
320 return FALSE(0);
321 }
322
323 g_hash_table_iter_init (&iter, hash1);
324 while (g_hash_table_iter_next (&iter, &key1, &value1)) {
325 value2 = g_hash_table_lookup (hash2, key1);
326 if (value2 == NULL((void*)0)) {
327 return FALSE(0);
328 }
329 id = GPOINTER_TO_UINT (key1)((guint) (gulong) (key1));
330 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
331 if (!eel_g_strv_equal ((char **)value1, (char **)value2)) {
332 return FALSE(0);
333 }
334 } else {
335 if (strcmp ((char *)value1, (char *)value2) != 0) {
336 return FALSE(0);
337 }
338 }
339 }
340
341 return TRUE(!(0));
342}
343
344static void
345clear_metadata (CajaFile *file)
346{
347 if (file->details->metadata) {
348 metadata_hash_free (file->details->metadata);
349 file->details->metadata = NULL((void*)0);
350 }
351}
352
353static GHashTable *
354get_metadata_from_info (GFileInfo *info)
355{
356 GHashTable *metadata;
357 char **attrs;
358 guint id;
359 int i;
360 GFileAttributeType type;
361 gpointer value;
362
363 attrs = g_file_info_list_attributes (info, "metadata");
364
365 metadata = g_hash_table_new (NULL((void*)0), NULL((void*)0));
366
367 for (i = 0; attrs[i] != NULL((void*)0); i++) {
368 id = caja_metadata_get_id (attrs[i] + strlen ("metadata::"));
369 if (id == 0) {
370 continue;
371 }
372
373 if (!g_file_info_get_attribute_data (info, attrs[i],
374 &type, &value, NULL((void*)0))) {
375 continue;
376 }
377
378 if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
379 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
380 g_strdup ((char *)value)g_strdup_inline ((char *)value));
381 } else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) {
382 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
383 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
384 g_strdupv ((char **)value));
385 }
386 }
387
388 g_strfreev (attrs);
389
390 return metadata;
391}
392
393gboolean
394caja_file_update_metadata_from_info (CajaFile *file,
395 GFileInfo *info)
396{
397 gboolean changed = FALSE(0);
398
399 if (g_file_info_has_namespace (info, "metadata")) {
400 GHashTable *metadata;
401
402 metadata = get_metadata_from_info (info);
403 if (!metadata_hash_equal (metadata,
404 file->details->metadata)) {
405 changed = TRUE(!(0));
406 clear_metadata (file);
407 file->details->metadata = metadata;
408 } else {
409 metadata_hash_free (metadata);
410 }
411 } else if (file->details->metadata) {
412 changed = TRUE(!(0));
413 clear_metadata (file);
414 }
415 return changed;
416}
417
418void
419caja_file_clear_info (CajaFile *file)
420{
421 file->details->got_file_info = FALSE(0);
422 if (file->details->get_info_error) {
423 g_error_free (file->details->get_info_error);
424 file->details->get_info_error = NULL((void*)0);
425 }
426 /* Reset to default type, which might be other than unknown for
427 special kinds of files like the desktop or a search directory */
428 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
429
430 if (!file->details->got_custom_display_name) {
431 caja_file_clear_display_name (file);
432 }
433
434 if (!file->details->got_custom_activation_uri &&
435 file->details->activation_uri != NULL((void*)0)) {
436 g_free (file->details->activation_uri);
437 file->details->activation_uri = NULL((void*)0);
438 }
439
440 if (file->details->icon != NULL((void*)0)) {
441 g_object_unref (file->details->icon);
442 file->details->icon = NULL((void*)0);
443 }
444
445 g_free (file->details->thumbnail_path);
446 file->details->thumbnail_path = NULL((void*)0);
447 file->details->thumbnailing_failed = FALSE(0);
448
449 file->details->is_launcher = FALSE(0);
450 file->details->is_foreign_link = FALSE(0);
451 file->details->is_trusted_link = FALSE(0);
452 file->details->is_symlink = FALSE(0);
453 file->details->is_hidden = FALSE(0);
454 file->details->is_backup = FALSE(0);
455 file->details->is_mountpoint = FALSE(0);
456 file->details->uid = -1;
457 file->details->gid = -1;
458 file->details->can_read = TRUE(!(0));
459 file->details->can_write = TRUE(!(0));
460 file->details->can_execute = TRUE(!(0));
461 file->details->can_delete = TRUE(!(0));
462 file->details->can_trash = TRUE(!(0));
463 file->details->can_rename = TRUE(!(0));
464 file->details->can_mount = FALSE(0);
465 file->details->can_unmount = FALSE(0);
466 file->details->can_eject = FALSE(0);
467 file->details->can_start = FALSE(0);
468 file->details->can_start_degraded = FALSE(0);
469 file->details->can_stop = FALSE(0);
470 file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
471 file->details->can_poll_for_media = FALSE(0);
472 file->details->is_media_check_automatic = FALSE(0);
473 file->details->has_permissions = FALSE(0);
474 file->details->permissions = 0;
475 file->details->size = -1;
476 file->details->size_on_disk = -1;
477 file->details->sort_order = 0;
478 file->details->mtime = 0;
479 file->details->atime = 0;
480 file->details->ctime = 0;
481 file->details->btime = 0;
482 file->details->trash_time = 0;
483 g_free (file->details->symlink_name);
484 file->details->symlink_name = NULL((void*)0);
485 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
486 file->details->mime_type = NULL((void*)0);
487 g_free (file->details->selinux_context);
488 file->details->selinux_context = NULL((void*)0);
489 g_free (file->details->description);
490 file->details->description = NULL((void*)0);
491 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
492 file->details->owner = NULL((void*)0);
493 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
494 file->details->owner_real = NULL((void*)0);
495 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
496 file->details->group = NULL((void*)0);
497
498 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
499 file->details->filesystem_id = NULL((void*)0);
500
501 clear_metadata (file);
502}
503
504static CajaFile *
505caja_file_new_from_filename (CajaDirectory *directory,
506 const char *filename,
507 gboolean self_owned)
508{
509 CajaFile *file;
510
511 g_assert (CAJA_IS_DIRECTORY (directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_421
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_421
= 1; else _g_boolean_var_421 = 0; _g_boolean_var_421; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 511, ((const char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"
); } while (0)
;
512 g_assert (filename != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_422
; if (filename != ((void*)0)) _g_boolean_var_422 = 1; else _g_boolean_var_422
= 0; _g_boolean_var_422; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 512, ((const char*) (__func__)
), "filename != NULL"); } while (0)
;
513 g_assert (filename[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_423
; if (filename[0] != '\0') _g_boolean_var_423 = 1; else _g_boolean_var_423
= 0; _g_boolean_var_423; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 513, ((const char*) (__func__)
), "filename[0] != '\\0'"); } while (0)
;
514
515 if (CAJA_IS_DESKTOP_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_desktop_directory_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; }
))))
) {
516 if (self_owned) {
517 file = CAJA_FILE (g_object_new (CAJA_TYPE_DESKTOP_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_desktop_directory_file_get_type
(), ((void*)0)))))))
;
518 } else {
519 /* This doesn't normally happen, unless the user somehow types in a uri
520 * that references a file like this. (See #349840) */
521 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
522 }
523 } else if (CAJA_IS_SEARCH_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_search_directory_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; }
))))
) {
524 if (self_owned) {
525 file = CAJA_FILE (g_object_new (CAJA_TYPE_SEARCH_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_search_directory_file_get_type
(), ((void*)0)))))))
;
526 } else {
527 /* This doesn't normally happen, unless the user somehow types in a uri
528 * that references a file like this. (See #349840) */
529 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
530 }
531 } else if (g_str_has_suffix (filename, CAJA_SAVED_SEARCH_EXTENSION)(__builtin_constant_p (".savedSearch")? __extension__ ({ const
char * const __str = (filename); const char * const __suffix
= (".savedSearch"); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_424; if (__str == ((void
*)0) || __suffix == ((void*)0)) _g_boolean_var_424 = 1; else _g_boolean_var_424
= 0; _g_boolean_var_424; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".savedSearch") )
) {
532 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
533 } else {
534 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
535 }
536
537 file->details->directory = caja_directory_ref (directory);
538
539 file->details->name = g_ref_string_new (filename);
540
541#ifdef CAJA_FILE_DEBUG_REF
542 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
543#endif
544
545 return file;
546}
547
548static void
549modify_link_hash_table (CajaFile *file,
550 ModifyListFunction modify_function)
551{
552 char *target_uri;
553 gboolean found;
554 gpointer original_key;
555 GList **list_ptr;
556
557 /* Check if there is a symlink name. If none, we are OK. */
558 if (file->details->symlink_name == NULL((void*)0) || !caja_file_is_symbolic_link (file)) {
559 return;
560 }
561
562 /* Create the hash table first time through. */
563 if (symbolic_links == NULL((void*)0)) {
564 symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
565 }
566
567 target_uri = caja_file_get_symbolic_link_target_uri (file);
568
569 /* Find the old contents of the hash table. */
570 found = g_hash_table_lookup_extended
571 (symbolic_links, target_uri,
572 &original_key, (gpointer *)&list_ptr);
573 if (!found) {
574 list_ptr = g_new0 (GList *, 1)(GList * *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (GList *); 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
; }))
;
575 original_key = g_strdup (target_uri)g_strdup_inline (target_uri);
576 g_hash_table_insert (symbolic_links, original_key, list_ptr);
577 }
578 (* modify_function) (list_ptr, file);
579 if (*list_ptr == NULL((void*)0)) {
580 g_hash_table_remove (symbolic_links, target_uri);
581 g_free (list_ptr);
582 g_free (original_key);
583 }
584 g_free (target_uri);
585}
586
587static void
588symbolic_link_weak_notify (gpointer data,
589 GObject *where_the_object_was)
590{
591 GList **list = data;
592 /* This really shouldn't happen, but we're seeing some strange things in
593 bug #358172 where the symlink hashtable isn't correctly updated. */
594 *list = g_list_remove (*list, where_the_object_was);
595}
596
597static void
598add_to_link_hash_table_list (GList **list, CajaFile *file)
599{
600 if (g_list_find (*list, file) != NULL((void*)0)) {
601 g_warning ("Adding file to symlink_table multiple times. "
602 "Please add feedback of what you were doing at https://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
603 return;
604 }
605 g_object_weak_ref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
606 *list = g_list_prepend (*list, file);
607}
608
609static void
610add_to_link_hash_table (CajaFile *file)
611{
612 modify_link_hash_table (file, add_to_link_hash_table_list);
613}
614
615static void
616remove_from_link_hash_table_list (GList **list, CajaFile *file)
617{
618 if (g_list_find (*list, file) != NULL((void*)0)) {
619 g_object_weak_unref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
620 *list = g_list_remove (*list, file);
621 }
622}
623
624static void
625remove_from_link_hash_table (CajaFile *file)
626{
627 modify_link_hash_table (file, remove_from_link_hash_table_list);
628}
629
630CajaFile *
631caja_file_new_from_info (CajaDirectory *directory,
632 GFileInfo *info)
633{
634 CajaFile *file;
635 const char *mime_type;
636
637 g_return_val_if_fail (CAJA_IS_DIRECTORY (directory), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_425
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_425
= 1; else _g_boolean_var_425 = 0; _g_boolean_var_425; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"); return
(((void*)0)); } } while (0)
;
638 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_426
; if (info != ((void*)0)) _g_boolean_var_426 = 1; else _g_boolean_var_426
= 0; _g_boolean_var_426; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "info != NULL"); return
(((void*)0)); } } while (0)
;
639
640 mime_type = g_file_info_get_content_type (info);
641 if (mime_type &&
642 strcmp (mime_type, CAJA_SAVED_SEARCH_MIMETYPE"application/x-mate-saved-search") == 0) {
643 g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
644 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
645 } else {
646 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
647 }
648
649 file->details->directory = caja_directory_ref (directory);
650
651 update_info_and_name (file, info);
652
653#ifdef CAJA_FILE_DEBUG_REF
654 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
655#endif
656
657 return file;
658}
659
660static CajaFile *
661caja_file_get_internal (GFile *location, gboolean create)
662{
663 gboolean self_owned;
664 CajaDirectory *directory;
665 CajaFile *file;
666 GFile *parent;
667 char *basename;
668
669 g_assert (location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_427
; if (location != ((void*)0)) _g_boolean_var_427 = 1; else _g_boolean_var_427
= 0; _g_boolean_var_427; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 669, ((const char*) (__func__)
), "location != NULL"); } while (0)
;
670
671 parent = g_file_get_parent (location);
672
673 self_owned = FALSE(0);
674 if (parent == NULL((void*)0)) {
675 self_owned = TRUE(!(0));
676 parent = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
677 }
678
679 /* Get object that represents the directory. */
680 directory = caja_directory_get_internal (parent, create);
681
682 g_object_unref (parent);
683
684 /* Get the name for the file. */
685 if (self_owned && directory != NULL((void*)0)) {
686 basename = caja_directory_get_name_for_self_as_new_file (directory);
687 } else {
688 basename = g_file_get_basename (location);
689 }
690 /* Check to see if it's a file that's already known. */
691 if (directory == NULL((void*)0)) {
692 file = NULL((void*)0);
693 } else if (self_owned) {
694 file = directory->details->as_file;
695 } else {
696 file = caja_directory_find_file_by_name (directory, basename);
697 }
698
699 /* Ref or create the file. */
700 if (file != NULL((void*)0)) {
701 caja_file_ref (file);
702 } else if (create && directory != NULL((void*)0)) {
703 file = caja_file_new_from_filename (directory, basename, self_owned);
704 if (self_owned) {
705 g_assert (directory->details->as_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_428
; if (directory->details->as_file == ((void*)0)) _g_boolean_var_428
= 1; else _g_boolean_var_428 = 0; _g_boolean_var_428; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 705, ((const char*) (__func__)), "directory->details->as_file == NULL"
); } while (0)
;
706 directory->details->as_file = file;
707 } else {
708 caja_directory_add_file (directory, file);
709 }
710 }
711
712 g_free (basename);
713 caja_directory_unref (directory);
714
715 return file;
716}
717
718CajaFile *
719caja_file_get (GFile *location)
720{
721 return caja_file_get_internal (location, TRUE(!(0)));
722}
723
724CajaFile *
725caja_file_get_existing (GFile *location)
726{
727 return caja_file_get_internal (location, FALSE(0));
728}
729
730CajaFile *
731caja_file_get_existing_by_uri (const char *uri)
732{
733 GFile *location;
734 CajaFile *file;
735
736 location = g_file_new_for_uri (uri);
737 file = caja_file_get_internal (location, FALSE(0));
738 g_object_unref (location);
739
740 return file;
741}
742
743CajaFile *
744caja_file_get_by_uri (const char *uri)
745{
746 GFile *location;
747 CajaFile *file;
748
749 location = g_file_new_for_uri (uri);
750 file = caja_file_get_internal (location, TRUE(!(0)));
751 g_object_unref (location);
752
753 return file;
754}
755
756gboolean
757caja_file_is_self_owned (CajaFile *file)
758{
759 return file->details->directory->details->as_file == file;
760}
761
762static void
763finalize (GObject *object)
764{
765 CajaDirectory *directory;
766 CajaFile *file;
767
768 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
769
770 g_assert (file->details->operations_in_progress == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_429
; if (file->details->operations_in_progress == ((void*)
0)) _g_boolean_var_429 = 1; else _g_boolean_var_429 = 0; _g_boolean_var_429
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 770, ((const char*) (__func__)), "file->details->operations_in_progress == NULL"
); } while (0)
;
771
772 if (file->details->is_thumbnailing) {
773 char *uri;
774
775 uri = caja_file_get_uri (file);
776 caja_thumbnail_remove_from_queue (uri);
777 g_free (uri);
778 }
779
780 caja_async_destroying_file (file);
781
782 remove_from_link_hash_table (file);
783
784 directory = file->details->directory;
785
786 if (caja_file_is_self_owned (file)) {
787 directory->details->as_file = NULL((void*)0);
788 } else {
789 if (!file->details->is_gone) {
790 caja_directory_remove_file (directory, file);
791 }
792 }
793
794 if (file->details->get_info_error) {
795 g_error_free (file->details->get_info_error);
796 }
797
798 caja_directory_unref (directory);
799 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
800 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
801 g_free (file->details->display_name_collation_key);
802 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
803 if (file->details->icon) {
804 g_object_unref (file->details->icon);
805 }
806 g_free (file->details->thumbnail_path);
807 g_free (file->details->symlink_name);
808 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
809 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
810 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
811 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
812 g_free (file->details->selinux_context);
813 g_free (file->details->description);
814 g_free (file->details->top_left_text);
815 g_free (file->details->custom_icon);
816 g_free (file->details->activation_uri);
817 g_free (file->details->compare_by_emblem_cache);
818
819 if (file->details->thumbnail) {
820 g_object_unref (file->details->thumbnail);
821 }
822 if (file->details->mount) {
823 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
824 g_object_unref (file->details->mount);
825 }
826
827 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
828
829 g_list_free_full (file->details->mime_list, g_free);
830 g_list_free_full (file->details->pending_extension_emblems, g_free);
831 g_list_free_full (file->details->extension_emblems, g_free);
832 g_list_free_full (file->details->pending_info_providers, g_object_unref);
833
834 if (file->details->pending_extension_attributes) {
835 g_hash_table_destroy (file->details->pending_extension_attributes);
836 }
837
838 if (file->details->extension_attributes) {
839 g_hash_table_destroy (file->details->extension_attributes);
840 }
841
842 if (file->details->metadata) {
843 metadata_hash_free (file->details->metadata);
844 }
845
846 G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->finalize (object);
847}
848
849CajaFile *
850caja_file_ref (CajaFile *file)
851{
852 if (file == NULL((void*)0)) {
853 return NULL((void*)0);
854 }
855 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_430
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_430
= 1; else _g_boolean_var_430 = 0; _g_boolean_var_430; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
856
857#ifdef CAJA_FILE_DEBUG_REF
858 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
859#endif
860
861 return g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
862}
863
864void
865caja_file_unref (CajaFile *file)
866{
867 if (file == NULL((void*)0)) {
868 return;
869 }
870
871 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_431
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_431
= 1; else _g_boolean_var_431 = 0; _g_boolean_var_431; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
872
873#ifdef CAJA_FILE_DEBUG_REF
874 DEBUG_REF_PRINTFprintf("%10p unref'd", file);
875#endif
876
877 g_object_unref (file);
878}
879
880/**
881 * caja_file_get_parent_uri_for_display:
882 *
883 * Get the uri for the parent directory.
884 *
885 * @file: The file in question.
886 *
887 * Return value: A string representing the parent's location,
888 * formatted for user display (including stripping "file://").
889 * If the parent is NULL, returns the empty string.
890 */
891char *
892caja_file_get_parent_uri_for_display (CajaFile *file)
893{
894 GFile *parent;
895 char *result;
896
897 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_432
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_432
= 1; else _g_boolean_var_432 = 0; _g_boolean_var_432; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 897, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
898
899 parent = caja_file_get_parent_location (file);
900 if (parent) {
901 result = g_file_get_parse_name (parent);
902 g_object_unref (parent);
903 } else {
904 result = g_strdup ("")g_strdup_inline ("");
905 }
906
907 return result;
908}
909
910/**
911 * caja_file_get_parent_uri:
912 *
913 * Get the uri for the parent directory.
914 *
915 * @file: The file in question.
916 *
917 * Return value: A string for the parent's location, in "raw URI" form.
918 * Use caja_file_get_parent_uri_for_display instead if the
919 * result is to be displayed on-screen.
920 * If the parent is NULL, returns the empty string.
921 */
922char *
923caja_file_get_parent_uri (CajaFile *file)
924{
925 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_433
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_433
= 1; else _g_boolean_var_433 = 0; _g_boolean_var_433; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 925, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
926
927 if (caja_file_is_self_owned (file)) {
928 /* Callers expect an empty string, not a NULL. */
929 return g_strdup ("")g_strdup_inline ("");
930 }
931
932 return caja_directory_get_uri (file->details->directory);
933}
934
935GFile *
936caja_file_get_parent_location (CajaFile *file)
937{
938 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_434
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_434
= 1; else _g_boolean_var_434 = 0; _g_boolean_var_434; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 938, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
939
940 if (caja_file_is_self_owned (file)) {
941 /* Callers expect an empty string, not a NULL. */
942 return NULL((void*)0);
943 }
944
945 return caja_directory_get_location (file->details->directory);
946}
947
948CajaFile *
949caja_file_get_parent (CajaFile *file)
950{
951 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_435
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_435
= 1; else _g_boolean_var_435 = 0; _g_boolean_var_435; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 951, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
952
953 if (caja_file_is_self_owned (file)) {
954 return NULL((void*)0);
955 }
956
957 return caja_directory_get_corresponding_file (file->details->directory);
958}
959
960/**
961 * caja_file_can_read:
962 *
963 * Check whether the user is allowed to read the contents of this file.
964 *
965 * @file: The file to check.
966 *
967 * Return value: FALSE if the user is definitely not allowed to read
968 * the contents of the file. If the user has read permission, or
969 * the code can't tell whether the user has read permission,
970 * returns TRUE (so failures must always be handled).
971 */
972gboolean
973caja_file_can_read (CajaFile *file)
974{
975 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_436
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_436
= 1; else _g_boolean_var_436 = 0; _g_boolean_var_436; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
976
977 return file->details->can_read;
978}
979
980/**
981 * caja_file_can_write:
982 *
983 * Check whether the user is allowed to write to this file.
984 *
985 * @file: The file to check.
986 *
987 * Return value: FALSE if the user is definitely not allowed to write
988 * to the file. If the user has write permission, or
989 * the code can't tell whether the user has write permission,
990 * returns TRUE (so failures must always be handled).
991 */
992gboolean
993caja_file_can_write (CajaFile *file)
994{
995 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_437
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_437
= 1; else _g_boolean_var_437 = 0; _g_boolean_var_437; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
996
997 return file->details->can_write;
998}
999
1000/**
1001 * caja_file_can_execute:
1002 *
1003 * Check whether the user is allowed to execute this file.
1004 *
1005 * @file: The file to check.
1006 *
1007 * Return value: FALSE if the user is definitely not allowed to execute
1008 * the file. If the user has execute permission, or
1009 * the code can't tell whether the user has execute permission,
1010 * returns TRUE (so failures must always be handled).
1011 */
1012gboolean
1013caja_file_can_execute (CajaFile *file)
1014{
1015 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_438
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_438
= 1; else _g_boolean_var_438 = 0; _g_boolean_var_438; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1016
1017 return file->details->can_execute;
1018}
1019
1020gboolean
1021caja_file_can_mount (CajaFile *file)
1022{
1023 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_439
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_439
= 1; else _g_boolean_var_439 = 0; _g_boolean_var_439; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1024
1025 return file->details->can_mount;
1026}
1027
1028gboolean
1029caja_file_can_unmount (CajaFile *file)
1030{
1031 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_440
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_440
= 1; else _g_boolean_var_440 = 0; _g_boolean_var_440; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1032
1033 return file->details->can_unmount ||
1034 (file->details->mount != NULL((void*)0) &&
1035 g_mount_can_unmount (file->details->mount));
1036}
1037
1038gboolean
1039caja_file_can_eject (CajaFile *file)
1040{
1041 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_441
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_441
= 1; else _g_boolean_var_441 = 0; _g_boolean_var_441; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1042
1043 return file->details->can_eject ||
1044 (file->details->mount != NULL((void*)0) &&
1045 g_mount_can_eject (file->details->mount));
1046}
1047
1048gboolean
1049caja_file_can_start (CajaFile *file)
1050{
1051 gboolean ret;
1052 GDrive *drive;
1053
1054 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_442
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_442
= 1; else _g_boolean_var_442 = 0; _g_boolean_var_442; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1055
1056 ret = FALSE(0);
1057
1058 if (file->details->can_start) {
1059 ret = TRUE(!(0));
1060 goto out;
1061 }
1062
1063 if (file->details->mount != NULL((void*)0)) {
1064 drive = g_mount_get_drive (file->details->mount);
1065 if (drive != NULL((void*)0)) {
1066 ret = g_drive_can_start (drive);
1067 g_object_unref (drive);
1068 }
1069 }
1070
1071 out:
1072 return ret;
1073}
1074
1075gboolean
1076caja_file_can_start_degraded (CajaFile *file)
1077{
1078 gboolean ret;
1079 GDrive *drive;
1080
1081 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_443
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_443
= 1; else _g_boolean_var_443 = 0; _g_boolean_var_443; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1082
1083 ret = FALSE(0);
1084
1085 if (file->details->can_start_degraded) {
1086 ret = TRUE(!(0));
1087 goto out;
1088 }
1089
1090 if (file->details->mount != NULL((void*)0)) {
1091 drive = g_mount_get_drive (file->details->mount);
1092 if (drive != NULL((void*)0)) {
1093 ret = g_drive_can_start_degraded (drive);
1094 g_object_unref (drive);
1095 }
1096 }
1097
1098 out:
1099 return ret;
1100}
1101
1102gboolean
1103caja_file_can_poll_for_media (CajaFile *file)
1104{
1105 gboolean ret;
1106 GDrive *drive;
1107
1108 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_444
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_444
= 1; else _g_boolean_var_444 = 0; _g_boolean_var_444; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1109
1110 ret = FALSE(0);
1111
1112 if (file->details->can_poll_for_media) {
1113 ret = TRUE(!(0));
1114 goto out;
1115 }
1116
1117 if (file->details->mount != NULL((void*)0)) {
1118 drive = g_mount_get_drive (file->details->mount);
1119 if (drive != NULL((void*)0)) {
1120 ret = g_drive_can_poll_for_media (drive);
1121 g_object_unref (drive);
1122 }
1123 }
1124
1125 out:
1126 return ret;
1127}
1128
1129gboolean
1130caja_file_is_media_check_automatic (CajaFile *file)
1131{
1132 gboolean ret;
1133 GDrive *drive;
1134
1135 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_445
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_445
= 1; else _g_boolean_var_445 = 0; _g_boolean_var_445; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1136
1137 ret = FALSE(0);
1138
1139 if (file->details->is_media_check_automatic) {
1140 ret = TRUE(!(0));
1141 goto out;
1142 }
1143
1144 if (file->details->mount != NULL((void*)0)) {
1145 drive = g_mount_get_drive (file->details->mount);
1146 if (drive != NULL((void*)0)) {
1147 ret = g_drive_is_media_check_automatic (drive);
1148 g_object_unref (drive);
1149 }
1150 }
1151
1152 out:
1153 return ret;
1154}
1155
1156
1157gboolean
1158caja_file_can_stop (CajaFile *file)
1159{
1160 gboolean ret;
1161 GDrive *drive;
1162
1163 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_446
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_446
= 1; else _g_boolean_var_446 = 0; _g_boolean_var_446; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1164
1165 ret = FALSE(0);
1166
1167 if (file->details->can_stop) {
1168 ret = TRUE(!(0));
1169 goto out;
1170 }
1171
1172 if (file->details->mount != NULL((void*)0)) {
1173 drive = g_mount_get_drive (file->details->mount);
1174 if (drive != NULL((void*)0)) {
1175 ret = g_drive_can_stop (drive);
1176 g_object_unref (drive);
1177 }
1178 }
1179
1180 out:
1181 return ret;
1182}
1183
1184GDriveStartStopType
1185caja_file_get_start_stop_type (CajaFile *file)
1186{
1187 GDriveStartStopType ret;
1188 GDrive *drive;
1189
1190 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_447
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_447
= 1; else _g_boolean_var_447 = 0; _g_boolean_var_447; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1191
1192 ret = G_DRIVE_START_STOP_TYPE_UNKNOWN;
1193
1194 ret = file->details->start_stop_type;
1195 if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1196 goto out;
1197
1198 if (file->details->mount != NULL((void*)0)) {
1199 drive = g_mount_get_drive (file->details->mount);
1200 if (drive != NULL((void*)0)) {
1201 ret = g_drive_get_start_stop_type (drive);
1202 g_object_unref (drive);
1203 }
1204 }
1205
1206 out:
1207 return ret;
1208}
1209
1210void
1211caja_file_mount (CajaFile *file,
1212 GMountOperation *mount_op,
1213 GCancellable *cancellable,
1214 CajaFileOperationCallback callback,
1215 gpointer callback_data)
1216{
1217 GError *error;
1218
1219 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount == NULL((void*)0)) {
1220 if (callback) {
1221 error = NULL((void*)0);
1222 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1223 _("This file cannot be mounted")dcgettext (((void*)0), "This file cannot be mounted", 5));
1224 callback (file, NULL((void*)0), error, callback_data);
1225 g_error_free (error);
1226 }
1227 } else {
1228 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount (file, mount_op, cancellable, callback, callback_data);
1229 }
1230}
1231
1232typedef struct {
1233 CajaFile *file;
1234 CajaFileOperationCallback callback;
1235 gpointer callback_data;
1236} UnmountData;
1237
1238static void
1239unmount_done (void *callback_data)
1240{
1241 UnmountData *data;
1242
1243 data = (UnmountData *)callback_data;
1244 if (data->callback) {
1245 data->callback (data->file, NULL((void*)0), NULL((void*)0), data->callback_data);
1246 }
1247 caja_file_unref (data->file);
1248 g_free (data);
1249}
1250
1251void
1252caja_file_unmount (CajaFile *file,
1253 GMountOperation *mount_op,
1254 GCancellable *cancellable,
1255 CajaFileOperationCallback callback,
1256 gpointer callback_data)
1257{
1258 GError *error;
1259 UnmountData *data;
1260
1261 if (file->details->can_unmount) {
1262 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount != NULL((void*)0)) {
1263 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount (file, mount_op, cancellable, callback, callback_data);
1264 } else {
1265 if (callback) {
1266 error = NULL((void*)0);
1267 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1268 _("This file cannot be unmounted")dcgettext (((void*)0), "This file cannot be unmounted", 5));
1269 callback (file, NULL((void*)0), error, callback_data);
1270 g_error_free (error);
1271 }
1272 }
1273 } else if (file->details->mount != NULL((void*)0) &&
1274 g_mount_can_unmount (file->details->mount)) {
1275 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1276 data->file = caja_file_ref (file);
1277 data->callback = callback;
1278 data->callback_data = callback_data;
1279 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, FALSE(0), TRUE(!(0)), unmount_done, data);
1280 } else if (callback) {
1281 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1282 }
1283}
1284
1285void
1286caja_file_eject (CajaFile *file,
1287 GMountOperation *mount_op,
1288 GCancellable *cancellable,
1289 CajaFileOperationCallback callback,
1290 gpointer callback_data)
1291{
1292 GError *error;
1293 UnmountData *data;
1294
1295 if (file->details->can_eject) {
1296 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject != NULL((void*)0)) {
1297 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject (file, mount_op, cancellable, callback, callback_data);
1298 } else {
1299 if (callback) {
1300 error = NULL((void*)0);
1301 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1302 _("This file cannot be ejected")dcgettext (((void*)0), "This file cannot be ejected", 5));
1303 callback (file, NULL((void*)0), error, callback_data);
1304 g_error_free (error);
1305 }
1306 }
1307 } else if (file->details->mount != NULL((void*)0) &&
1308 g_mount_can_eject (file->details->mount)) {
1309 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1310 data->file = caja_file_ref (file);
1311 data->callback = callback;
1312 data->callback_data = callback_data;
1313 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, TRUE(!(0)), TRUE(!(0)), unmount_done, data);
1314 } else if (callback) {
1315 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1316 }
1317}
1318
1319void
1320caja_file_start (CajaFile *file,
1321 GMountOperation *start_op,
1322 GCancellable *cancellable,
1323 CajaFileOperationCallback callback,
1324 gpointer callback_data)
1325{
1326 GError *error;
1327
1328 if ((file->details->can_start || file->details->can_start_degraded) &&
1329 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start != NULL((void*)0)) {
1330 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start (file, start_op, cancellable, callback, callback_data);
1331 } else {
1332 if (callback) {
1333 error = NULL((void*)0);
1334 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1335 _("This file cannot be started")dcgettext (((void*)0), "This file cannot be started", 5));
1336 callback (file, NULL((void*)0), error, callback_data);
1337 g_error_free (error);
1338 }
1339 }
1340}
1341
1342static void
1343file_stop_callback (GObject *source_object,
1344 GAsyncResult *res,
1345 gpointer callback_data)
1346{
1347 CajaFileOperation *op;
1348 gboolean stopped;
1349 GError *error;
1350
1351 op = callback_data;
1352
1353 error = NULL((void*)0);
1354 stopped = g_drive_stop_finish (G_DRIVE (source_object)((((GDrive*) (void *) ((source_object))))),
1355 res, &error);
1356
1357 if (!stopped &&
1358 error->domain == G_IO_ERRORg_io_error_quark() &&
1359 (error->code == G_IO_ERROR_FAILED_HANDLED ||
1360 error->code == G_IO_ERROR_CANCELLED)) {
1361 g_error_free (error);
1362 error = NULL((void*)0);
1363 }
1364
1365 caja_file_operation_complete (op, NULL((void*)0), error);
1366 if (error) {
1367 g_error_free (error);
1368 }
1369}
1370
1371void
1372caja_file_stop (CajaFile *file,
1373 GMountOperation *mount_op,
1374 GCancellable *cancellable,
1375 CajaFileOperationCallback callback,
1376 gpointer callback_data)
1377{
1378 GError *error;
1379
1380 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1381 if (file->details->can_stop) {
1382 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop (file, mount_op, cancellable, callback, callback_data);
1383 } else {
1384 if (callback) {
1385 error = NULL((void*)0);
1386 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1387 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1388 callback (file, NULL((void*)0), error, callback_data);
1389 g_error_free (error);
1390 }
1391 }
1392 } else {
1393 GDrive *drive;
1394
1395 drive = NULL((void*)0);
1396 if (file->details->mount != NULL((void*)0))
1397 drive = g_mount_get_drive (file->details->mount);
1398
1399 if (drive != NULL((void*)0) && g_drive_can_stop (drive)) {
1400 CajaFileOperation *op;
1401
1402 op = caja_file_operation_new (file, callback, callback_data);
1403 if (cancellable) {
1404 g_object_unref (op->cancellable);
1405 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
1406 }
1407
1408 g_drive_stop (drive,
1409 G_MOUNT_UNMOUNT_NONE,
1410 mount_op,
1411 op->cancellable,
1412 file_stop_callback,
1413 op);
1414 } else {
1415 if (callback) {
1416 error = NULL((void*)0);
1417 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1418 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1419 callback (file, NULL((void*)0), error, callback_data);
1420 g_error_free (error);
1421 }
1422 }
1423
1424 if (drive != NULL((void*)0)) {
1425 g_object_unref (drive);
1426 }
1427 }
1428}
1429
1430void
1431caja_file_poll_for_media (CajaFile *file)
1432{
1433 if (file->details->can_poll_for_media) {
1434 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1435 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->poll_for_media (file);
1436 }
1437 } else if (file->details->mount != NULL((void*)0)) {
1438 GDrive *drive;
1439 drive = g_mount_get_drive (file->details->mount);
1440 if (drive != NULL((void*)0)) {
1441 g_drive_poll_for_media (drive,
1442 NULL((void*)0), /* cancellable */
1443 NULL((void*)0), /* GAsyncReadyCallback */
1444 NULL((void*)0)); /* user_data */
1445 g_object_unref (drive);
1446 }
1447 }
1448}
1449
1450/**
1451 * caja_file_is_desktop_directory:
1452 *
1453 * Check whether this file is the desktop directory.
1454 *
1455 * @file: The file to check.
1456 *
1457 * Return value: TRUE if this is the physical desktop directory.
1458 */
1459gboolean
1460caja_file_is_desktop_directory (CajaFile *file)
1461{
1462 GFile *dir;
1463
1464 dir = file->details->directory->details->location;
1465
1466 if (dir == NULL((void*)0)) {
1467 return FALSE(0);
1468 }
1469
1470 return caja_is_desktop_directory_file (dir, file->details->name);
1471}
1472
1473static gboolean
1474is_desktop_file (CajaFile *file)
1475{
1476 return caja_file_is_mime_type (file, "application/x-desktop");
1477}
1478
1479static gboolean
1480can_rename_desktop_file (CajaFile *file)
1481{
1482 GFile *location;
1483 gboolean res;
1484
1485 location = caja_file_get_location (file);
1486 res = g_file_is_native (location);
1487 g_object_unref (location);
1488 return res;
1489}
1490
1491/**
1492 * caja_file_can_rename:
1493 *
1494 * Check whether the user is allowed to change the name of the file.
1495 *
1496 * @file: The file to check.
1497 *
1498 * Return value: FALSE if the user is definitely not allowed to change
1499 * the name of the file. If the user is allowed to change the name, or
1500 * the code can't tell whether the user is allowed to change the name,
1501 * returns TRUE (so rename failures must always be handled).
1502 */
1503gboolean
1504caja_file_can_rename (CajaFile *file)
1505{
1506 gboolean can_rename;
1507
1508 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_448
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_448
= 1; else _g_boolean_var_448 = 0; _g_boolean_var_448; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1509
1510 /* Nonexistent files can't be renamed. */
1511 if (caja_file_is_gone (file)) {
1512 return FALSE(0);
1513 }
1514
1515 /* Self-owned files can't be renamed */
1516 if (caja_file_is_self_owned (file)) {
1517 return FALSE(0);
1518 }
1519
1520 if ((is_desktop_file (file) && !can_rename_desktop_file (file)) ||
1521 caja_file_is_home (file)) {
1522 return FALSE(0);
1523 }
1524
1525 can_rename = TRUE(!(0));
1526
1527 /* Certain types of links can't be renamed */
1528 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1529 CajaDesktopLink *link;
1530
1531 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1532
1533 if (link != NULL((void*)0)) {
1534 can_rename = caja_desktop_link_can_rename (link);
1535 g_object_unref (link);
1536 }
1537 }
1538
1539 if (!can_rename) {
1540 return FALSE(0);
1541 }
1542
1543 return file->details->can_rename;
1544}
1545
1546gboolean
1547caja_file_can_delete (CajaFile *file)
1548{
1549 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_449
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_449
= 1; else _g_boolean_var_449 = 0; _g_boolean_var_449; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1550
1551 /* Nonexistent files can't be deleted. */
1552 if (caja_file_is_gone (file)) {
1553 return FALSE(0);
1554 }
1555
1556 /* Self-owned files can't be deleted */
1557 if (caja_file_is_self_owned (file)) {
1558 return FALSE(0);
1559 }
1560
1561 return file->details->can_delete;
1562}
1563
1564gboolean
1565caja_file_can_trash (CajaFile *file)
1566{
1567 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_450
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_450
= 1; else _g_boolean_var_450 = 0; _g_boolean_var_450; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1568
1569 /* Nonexistent files can't be deleted. */
1570 if (caja_file_is_gone (file)) {
1571 return FALSE(0);
1572 }
1573
1574 /* Self-owned files can't be deleted */
1575 if (caja_file_is_self_owned (file)) {
1576 return FALSE(0);
1577 }
1578
1579 return file->details->can_trash;
1580}
1581
1582GFile *
1583caja_file_get_location (CajaFile *file)
1584{
1585 GFile *dir;
1586
1587 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_451
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_451
= 1; else _g_boolean_var_451 = 0; _g_boolean_var_451; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1588
1589 dir = file->details->directory->details->location;
1590
1591 if (caja_file_is_self_owned (file)) {
1592 return g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir));
1593 }
1594
1595 return g_file_get_child (dir, file->details->name);
1596}
1597
1598/* Return the actual uri associated with the passed-in file. */
1599char *
1600caja_file_get_uri (CajaFile *file)
1601{
1602 char *uri;
1603 GFile *loc;
1604
1605 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_452
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_452
= 1; else _g_boolean_var_452 = 0; _g_boolean_var_452; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1606
1607 loc = caja_file_get_location (file);
1608 uri = g_file_get_uri (loc);
1609 g_object_unref (loc);
1610
1611 return uri;
1612}
1613
1614char *
1615caja_file_get_uri_scheme (CajaFile *file)
1616{
1617 GFile *loc;
1618 char *scheme;
1619
1620 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_453
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_453
= 1; else _g_boolean_var_453 = 0; _g_boolean_var_453; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1621
1622 if (file->details->directory == NULL((void*)0) ||
1623 file->details->directory->details->location == NULL((void*)0)) {
1624 return NULL((void*)0);
1625 }
1626
1627 loc = caja_directory_get_location (file->details->directory);
1628 scheme = g_file_get_uri_scheme (loc);
1629 g_object_unref (loc);
1630
1631 return scheme;
1632}
1633
1634CajaFileOperation *
1635caja_file_operation_new (CajaFile *file,
1636 CajaFileOperationCallback callback,
1637 gpointer callback_data)
1638{
1639 CajaFileOperation *op;
1640
1641 op = g_new0 (CajaFileOperation, 1)(CajaFileOperation *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (CajaFileOperation); 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; }))
;
1642 op->file = caja_file_ref (file);
1643 op->callback = callback;
1644 op->callback_data = callback_data;
1645 op->cancellable = g_cancellable_new ();
1646
1647 op->file->details->operations_in_progress = g_list_prepend
1648 (op->file->details->operations_in_progress, op);
1649
1650 return op;
1651}
1652
1653static void
1654caja_file_operation_remove (CajaFileOperation *op)
1655{
1656 op->file->details->operations_in_progress = g_list_remove
1657 (op->file->details->operations_in_progress, op);
1658}
1659
1660void
1661caja_file_operation_free (CajaFileOperation *op)
1662{
1663 caja_file_operation_remove (op);
1664 caja_file_unref (op->file);
1665 g_object_unref (op->cancellable);
1666 if (op->free_data) {
1667 op->free_data (op->data);
1668 }
1669 // Start UNDO-REDO
1670 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1671 op->undo_redo_data);
1672 // End UNDO-REDO
1673 g_free (op);
1674}
1675
1676void
1677caja_file_operation_complete (CajaFileOperation *op, GFile *result_file, GError *error)
1678{
1679 /* Claim that something changed even if the operation failed.
1680 * This makes it easier for some clients who see the "reverting"
1681 * as "changing back".
1682 */
1683 caja_file_operation_remove (op);
1684 caja_file_changed (op->file);
1685 if (op->callback) {
1686 (* op->callback) (op->file, result_file, error, op->callback_data);
1687 }
1688 caja_file_operation_free (op);
1689}
1690
1691void
1692caja_file_operation_cancel (CajaFileOperation *op)
1693{
1694 /* Cancel the operation if it's still in progress. */
1695 g_cancellable_cancel (op->cancellable);
1696}
1697
1698static void
1699rename_get_info_callback (GObject *source_object,
1700 GAsyncResult *res,
1701 gpointer callback_data)
1702{
1703 CajaFileOperation *op;
1704 GFileInfo *new_info;
1705 GError *error;
1706
1707 op = callback_data;
1708
1709 error = NULL((void*)0);
1710 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
1711 if (new_info != NULL((void*)0)) {
1712 CajaDirectory *directory;
1713 CajaFile *existing_file;
1714 char *old_name;
1715 char *old_uri;
1716 char *new_uri;
1717 const char *new_name;
1718
1719 directory = op->file->details->directory;
1720
1721 new_name = g_file_info_get_name (new_info);
1722
1723 /* If there was another file by the same name in this
1724 * directory, mark it gone.
1725 */
1726 existing_file = caja_directory_find_file_by_name (directory, new_name);
1727 if (existing_file != NULL((void*)0)) {
1728 caja_file_mark_gone (existing_file);
1729 caja_file_changed (existing_file);
1730 }
1731
1732 old_uri = caja_file_get_uri (op->file);
1733 old_name = g_strdup (op->file->details->name)g_strdup_inline (op->file->details->name);
1734
1735 update_info_and_name (op->file, new_info);
1736
1737 g_free (old_name);
1738
1739 new_uri = caja_file_get_uri (op->file);
1740 caja_directory_moved (old_uri, new_uri);
1741 g_free (new_uri);
1742 g_free (old_uri);
1743
1744 /* the rename could have affected the display name if e.g.
1745 * we're in a vfolder where the name comes from a desktop file
1746 * and a rename affects the contents of the desktop file.
1747 */
1748 if (op->file->details->got_custom_display_name) {
1749 caja_file_invalidate_attributes (op->file,
1750 CAJA_FILE_ATTRIBUTE_INFO |
1751 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1752 }
1753
1754 g_object_unref (new_info);
1755 }
1756 caja_file_operation_complete (op, NULL((void*)0), error);
1757 if (error) {
1758 g_error_free (error);
1759 }
1760}
1761
1762static void
1763rename_callback (GObject *source_object,
1764 GAsyncResult *res,
1765 gpointer callback_data)
1766{
1767 CajaFileOperation *op;
1768 GFile *new_file;
1769 GError *error;
1770
1771 op = callback_data;
1772
1773 error = NULL((void*)0);
1774 new_file = g_file_set_display_name_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
1775 res, &error);
1776
1777 if (new_file != NULL((void*)0)) {
1778 // Start UNDO-REDO
1779 caja_undostack_manager_data_set_rename_information(op->undo_redo_data, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), new_file);
1780 // End UNDO-REDO
1781 g_file_query_info_async (new_file,
1782 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
1783 0,
1784 G_PRIORITY_DEFAULT0,
1785 op->cancellable,
1786 rename_get_info_callback, op);
1787 } else {
1788 caja_file_operation_complete (op, NULL((void*)0), error);
1789 g_error_free (error);
1790 }
1791}
1792
1793static gboolean
1794name_is (CajaFile *file, const char *new_name)
1795{
1796 const char *old_name;
1797 old_name = file->details->name;
1798 return strcmp (new_name, old_name) == 0;
1799}
1800
1801void
1802caja_file_rename (CajaFile *file,
1803 const char *new_name,
1804 CajaFileOperationCallback callback,
1805 gpointer callback_data)
1806{
1807 CajaFileOperation *op;
1808 char *old_name;
1809 char *new_file_name;
1810 gboolean success, name_changed;
1811 gboolean is_renameable_desktop_file;
1812 GFile *location;
1813 GError *error;
1814
1815 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_454
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_454
= 1; else _g_boolean_var_454 = 0; _g_boolean_var_454; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
1816 g_return_if_fail (new_name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_455
; if (new_name != ((void*)0)) _g_boolean_var_455 = 1; else _g_boolean_var_455
= 0; _g_boolean_var_455; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "new_name != NULL"
); return; } } while (0)
;
1817 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_456
; if (callback != ((void*)0)) _g_boolean_var_456 = 1; else _g_boolean_var_456
= 0; _g_boolean_var_456; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
1818
1819 is_renameable_desktop_file =
1820 is_desktop_file (file) && can_rename_desktop_file (file);
1821
1822 /* Return an error for incoming names containing path separators.
1823 * But not for .desktop files as '/' are allowed for them */
1824 if (strstr (new_name, "/") != NULL((void*)0) && !is_renameable_desktop_file) {
1825 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
1826 _("Slashes are not allowed in filenames")dcgettext (((void*)0), "Slashes are not allowed in filenames"
, 5)
);
1827 (* callback) (file, NULL((void*)0), error, callback_data);
1828 g_error_free (error);
1829 return;
1830 }
1831
1832 /* Can't rename a file that's already gone.
1833 * We need to check this here because there may be a new
1834 * file with the same name.
1835 */
1836 if (caja_file_is_gone (file)) {
1837 /* Claim that something changed even if the rename
1838 * failed. This makes it easier for some clients who
1839 * see the "reverting" to the old name as "changing
1840 * back".
1841 */
1842 caja_file_changed (file);
1843 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_FOUND,
1844 _("File not found")dcgettext (((void*)0), "File not found", 5));
1845 (* callback) (file, NULL((void*)0), error, callback_data);
1846 g_error_free (error);
1847 return;
1848 }
1849
1850 /* Test the name-hasn't-changed case explicitly, for two reasons.
1851 * (1) rename returns an error if new & old are same.
1852 * (2) We don't want to send file-changed signal if nothing changed.
1853 */
1854 if (!CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
&&
1855 !is_renameable_desktop_file &&
1856 name_is (file, new_name)) {
1857 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1858 return;
1859 }
1860
1861 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1862 * case before this case.
1863 */
1864 if (caja_file_is_self_owned (file)) {
1865 /* Claim that something changed even if the rename
1866 * failed. This makes it easier for some clients who
1867 * see the "reverting" to the old name as "changing
1868 * back".
1869 */
1870 caja_file_changed (file);
1871 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1872 _("Toplevel files cannot be renamed")dcgettext (((void*)0), "Toplevel files cannot be renamed", 5));
1873
1874 (* callback) (file, NULL((void*)0), error, callback_data);
1875 g_error_free (error);
1876 return;
1877 }
1878
1879 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1880 CajaDesktopLink *link;
1881
1882 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1883 old_name = caja_file_get_display_name (file);
1884
1885 if ((old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0)) {
1886 success = TRUE(!(0));
1887 } else {
1888 success = (link != NULL((void*)0) && caja_desktop_link_rename (link, new_name));
1889 }
1890
1891 if (success) {
1892 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1893 } else {
1894 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1895 _("Unable to rename desktop icon")dcgettext (((void*)0), "Unable to rename desktop icon", 5));
1896 (* callback) (file, NULL((void*)0), error, callback_data);
1897 g_error_free (error);
1898 }
1899
1900 g_free (old_name);
1901 g_object_unref (link);
1902 return;
1903 }
1904
1905 if (is_renameable_desktop_file) {
1906 char *uri;
1907
1908 /* Don't actually change the name if the new name is the same.
1909 * This helps for the vfolder method where this can happen and
1910 * we want to minimize actual changes
1911 */
1912 uri = caja_file_get_uri (file);
1913 old_name = caja_link_local_get_text (uri);
1914 if (old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0) {
1915 success = TRUE(!(0));
1916 name_changed = FALSE(0);
1917 } else {
1918 success = caja_link_local_set_text (uri, new_name);
1919 name_changed = TRUE(!(0));
1920 }
1921 g_free (old_name);
1922 g_free (uri);
1923
1924 if (!success) {
1925 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1926 _("Unable to rename desktop file")dcgettext (((void*)0), "Unable to rename desktop file", 5));
1927 (* callback) (file, NULL((void*)0), error, callback_data);
1928 g_error_free (error);
1929 return;
1930 }
1931 if (!g_str_has_suffix(new_name, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (new_name); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_457; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_457 = 1; else _g_boolean_var_457
= 0; _g_boolean_var_457; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (new_name, ".desktop") )
)
1932 new_file_name = g_strdup_printf ("%s.desktop", new_name);
1933 else
1934 new_file_name = g_strdup_printf("%s", new_name);
1935 new_file_name = g_strdelimit (new_file_name, "/", '-');
1936
1937 if (name_is (file, new_file_name)) {
1938 if (name_changed) {
1939 caja_file_invalidate_attributes (file,
1940 CAJA_FILE_ATTRIBUTE_INFO |
1941 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1942 }
1943
1944 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1945 g_free (new_file_name);
1946 return;
1947 }
1948 } else {
1949 new_file_name = g_strdup (new_name)g_strdup_inline (new_name);
1950 }
1951
1952 /* Set up a renaming operation. */
1953 op = caja_file_operation_new (file, callback, callback_data);
1954 op->is_rename = TRUE(!(0));
1955
1956 /* Do the renaming. */
1957
1958 location = caja_file_get_location (file);
1959
1960 // Start UNDO-REDO
1961 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
1962 op->undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RENAME, 1);
1963 }
1964 // End UNDO-REDO
1965
1966 g_file_set_display_name_async (location,
1967 new_file_name,
1968 G_PRIORITY_DEFAULT0,
1969 op->cancellable,
1970 rename_callback,
1971 op);
1972 g_free (new_file_name);
1973 g_object_unref (location);
1974}
1975
1976gboolean
1977caja_file_rename_in_progress (CajaFile *file)
1978{
1979 GList *node;
1980 CajaFileOperation *op = NULL((void*)0);
1981
1982 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = node->next) {
1983 op = node->data;
1984 if (op->is_rename) {
1985 return TRUE(!(0));
1986 }
1987 }
1988 return FALSE(0);
1989}
1990
1991void
1992caja_file_cancel (CajaFile *file,
1993 CajaFileOperationCallback callback,
1994 gpointer callback_data)
1995{
1996 GList *node, *next;
1997 CajaFileOperation *op = NULL((void*)0);
1998
1999 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = next) {
2000 next = node->next;
2001 op = node->data;
2002
2003 g_assert (op->file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_458
; if (op->file == file) _g_boolean_var_458 = 1; else _g_boolean_var_458
= 0; _g_boolean_var_458; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2003, ((const char*) (__func__
)), "op->file == file"); } while (0)
;
2004 if (op->callback == callback && op->callback_data == callback_data) {
2005 caja_file_operation_cancel (op);
2006 }
2007 }
2008}
2009
2010gboolean
2011caja_file_matches_uri (CajaFile *file, const char *match_uri)
2012{
2013 GFile *match_file, *location;
2014 gboolean result;
2015
2016 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_459
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_459
= 1; else _g_boolean_var_459 = 0; _g_boolean_var_459; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2017 g_return_val_if_fail (match_uri != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_460
; if (match_uri != ((void*)0)) _g_boolean_var_460 = 1; else _g_boolean_var_460
= 0; _g_boolean_var_460; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "match_uri != NULL"
); return ((0)); } } while (0)
;
2018
2019 location = caja_file_get_location (file);
2020 match_file = g_file_new_for_uri (match_uri);
2021 result = g_file_equal (location, match_file);
2022 g_object_unref (location);
2023 g_object_unref (match_file);
2024
2025 return result;
2026}
2027
2028int
2029caja_file_compare_location (CajaFile *file_1,
2030 CajaFile *file_2)
2031{
2032 GFile *loc_a, *loc_b;
2033 gboolean res;
2034
2035 loc_a = caja_file_get_location (file_1);
2036 loc_b = caja_file_get_location (file_2);
2037
2038 res = !g_file_equal (loc_a, loc_b);
2039
2040 g_object_unref (loc_a);
2041 g_object_unref (loc_b);
2042
2043 return (gint) res;
2044}
2045
2046gboolean
2047caja_file_is_local (CajaFile *file)
2048{
2049 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_461
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_461
= 1; else _g_boolean_var_461 = 0; _g_boolean_var_461; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2050
2051 return caja_directory_is_local (file->details->directory);
2052}
2053
2054static void
2055update_link (CajaFile *link_file, CajaFile *target_file)
2056{
2057 g_assert (CAJA_IS_FILE (link_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_462
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((link_file)); GType __t = (caja_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_462
= 1; else _g_boolean_var_462 = 0; _g_boolean_var_462; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2057, ((const char*) (__func__)), "CAJA_IS_FILE (link_file)"
); } while (0)
;
2058 g_assert (CAJA_IS_FILE (target_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_463
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_file)); GType __t = (caja_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_463
= 1; else _g_boolean_var_463 = 0; _g_boolean_var_463; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2058, ((const char*) (__func__)), "CAJA_IS_FILE (target_file)"
); } while (0)
;
2059
2060 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
2061 * here then the hash table is a waste of time.
2062 */
2063}
2064
2065static GList *
2066get_link_files (CajaFile *target_file)
2067{
2068 GList **link_files;
2069
2070 if (symbolic_links == NULL((void*)0)) {
2071 link_files = NULL((void*)0);
2072 } else {
2073 char *uri;
2074
2075 uri = caja_file_get_uri (target_file);
2076 link_files = g_hash_table_lookup (symbolic_links, uri);
2077 g_free (uri);
2078 }
2079 if (link_files) {
2080 return caja_file_list_copy (*link_files);
2081 }
2082 return NULL((void*)0);
2083}
2084
2085static void
2086update_links_if_target (CajaFile *target_file)
2087{
2088 GList *link_files, *p;
2089
2090 link_files = get_link_files (target_file);
2091 for (p = link_files; p != NULL((void*)0); p = p->next) {
2092 update_link (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))), target_file);
2093 }
2094 caja_file_list_free (link_files);
2095}
2096
2097static gboolean
2098update_info_internal (CajaFile *file,
2099 GFileInfo *info,
2100 gboolean update_name)
2101{
2102 gboolean changed;
2103 gboolean is_symlink, is_hidden, is_backup, is_mountpoint;
2104 gboolean has_permissions;
2105 guint32 permissions;
2106 gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2107 gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2108 GDriveStartStopType start_stop_type;
2109 gboolean thumbnailing_failed;
2110 int uid, gid;
2111 goffset size;
2112 goffset size_on_disk;
2113 int sort_order;
2114 time_t atime, mtime, ctime, btime;
2115 time_t trash_time;
2116 const char * time_string;
2117 const char *symlink_name, *mime_type, *selinux_context, *thumbnail_path;
2118 GFileType file_type;
2119 GIcon *icon;
2120 const char *description;
2121 const char *filesystem_id;
2122 const char *trash_orig_path;
2123 const char *group, *owner, *owner_real;
2124 gboolean free_owner, free_group;
2125
2126 if (file->details->is_gone) {
2127 return FALSE(0);
2128 }
2129
2130 if (info == NULL((void*)0)) {
2131 caja_file_mark_gone (file);
2132 return TRUE(!(0));
2133 }
2134
2135 file->details->file_info_is_up_to_date = TRUE(!(0));
2136
2137 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2138 * point to the old name know that the file has been renamed.
2139 */
2140
2141 remove_from_link_hash_table (file);
2142
2143 changed = FALSE(0);
2144
2145 if (!file->details->got_file_info) {
2146 changed = TRUE(!(0));
2147 }
2148 file->details->got_file_info = TRUE(!(0));
2149
2150 changed |= caja_file_set_display_name (file,
2151 g_file_info_get_display_name (info),
2152 g_file_info_get_edit_name (info),
2153 FALSE(0));
2154
2155 file_type = g_file_info_get_file_type (info);
2156 if (file->details->type != file_type) {
2157 changed = TRUE(!(0));
2158 }
2159 file->details->type = file_type;
2160
2161 if (!file->details->got_custom_activation_uri) {
2162 const char *activation_uri;
2163
2164 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri");
2165 if (activation_uri == NULL((void*)0)) {
2166 if (file->details->activation_uri) {
2167 g_free (file->details->activation_uri);
2168 file->details->activation_uri = NULL((void*)0);
2169 changed = TRUE(!(0));
2170 }
2171 } else {
2172 char *old_activation_uri;
2173
2174 old_activation_uri = file->details->activation_uri;
2175 file->details->activation_uri = g_strdup (activation_uri)g_strdup_inline (activation_uri);
2176
2177 if (old_activation_uri) {
2178 if (strcmp (old_activation_uri,
2179 file->details->activation_uri) != 0) {
2180 changed = TRUE(!(0));
2181 }
2182 g_free (old_activation_uri);
2183 } else {
2184 changed = TRUE(!(0));
2185 }
2186 }
2187 }
2188
2189 is_symlink = g_file_info_get_is_symlink (info);
2190 if (file->details->is_symlink != is_symlink) {
2191 changed = TRUE(!(0));
2192 }
2193 file->details->is_symlink = is_symlink;
2194
2195 is_hidden = g_file_info_get_is_hidden (info);
2196 is_backup = g_file_info_get_is_backup (info);
2197 if (file->details->is_hidden != is_hidden ||
2198 file->details->is_backup != is_backup) {
2199 changed = TRUE(!(0));
2200 }
2201 file->details->is_hidden = is_hidden;
2202 file->details->is_backup = is_backup;
2203
2204 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT"unix::is-mountpoint");
2205 if (file->details->is_mountpoint != is_mountpoint) {
2206 changed = TRUE(!(0));
2207 }
2208 file->details->is_mountpoint = is_mountpoint;
2209
2210 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
2211 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");;
2212 if (file->details->has_permissions != has_permissions ||
2213 file->details->permissions != permissions) {
2214 changed = TRUE(!(0));
2215 }
2216 file->details->has_permissions = has_permissions;
2217 file->details->permissions = permissions;
2218
2219 /* We default to TRUE for this if we can't know */
2220 can_read = TRUE(!(0));
2221 can_write = TRUE(!(0));
2222 can_execute = TRUE(!(0));
2223 can_delete = TRUE(!(0));
2224 can_trash = TRUE(!(0));
2225 can_rename = TRUE(!(0));
2226 can_mount = FALSE(0);
2227 can_unmount = FALSE(0);
2228 can_eject = FALSE(0);
2229 can_start = FALSE(0);
2230 can_start_degraded = FALSE(0);
2231 can_stop = FALSE(0);
2232 can_poll_for_media = FALSE(0);
2233 is_media_check_automatic = FALSE(0);
2234 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2235 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read")) {
2236 can_read = g_file_info_get_attribute_boolean (info,
2237 G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read");
2238 }
2239 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write")) {
2240 can_write = g_file_info_get_attribute_boolean (info,
2241 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write");
2242 }
2243 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute")) {
2244 can_execute = g_file_info_get_attribute_boolean (info,
2245 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute");
2246 }
2247 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete")) {
2248 can_delete = g_file_info_get_attribute_boolean (info,
2249 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete");
2250 }
2251 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash")) {
2252 can_trash = g_file_info_get_attribute_boolean (info,
2253 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash");
2254 }
2255 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename")) {
2256 can_rename = g_file_info_get_attribute_boolean (info,
2257 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename");
2258 }
2259 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount")) {
2260 can_mount = g_file_info_get_attribute_boolean (info,
2261 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount");
2262 }
2263 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount")) {
2264 can_unmount = g_file_info_get_attribute_boolean (info,
2265 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount");
2266 }
2267 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject")) {
2268 can_eject = g_file_info_get_attribute_boolean (info,
2269 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject");
2270 }
2271 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start")) {
2272 can_start = g_file_info_get_attribute_boolean (info,
2273 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start");
2274 }
2275 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded")) {
2276 can_start_degraded = g_file_info_get_attribute_boolean (info,
2277 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded");
2278 }
2279 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop")) {
2280 can_stop = g_file_info_get_attribute_boolean (info,
2281 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop");
2282 }
2283 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type")) {
2284 start_stop_type = g_file_info_get_attribute_uint32 (info,
2285 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type");
2286 }
2287 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll")) {
2288 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2289 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll");
2290 }
2291 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic")) {
2292 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2293 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic");
2294 }
2295 if (file->details->can_read != can_read ||
2296 file->details->can_write != can_write ||
2297 file->details->can_execute != can_execute ||
2298 file->details->can_delete != can_delete ||
2299 file->details->can_trash != can_trash ||
2300 file->details->can_rename != can_rename ||
2301 file->details->can_mount != can_mount ||
2302 file->details->can_unmount != can_unmount ||
2303 file->details->can_eject != can_eject ||
2304 file->details->can_start != can_start ||
2305 file->details->can_start_degraded != can_start_degraded ||
2306 file->details->can_stop != can_stop ||
2307 file->details->start_stop_type != start_stop_type ||
2308 file->details->can_poll_for_media != can_poll_for_media ||
2309 file->details->is_media_check_automatic != is_media_check_automatic) {
2310 changed = TRUE(!(0));
2311 }
2312
2313 file->details->can_read = can_read;
2314 file->details->can_write = can_write;
2315 file->details->can_execute = can_execute;
2316 file->details->can_delete = can_delete;
2317 file->details->can_trash = can_trash;
2318 file->details->can_rename = can_rename;
2319 file->details->can_mount = can_mount;
2320 file->details->can_unmount = can_unmount;
2321 file->details->can_eject = can_eject;
2322 file->details->can_start = can_start;
2323 file->details->can_start_degraded = can_start_degraded;
2324 file->details->can_stop = can_stop;
2325 file->details->start_stop_type = start_stop_type;
2326 file->details->can_poll_for_media = can_poll_for_media;
2327 file->details->is_media_check_automatic = is_media_check_automatic;
2328
2329 free_owner = FALSE(0);
2330 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER"owner::user");
2331 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL"owner::user-real");
2332 free_group = FALSE(0);
2333 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
2334
2335 uid = -1;
2336 gid = -1;
2337 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid")) {
2338 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid");
2339 if (owner == NULL((void*)0)) {
2340 free_owner = TRUE(!(0));
2341 owner = g_strdup_printf ("%d", uid);
2342 }
2343 }
2344 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid")) {
2345 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid");
2346 if (group == NULL((void*)0)) {
2347 free_group = TRUE(!(0));
2348 group = g_strdup_printf ("%d", gid);
2349 }
2350 }
2351 if (file->details->uid != uid ||
2352 file->details->gid != gid) {
2353 changed = TRUE(!(0));
2354 }
2355 file->details->uid = uid;
2356 file->details->gid = gid;
2357
2358 if (eel_strcmp (file->details->owner, owner) != 0) {
2359 changed = TRUE(!(0));
2360 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2361 file->details->owner = g_ref_string_new_intern (owner);
2362 }
2363
2364 if (eel_strcmp (file->details->owner_real, owner_real) != 0) {
2365 changed = TRUE(!(0));
2366 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2367 file->details->owner_real = g_ref_string_new_intern (owner_real);
2368 }
2369
2370 if (eel_strcmp (file->details->group, group) != 0) {
2371 changed = TRUE(!(0));
2372 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2373 file->details->group = g_ref_string_new_intern (group);
2374 }
2375
2376 if (free_owner) {
2377 g_free ((char *)owner);
2378 }
2379 if (free_group) {
2380 g_free ((char *)group);
2381 }
2382
2383 size = -1;
2384 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size")) {
2385 size = g_file_info_get_size (info);
2386 }
2387 if (file->details->size != size) {
2388 changed = TRUE(!(0));
2389 }
2390 file->details->size = size;
2391
2392 size_on_disk = -1;
2393 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size")) {
2394 size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size");
2395 }
2396 if (file->details->size_on_disk != size_on_disk) {
2397 changed = TRUE(!(0));
2398 }
2399 file->details->size_on_disk = size_on_disk;
2400
2401 sort_order = g_file_info_get_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER"standard::sort-order");
2402 if (file->details->sort_order != sort_order) {
2403 changed = TRUE(!(0));
2404 }
2405 file->details->sort_order = sort_order;
2406
2407 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS"time::access");
2408 ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED"time::changed");
2409 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
2410 btime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED"time::created");
2411 if (file->details->atime != atime ||
2412 file->details->mtime != mtime ||
2413 file->details->ctime != ctime ||
2414 file->details->btime != btime) {
2415 if (file->details->thumbnail == NULL((void*)0)) {
2416 file->details->thumbnail_is_up_to_date = FALSE(0);
2417 }
2418
2419 changed = TRUE(!(0));
2420 }
2421 file->details->atime = atime;
2422 file->details->ctime = ctime;
2423 file->details->mtime = mtime;
2424 file->details->btime = btime;
2425
2426 if (file->details->thumbnail != NULL((void*)0) &&
2427 file->details->thumbnail_mtime != 0 &&
2428 file->details->thumbnail_mtime != mtime) {
2429 file->details->thumbnail_is_up_to_date = FALSE(0);
2430 changed = TRUE(!(0));
2431 }
2432
2433 icon = g_file_info_get_icon (info);
2434 if (!g_icon_equal (icon, file->details->icon)) {
2435 changed = TRUE(!(0));
2436
2437 if (file->details->icon) {
2438 g_object_unref (file->details->icon);
2439 }
2440 file->details->icon = g_object_ref (icon)((__typeof__ (icon)) (g_object_ref) (icon));
2441 }
2442
2443 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
2444 if (eel_strcmp (file->details->thumbnail_path, thumbnail_path) != 0) {
2445 changed = TRUE(!(0));
2446 g_free (file->details->thumbnail_path);
2447 file->details->thumbnail_path = g_strdup (thumbnail_path)g_strdup_inline (thumbnail_path);
2448 }
2449
2450 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED"thumbnail::failed");
2451 if (file->details->thumbnailing_failed != thumbnailing_failed) {
2452 changed = TRUE(!(0));
2453 file->details->thumbnailing_failed = thumbnailing_failed;
2454 }
2455
2456 symlink_name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET"standard::symlink-target");
2457
2458 if (eel_strcmp (file->details->symlink_name, symlink_name) != 0) {
2459 changed = TRUE(!(0));
2460 g_free (file->details->symlink_name);
2461 file->details->symlink_name = g_strdup (symlink_name)g_strdup_inline (symlink_name);
2462 }
2463
2464 mime_type = g_file_info_get_content_type (info);
2465 if (eel_strcmp (file->details->mime_type, mime_type) != 0) {
2466 changed = TRUE(!(0));
2467 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2468 file->details->mime_type = g_ref_string_new_intern (mime_type);
2469 }
2470
2471 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT"selinux::context");
2472 if (eel_strcmp (file->details->selinux_context, selinux_context) != 0) {
2473 changed = TRUE(!(0));
2474 g_free (file->details->selinux_context);
2475 file->details->selinux_context = g_strdup (selinux_context)g_strdup_inline (selinux_context);
2476 }
2477
2478 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION"standard::description");
2479 if (eel_strcmp (file->details->description, description) != 0) {
2480 changed = TRUE(!(0));
2481 g_free (file->details->description);
2482 file->details->description = g_strdup (description)g_strdup_inline (description);
2483 }
2484
2485 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
2486 if (eel_strcmp (file->details->filesystem_id, filesystem_id) != 0) {
2487 changed = TRUE(!(0));
2488 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
2489 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2490 }
2491
2492 trash_time = 0;
2493 time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"trash::deletion-date");
2494 if (time_string != NULL((void*)0)) {
2495#if GLIB_CHECK_VERSION(2,61,2)(2 > (2) || (2 == (2) && 80 > (61)) || (2 == (2
) && 80 == (61) && 3 >= (2)))
2496 GDateTime *dt;
2497 GTimeZone *tz;
2498 tz = g_time_zone_new_local ();
2499 dt = g_date_time_new_from_iso8601 (time_string, tz);
2500 if (dt) {
2501 trash_time = (time_t) g_date_time_to_unix (dt);
2502 g_date_time_unref (dt);
2503 }
2504 g_time_zone_unref (tz);
2505#else
2506 GTimeVal g_trash_time;
2507 g_time_val_from_iso8601 (time_string, &g_trash_time);
2508 trash_time = g_trash_time.tv_sec;
2509#endif
2510 }
2511 if (file->details->trash_time != trash_time) {
2512 changed = TRUE(!(0));
2513 file->details->trash_time = trash_time;
2514 }
2515
2516 trash_orig_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path");
2517 if (eel_strcmp (file->details->trash_orig_path, trash_orig_path) != 0) {
2518 changed = TRUE(!(0));
2519 g_free (file->details->trash_orig_path);
2520 file->details->trash_orig_path = g_strdup (trash_orig_path)g_strdup_inline (trash_orig_path);
2521 }
2522
2523 changed |=
2524 caja_file_update_metadata_from_info (file, info);
2525
2526 if (update_name) {
2527 const char *name;
2528
2529 name = g_file_info_get_name (info);
2530 if (file->details->name == NULL((void*)0) ||
2531 strcmp (file->details->name, name) != 0) {
2532 GList *node;
2533
2534 changed = TRUE(!(0));
2535
2536 node = caja_directory_begin_file_name_change
2537 (file->details->directory, file);
2538
2539 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2540 if (eel_strcmp (file->details->display_name, name) == 0) {
2541 file->details->name = g_ref_string_acquire (file->details->display_name);
2542 } else {
2543 file->details->name = g_ref_string_new (name);
2544 }
2545
2546 if (!file->details->got_custom_display_name &&
2547 g_file_info_get_display_name (info) == NULL((void*)0)) {
2548 /* If the file info's display name is NULL,
2549 * caja_file_set_display_name() did
2550 * not unset the display name.
2551 */
2552 caja_file_clear_display_name (file);
2553 }
2554
2555 caja_directory_end_file_name_change
2556 (file->details->directory, file, node);
2557 }
2558 }
2559
2560 if (changed) {
2561 add_to_link_hash_table (file);
2562
2563 update_links_if_target (file);
2564 }
2565
2566 return changed;
2567}
2568
2569static gboolean
2570update_info_and_name (CajaFile *file,
2571 GFileInfo *info)
2572{
2573 return update_info_internal (file, info, TRUE(!(0)));
2574}
2575
2576gboolean
2577caja_file_update_info (CajaFile *file,
2578 GFileInfo *info)
2579{
2580 return update_info_internal (file, info, FALSE(0));
2581}
2582
2583void
2584caja_file_refresh_info (CajaFile *file)
2585{
2586 GFile *gfile;
2587 GFileInfo *new_info;
2588
2589 gfile = caja_file_get_location (file);
2590 new_info = g_file_query_info (gfile, CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
2591 G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
2592 if (new_info != NULL((void*)0)) {
2593 if (caja_file_update_info (file, new_info)) {
2594 caja_file_changed (file);
2595 }
2596 g_object_unref (new_info);
2597 }
2598 g_object_unref (gfile);
2599}
2600
2601static gboolean
2602update_name_internal (CajaFile *file,
2603 const char *name,
2604 gboolean in_directory)
2605{
2606 GList *node;
2607
2608 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_464
; if (name != ((void*)0)) _g_boolean_var_464 = 1; else _g_boolean_var_464
= 0; _g_boolean_var_464; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2608, ((const char*) (__func__
)), "name != NULL"); } while (0)
;
2609
2610 if (file->details->is_gone) {
2611 return FALSE(0);
2612 }
2613
2614 if (name_is (file, name)) {
2615 return FALSE(0);
2616 }
2617
2618 node = NULL((void*)0);
2619 if (in_directory) {
2620 node = caja_directory_begin_file_name_change
2621 (file->details->directory, file);
2622 }
2623
2624 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2625 file->details->name = g_ref_string_new (name);
2626
2627 if (!file->details->got_custom_display_name) {
2628 caja_file_clear_display_name (file);
2629 }
2630
2631 if (in_directory) {
2632 caja_directory_end_file_name_change
2633 (file->details->directory, file, node);
2634 }
2635
2636 return TRUE(!(0));
2637}
2638
2639gboolean
2640caja_file_update_name (CajaFile *file, const char *name)
2641{
2642 gboolean ret;
2643
2644 ret = update_name_internal (file, name, TRUE(!(0)));
2645
2646 if (ret) {
2647 update_links_if_target (file);
2648 }
2649
2650 return ret;
2651}
2652
2653gboolean
2654caja_file_update_name_and_directory (CajaFile *file,
2655 const char *name,
2656 CajaDirectory *new_directory)
2657{
2658 CajaDirectory *old_directory;
2659 FileMonitors *monitors;
2660
2661 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_465
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_465
= 1; else _g_boolean_var_465 = 0; _g_boolean_var_465; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2662 g_return_val_if_fail (CAJA_IS_DIRECTORY (file->details->directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_466
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file->details->directory)); GType __t = (caja_directory_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_466 = 1; else _g_boolean_var_466 =
0; _g_boolean_var_466; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_DIRECTORY (file->details->directory)"
); return ((0)); } } while (0)
;
2663 g_return_val_if_fail (!file->details->is_gone, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_467
; if (!file->details->is_gone) _g_boolean_var_467 = 1; else
_g_boolean_var_467 = 0; _g_boolean_var_467; }), 1))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "!file->details->is_gone"); return ((0)); } } while
(0)
;
2664 g_return_val_if_fail (!caja_file_is_self_owned (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_468
; if (!caja_file_is_self_owned (file)) _g_boolean_var_468 = 1
; else _g_boolean_var_468 = 0; _g_boolean_var_468; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "!caja_file_is_self_owned (file)"); return ((
0)); } } while (0)
;
2665 g_return_val_if_fail (CAJA_IS_DIRECTORY (new_directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_469
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_directory)); GType __t = (caja_directory_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_469 = 1; else _g_boolean_var_469 = 0; _g_boolean_var_469
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "CAJA_IS_DIRECTORY (new_directory)"
); return ((0)); } } while (0)
;
2666
2667 old_directory = file->details->directory;
2668 if (old_directory == new_directory) {
2669 if (name) {
2670 return update_name_internal (file, name, TRUE(!(0)));
2671 } else {
2672 return FALSE(0);
2673 }
2674 }
2675
2676 caja_file_ref (file);
2677
2678 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2679 * point to the old name know that the file has been moved.
2680 */
2681
2682 remove_from_link_hash_table (file);
2683
2684 monitors = caja_directory_remove_file_monitors (old_directory, file);
2685 caja_directory_remove_file (old_directory, file);
2686
2687 file->details->directory = caja_directory_ref (new_directory);
2688 caja_directory_unref (old_directory);
2689
2690 if (name) {
2691 update_name_internal (file, name, FALSE(0));
2692 }
2693
2694 caja_directory_add_file (new_directory, file);
2695 caja_directory_add_file_monitors (new_directory, file, monitors);
2696
2697 add_to_link_hash_table (file);
2698
2699 update_links_if_target (file);
2700
2701 caja_file_unref (file);
2702
2703 return TRUE(!(0));
2704}
2705
2706void
2707caja_file_set_directory (CajaFile *file,
2708 CajaDirectory *new_directory)
2709{
2710 caja_file_update_name_and_directory (file, NULL((void*)0), new_directory);
2711}
2712
2713static Knowledge
2714get_item_count (CajaFile *file,
2715 guint *count)
2716{
2717 gboolean known, unreadable;
2718
2719 known = caja_file_get_directory_item_count
2720 (file, count, &unreadable);
2721 if (!known) {
2722 return UNKNOWN;
2723 }
2724 if (unreadable) {
2725 return UNKNOWABLE;
2726 }
2727 return KNOWN;
2728}
2729
2730static Knowledge
2731get_size (CajaFile *file,
2732 goffset *size,
2733 gboolean size_on_disk)
2734{
2735 /* If we tried and failed, then treat it like there is no size
2736 * to know.
2737 */
2738 if (file->details->get_info_failed) {
2739 return UNKNOWABLE;
2740 }
2741
2742 /* If the info is NULL that means we haven't even tried yet,
2743 * so it's just unknown, not unknowable.
2744 */
2745 if (!file->details->got_file_info) {
2746 return UNKNOWN;
2747 }
2748
2749 /* If we got info with no size in it, it means there is no
2750 * such thing as a size as far as mate-vfs is concerned,
2751 * so "unknowable".
2752 */
2753 if (size_on_disk && file->details->size_on_disk == -1) {
2754 return UNKNOWABLE;
2755 }
2756
2757 if (!size_on_disk && file->details->size == -1) {
2758 return UNKNOWABLE;
2759 }
2760
2761 /* We have a size! */
2762 if (size_on_disk) {
2763 *size = file->details->size_on_disk;
2764 } else {
2765 *size = file->details->size;
2766 }
2767
2768 return KNOWN;
2769}
2770
2771static Knowledge
2772get_time (CajaFile *file,
2773 time_t *time_out,
2774 CajaDateType type)
2775{
2776 time_t time;
2777
2778 /* If we tried and failed, then treat it like there is no size
2779 * to know.
2780 */
2781 if (file->details->get_info_failed) {
2782 return UNKNOWABLE;
2783 }
2784
2785 /* If the info is NULL that means we haven't even tried yet,
2786 * so it's just unknown, not unknowable.
2787 */
2788 if (!file->details->got_file_info) {
2789 return UNKNOWN;
2790 }
2791
2792 time = 0;
2793 switch (type) {
2794 case CAJA_DATE_TYPE_MODIFIED:
2795 time = file->details->mtime;
2796 break;
2797 case CAJA_DATE_TYPE_ACCESSED:
2798 time = file->details->atime;
2799 break;
2800 case CAJA_DATE_TYPE_CREATED:
2801 time = file->details->btime;
2802 break;
2803 case CAJA_DATE_TYPE_TRASHED:
2804 time = file->details->trash_time;
2805 break;
2806 default:
2807 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file.c", 2807
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2808 break;
2809 }
2810
2811 *time_out = time;
2812
2813 /* If we got info with no modification time in it, it means
2814 * there is no such thing as a modification time as far as
2815 * mate-vfs is concerned, so "unknowable".
2816 */
2817 if (time == 0) {
2818 return UNKNOWABLE;
2819 }
2820 return KNOWN;
2821}
2822
2823static int
2824compare_directories_by_count (CajaFile *file_1, CajaFile *file_2)
2825{
2826 /* Sort order:
2827 * Directories with unknown # of items
2828 * Directories with "unknowable" # of items
2829 * Directories with 0 items
2830 * Directories with n items
2831 */
2832
2833 Knowledge count_known_1, count_known_2;
2834 guint count_1, count_2;
2835
2836 count_known_1 = get_item_count (file_1, &count_1);
2837 count_known_2 = get_item_count (file_2, &count_2);
2838
2839 if (count_known_1 > count_known_2) {
2840 return -1;
2841 }
2842 if (count_known_1 < count_known_2) {
2843 return +1;
2844 }
2845
2846 /* count_known_1 and count_known_2 are equal now. Check if count
2847 * details are UNKNOWABLE or UNKNOWN.
2848 */
2849 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2850 return 0;
2851 }
2852
2853 if (count_1 < count_2) {
2854 return -1;
2855 }
2856 if (count_1 > count_2) {
2857 return +1;
2858 }
2859
2860 return 0;
2861}
2862
2863static int
2864compare_files_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2865{
2866 /* Sort order:
2867 * Files with unknown size.
2868 * Files with "unknowable" size.
2869 * Files with smaller sizes.
2870 * Files with large sizes.
2871 */
2872
2873 Knowledge size_known_1, size_known_2;
2874 goffset size_1 = 0, size_2 = 0;
2875
2876 size_known_1 = get_size (file_1, &size_1, size_on_disk);
2877 size_known_2 = get_size (file_2, &size_2, size_on_disk);
2878
2879 if (size_known_1 > size_known_2) {
2880 return -1;
2881 }
2882 if (size_known_1 < size_known_2) {
2883 return +1;
2884 }
2885
2886 /* size_known_1 and size_known_2 are equal now. Check if size
2887 * details are UNKNOWABLE or UNKNOWN
2888 */
2889 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2890 return 0;
2891 }
2892
2893 if (size_1 < size_2) {
2894 return -1;
2895 }
2896 if (size_1 > size_2) {
2897 return +1;
2898 }
2899
2900 return 0;
2901}
2902
2903static int
2904compare_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2905{
2906 /* Sort order:
2907 * Directories with n items
2908 * Directories with 0 items
2909 * Directories with "unknowable" # of items
2910 * Directories with unknown # of items
2911 * Files with large sizes.
2912 * Files with smaller sizes.
2913 * Files with "unknowable" size.
2914 * Files with unknown size.
2915 */
2916
2917 gboolean is_directory_1, is_directory_2;
2918
2919 is_directory_1 = caja_file_is_directory (file_1);
2920 is_directory_2 = caja_file_is_directory (file_2);
2921
2922 if (is_directory_1 && !is_directory_2) {
2923 return -1;
2924 }
2925 if (is_directory_2 && !is_directory_1) {
2926 return +1;
2927 }
2928
2929 if (is_directory_1) {
2930 return compare_directories_by_count (file_1, file_2);
2931 } else {
2932 return compare_files_by_size (file_1, file_2, size_on_disk);
2933 }
2934}
2935
2936static int
2937compare_by_display_name (CajaFile *file_1, CajaFile *file_2)
2938{
2939 const char *name_1, *name_2;
2940 const char *key_1, *key_2;
2941 gboolean sort_last_1, sort_last_2;
2942 int compare;
2943
2944 name_1 = caja_file_peek_display_name (file_1);
2945 name_2 = caja_file_peek_display_name (file_2);
2946
2947 sort_last_1 = name_1[0] == SORT_LAST_CHAR1'.' || name_1[0] == SORT_LAST_CHAR2'#';
2948 sort_last_2 = name_2[0] == SORT_LAST_CHAR1'.' || name_2[0] == SORT_LAST_CHAR2'#';
2949
2950 if (sort_last_1 && !sort_last_2) {
2951 compare = +1;
2952 } else if (!sort_last_1 && sort_last_2) {
2953 compare = -1;
2954 } else {
2955 key_1 = caja_file_peek_display_name_collation_key (file_1);
2956 key_2 = caja_file_peek_display_name_collation_key (file_2);
2957 compare = strcmp (key_1, key_2);
2958 }
2959
2960 return compare;
2961}
2962
2963static int
2964compare_by_directory_name (CajaFile *file_1, CajaFile *file_2)
2965{
2966 char *directory_1, *directory_2;
2967 int compare;
2968
2969 if (file_1->details->directory == file_2->details->directory) {
2970 return 0;
2971 }
2972
2973 directory_1 = caja_file_get_parent_uri_for_display (file_1);
2974 directory_2 = caja_file_get_parent_uri_for_display (file_2);
2975
2976 compare = g_utf8_collate (directory_1, directory_2);
2977
2978 g_free (directory_1);
2979 g_free (directory_2);
2980
2981 return compare;
2982}
2983
2984static gboolean
2985file_has_note (CajaFile *file)
2986{
2987 char *note;
2988 gboolean res;
2989
2990 note = caja_file_get_metadata (file, CAJA_METADATA_KEY_ANNOTATION"annotation", NULL((void*)0));
2991 res = note != NULL((void*)0) && note[0] != 0;
2992 g_free (note);
2993
2994 return res;
2995}
2996
2997static GList *
2998prepend_automatic_keywords (CajaFile *file,
2999 GList *names)
3000{
3001 /* Prepend in reverse order. */
3002 CajaFile *parent;
3003
3004 parent = caja_file_get_parent (file);
3005
3006#ifdef TRASH_IS_FAST_ENOUGH
3007 if (caja_file_is_in_trash (file)) {
3008 names = g_list_prepend
3009 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash"));
3010 }
3011#endif
3012 if (file_has_note (file)) {
3013 names = g_list_prepend
3014 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_NOTE)g_strdup_inline ("note"));
3015 }
3016
3017 /* Trash files are assumed to be read-only,
3018 * so we want to ignore them here. */
3019 if (!caja_file_can_write (file) &&
3020 !caja_file_is_in_trash (file) &&
3021 (parent == NULL((void*)0) || caja_file_can_write (parent))) {
3022 names = g_list_prepend
3023 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite"));
3024 }
3025 if (!caja_file_can_read (file)) {
3026 names = g_list_prepend
3027 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_READ)g_strdup_inline ("noread"));
3028 }
3029 if (caja_file_is_symbolic_link (file)) {
3030 names = g_list_prepend
3031 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_SYMBOLIC_LINK)g_strdup_inline ("symbolic-link"));
3032 }
3033
3034 if (parent) {
3035 caja_file_unref (parent);
3036 }
3037
3038
3039 return names;
3040}
3041
3042static void
3043fill_emblem_cache_if_needed (CajaFile *file)
3044{
3045 GList *node, *keywords;
3046 char *scanner;
3047 size_t length;
3048
3049 if (file->details->compare_by_emblem_cache != NULL((void*)0)) {
3050 /* Got a cache already. */
3051 return;
3052 }
3053
3054 keywords = caja_file_get_keywords (file);
3055
3056 /* Add up the keyword string lengths */
3057 length = 1;
3058 for (node = keywords; node != NULL((void*)0); node = node->next) {
3059 length += strlen ((const char *) node->data) + 1;
3060 }
3061
3062 /* Now that we know how large the cache struct needs to be, allocate it. */
3063 file->details->compare_by_emblem_cache = g_malloc (sizeof(CajaFileSortByEmblemCache) + length);
3064
3065 /* Copy them into the cache. */
3066 scanner = file->details->compare_by_emblem_cache->emblem_keywords;
3067 for (node = keywords; node != NULL((void*)0); node = node->next) {
3068 length = strlen ((const char *) node->data) + 1;
3069 memcpy (scanner, (const char *) node->data, length);
3070 scanner += length;
3071 }
3072
3073 /* Zero-terminate so we can tell where the list ends. */
3074 *scanner = 0;
3075
3076 g_list_free_full (keywords, g_free);
3077}
3078
3079static int
3080compare_by_emblems (CajaFile *file_1, CajaFile *file_2)
3081{
3082 const char *keyword_cache_1, *keyword_cache_2;
3083 int compare_result;
3084
3085 fill_emblem_cache_if_needed (file_1);
3086 fill_emblem_cache_if_needed (file_2);
3087
3088 /* We ignore automatic emblems, and only sort by user-added keywords. */
3089 compare_result = 0;
Value stored to 'compare_result' is never read
3090 keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords;
3091 keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords;
3092 for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) {
3093 size_t length;
3094
3095 compare_result = g_utf8_collate (keyword_cache_1, keyword_cache_2);
3096 if (compare_result != 0) {
3097 return compare_result;
3098 }
3099
3100 /* Advance to the next keyword */
3101 length = strlen (keyword_cache_1);
3102 keyword_cache_1 += length + 1;
3103 keyword_cache_2 += length + 1;
3104 }
3105
3106
3107 /* One or both is now NULL. */
3108 if (*keyword_cache_1 != '\0') {
3109 g_assert (*keyword_cache_2 == '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_470
; if (*keyword_cache_2 == '\0') _g_boolean_var_470 = 1; else _g_boolean_var_470
= 0; _g_boolean_var_470; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3109, ((const char*) (__func__
)), "*keyword_cache_2 == '\\0'"); } while (0)
;
3110 return -1;
3111 } else if (*keyword_cache_2 != '\0') {
3112 return +1;
3113 }
3114
3115 return 0;
3116}
3117
3118static int
3119compare_by_type (CajaFile *file_1, CajaFile *file_2)
3120{
3121 gboolean is_directory_1;
3122 gboolean is_directory_2;
3123 char *type_string_1;
3124 char *type_string_2;
3125 int result;
3126
3127 /* Directories go first. Then, if mime types are identical,
3128 * don't bother getting strings (for speed). This assumes
3129 * that the string is dependent entirely on the mime type,
3130 * which is true now but might not be later.
3131 */
3132 is_directory_1 = caja_file_is_directory (file_1);
3133 is_directory_2 = caja_file_is_directory (file_2);
3134
3135 if (is_directory_1 && is_directory_2) {
3136 return 0;
3137 }
3138
3139 if (is_directory_1) {
3140 return -1;
3141 }
3142
3143 if (is_directory_2) {
3144 return +1;
3145 }
3146
3147 if (file_1->details->mime_type != NULL((void*)0) &&
3148 file_2->details->mime_type != NULL((void*)0) &&
3149 strcmp (file_1->details->mime_type,
3150 file_2->details->mime_type) == 0) {
3151 return 0;
3152 }
3153
3154 type_string_1 = caja_file_get_type_as_string (file_1);
3155 type_string_2 = caja_file_get_type_as_string (file_2);
3156
3157 result = g_utf8_collate (type_string_1, type_string_2);
3158
3159 g_free (type_string_1);
3160 g_free (type_string_2);
3161
3162 return result;
3163}
3164
3165static int
3166compare_by_time (CajaFile *file_1, CajaFile *file_2, CajaDateType type)
3167{
3168 /* Sort order:
3169 * Files with unknown times.
3170 * Files with "unknowable" times.
3171 * Files with older times.
3172 * Files with newer times.
3173 */
3174
3175 Knowledge time_known_1, time_known_2;
3176 time_t time_1, time_2;
3177
3178 time_1 = 0;
3179 time_2 = 0;
3180
3181 time_known_1 = get_time (file_1, &time_1, type);
3182 time_known_2 = get_time (file_2, &time_2, type);
3183
3184 if (time_known_1 > time_known_2) {
3185 return -1;
3186 }
3187 if (time_known_1 < time_known_2) {
3188 return +1;
3189 }
3190
3191 /* Now time_known_1 is equal to time_known_2. Check whether
3192 * we failed to get modification times for files
3193 */
3194 if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3195 return 0;
3196 }
3197
3198 if (time_1 < time_2) {
3199 return -1;
3200 }
3201 if (time_1 > time_2) {
3202 return +1;
3203 }
3204
3205 return 0;
3206}
3207
3208static int
3209compare_by_full_path (CajaFile *file_1, CajaFile *file_2)
3210{
3211 int compare;
3212
3213 compare = compare_by_directory_name (file_1, file_2);
3214 if (compare != 0) {
3215 return compare;
3216 }
3217 return compare_by_display_name (file_1, file_2);
3218}
3219
3220/* prev_extension_segment:
3221 * @basename The basename of a file
3222 * @rem_chars A pointer to the amount of remaining characters
3223 *
3224 * Finds the next segment delimiter to the left. A starting character of '.' is
3225 * set to '\0'.
3226 *
3227 * Return value: The start of the previous segment (right of the dot) or
3228 * basename if there are none remaining.
3229 */
3230static char *
3231prev_extension_segment (char *basename, int *rem_chars)
3232{
3233 if (*basename == '.') {
3234 *basename = 0;
3235 basename--;
3236 (*rem_chars)--;
3237 }
3238
3239 while (*rem_chars > 0 && *basename != '.') {
3240 (*rem_chars)--;
3241 basename--;
3242 }
3243
3244 return basename + 1;
3245}
3246
3247/* is_valid_extension_segment:
3248 * @segment Part of a modifiable zero-terminated string
3249 * @segment_index The index of the current segment
3250 *
3251 * Uses a heuristic to identify valid file extensions.
3252 *
3253 * Return value: Whether the segment is part of the file extension.
3254 */
3255static gboolean
3256is_valid_extension_segment (const char *segment, int segment_index)
3257{
3258 gboolean result;
3259 gboolean has_letters;
3260 int char_offset;
3261 switch (segment_index) {
3262 case 0:
3263 /* extremely long segments are probably not part of the extension */
3264 result = strlen (segment) < 20;
3265 break;
3266 default:
3267 has_letters = FALSE(0);
3268 char_offset = 0;
3269 while (TRUE(!(0))) {
3270 char c;
3271
3272 c = *(segment + char_offset);
3273 if (c == '\0') {
3274 result = has_letters;
3275 break;
3276 }
3277 /* allow digits if there are also letters */
3278 else if (isalpha (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha
)
) {
3279 has_letters = TRUE(!(0));
3280 }
3281 /* fail if it is neither digit nor letter */
3282 else if (!isdigit (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
) {
3283 result = FALSE(0);
3284 break;
3285 }
3286
3287 if (char_offset >= SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3) {
3288 result = FALSE(0);
3289 break;
3290 }
3291 char_offset++;
3292 }
3293 }
3294 return result;
3295}
3296
3297static int
3298compare_by_extension_segments (CajaFile *file_1, CajaFile *file_2)
3299{
3300 char *name_1, *name_2;
3301 char *segment_1, *segment_2;
3302 int compare;
3303 int rem_chars_1, rem_chars_2;
3304 gboolean done_1, done_2;
3305 gboolean is_directory_1, is_directory_2;
3306 int segment_index;
3307
3308
3309 /* Directories do not have an extension */
3310 is_directory_1 = caja_file_is_directory (file_1);
3311 is_directory_2 = caja_file_is_directory (file_2);
3312
3313 if (is_directory_1 && is_directory_2) {
3314 return 0;
3315 } else if (is_directory_1) {
3316 return -1;
3317 } else if (is_directory_2) {
3318 return 1;
3319 }
3320
3321 name_1 = caja_file_get_display_name (file_1);
3322 name_2 = caja_file_get_display_name (file_2);
3323 rem_chars_1 = strlen (name_1);
3324 rem_chars_2 = strlen (name_2);
3325
3326 /* Point to one after the zero character */
3327 segment_1 = name_1 + rem_chars_1 + 1;
3328 segment_2 = name_2 + rem_chars_2 + 1;
3329
3330 segment_index = 0;
3331 do {
3332 segment_1 = prev_extension_segment (segment_1 - 1, &rem_chars_1);
3333 segment_2 = prev_extension_segment (segment_2 - 1, &rem_chars_2);
3334
3335 done_1 = rem_chars_1 <= 0 || !is_valid_extension_segment (segment_1, segment_index);
3336 done_2 = rem_chars_2 <= 0 || !is_valid_extension_segment (segment_2, segment_index);
3337 if (done_1 && !done_2) {
3338 compare = -1;
3339 break;
3340 }
3341 else if (!done_1 && done_2) {
3342 compare = 1;
3343 break;
3344 }
3345 else if (done_1 && done_2) {
3346 compare = 0;
3347 break;
3348 }
3349
3350 segment_index++;
3351 if (segment_index > SORT_BY_EXTENSION_MAX_SEGMENTS3 - 1) {
3352 break;
3353 }
3354 compare = strcmp (segment_1, segment_2);
3355 } while (compare == 0);
3356
3357 g_free (name_1);
3358 g_free (name_2);
3359
3360 return compare;
3361}
3362
3363static gchar *
3364caja_file_get_extension_as_string (CajaFile *file)
3365{
3366 int rem_chars;
3367 char *segment;
3368
3369 if (!caja_file_is_directory (file)) {
3370 char *name;
3371
3372 name = caja_file_get_display_name (file);
3373 rem_chars = strlen (name);
3374 segment = prev_extension_segment (name + rem_chars, &rem_chars);
3375
3376 if (rem_chars > 0 && is_valid_extension_segment (segment, 0)) {
3377 int segment_index;
3378 char *right_segment;
3379 char *result;
3380
3381 segment_index = 1;
3382 do {
3383 right_segment = segment;
3384 segment = prev_extension_segment (segment - 1, &rem_chars);
3385 if (rem_chars > 0 && is_valid_extension_segment (segment, segment_index)) {
3386 /* remove zero-termination of segment */
3387 *(right_segment - 1) = '.';
3388 }
3389 else {
3390 break;
3391 }
3392
3393 segment_index++;
3394 } while (segment_index < SORT_BY_EXTENSION_MAX_SEGMENTS3 + 1);
3395 result = g_strdup (right_segment)g_strdup_inline (right_segment);
3396 g_free (name);
3397 return result;
3398 }
3399 g_free (name);
3400 }
3401 return g_strdup ("")g_strdup_inline ("");
3402}
3403
3404static int
3405caja_file_compare_for_sort_internal (CajaFile *file_1,
3406 CajaFile *file_2,
3407 gboolean directories_first,
3408 gboolean reversed)
3409{
3410 gboolean is_directory_1, is_directory_2;
3411
3412 if (directories_first) {
3413 is_directory_1 = caja_file_is_directory (file_1);
3414 is_directory_2 = caja_file_is_directory (file_2);
3415
3416 if (is_directory_1 && !is_directory_2) {
3417 return -1;
3418 }
3419
3420 if (is_directory_2 && !is_directory_1) {
3421 return +1;
3422 }
3423 }
3424
3425 if (file_1->details->sort_order < file_2->details->sort_order) {
3426 return reversed ? 1 : -1;
3427 } else if (file_1->details->sort_order > file_2->details->sort_order) {
3428 return reversed ? -1 : 1;
3429 }
3430
3431 return 0;
3432}
3433
3434/**
3435 * caja_file_compare_for_sort:
3436 * @file_1: A file object
3437 * @file_2: Another file object
3438 * @sort_type: Sort criterion
3439 * @directories_first: Put all directories before any non-directories
3440 * @reversed: Reverse the order of the items, except that
3441 * the directories_first flag is still respected.
3442 *
3443 * Return value: int < 0 if @file_1 should come before file_2 in a
3444 * sorted list; int > 0 if @file_2 should come before file_1 in a
3445 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3446 * that each named sort type may actually break ties several ways, with the name
3447 * of the sort criterion being the primary but not only differentiator.
3448 **/
3449int
3450caja_file_compare_for_sort (CajaFile *file_1,
3451 CajaFile *file_2,
3452 CajaFileSortType sort_type,
3453 gboolean directories_first,
3454 gboolean reversed)
3455{
3456 int result;
3457
3458 if (file_1 == file_2) {
3459 return 0;
3460 }
3461
3462 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3463
3464 if (result == 0) {
3465 switch (sort_type) {
3466 case CAJA_FILE_SORT_BY_DISPLAY_NAME:
3467 result = compare_by_display_name (file_1, file_2);
3468 if (result == 0) {
3469 result = compare_by_directory_name (file_1, file_2);
3470 }
3471 break;
3472 case CAJA_FILE_SORT_BY_DIRECTORY:
3473 result = compare_by_full_path (file_1, file_2);
3474 break;
3475 case CAJA_FILE_SORT_BY_SIZE:
3476 /* Compare directory sizes ourselves, then if necessary
3477 * use MateVFS to compare file sizes.
3478 */
3479 result = compare_by_size (file_1, file_2, FALSE(0));
3480 if (result == 0) {
3481 result = compare_by_full_path (file_1, file_2);
3482 }
3483 break;
3484 case CAJA_FILE_SORT_BY_SIZE_ON_DISK:
3485 /* Compare directory sizes ourselves, then if necessary
3486 * use MateVFS to compare file sizes.
3487 */
3488 result = compare_by_size (file_1, file_2, TRUE(!(0)));
3489 if (result == 0) {
3490 result = compare_by_full_path (file_1, file_2);
3491 }
3492 break;
3493 case CAJA_FILE_SORT_BY_TYPE:
3494 /* MateVFS doesn't know about our special text for certain
3495 * mime types, so we handle the mime-type sorting ourselves.
3496 */
3497 result = compare_by_type (file_1, file_2);
3498 if (result == 0) {
3499 result = compare_by_full_path (file_1, file_2);
3500 }
3501 break;
3502 case CAJA_FILE_SORT_BY_MTIME:
3503 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_MODIFIED);
3504 if (result == 0) {
3505 result = compare_by_full_path (file_1, file_2);
3506 }
3507 break;
3508 case CAJA_FILE_SORT_BY_BTIME:
3509 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_CREATED);
3510 if (result == 0) {
3511 result = compare_by_full_path (file_1, file_2);
3512 }
3513 break;
3514 case CAJA_FILE_SORT_BY_ATIME:
3515 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_ACCESSED);
3516 if (result == 0) {
3517 result = compare_by_full_path (file_1, file_2);
3518 }
3519 break;
3520 case CAJA_FILE_SORT_BY_TRASHED_TIME:
3521 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_TRASHED);
3522 if (result == 0) {
3523 result = compare_by_full_path (file_1, file_2);
3524 }
3525 break;
3526 case CAJA_FILE_SORT_BY_EMBLEMS:
3527 /* MateVFS doesn't know squat about our emblems, so
3528 * we handle comparing them here, before falling back
3529 * to tie-breakers.
3530 */
3531 result = compare_by_emblems (file_1, file_2);
3532 if (result == 0) {
3533 result = compare_by_full_path (file_1, file_2);
3534 }
3535 break;
3536 case CAJA_FILE_SORT_BY_EXTENSION:
3537 result = compare_by_extension_segments (file_1, file_2);
3538 if (result == 0) {
3539 result = compare_by_full_path (file_1, file_2);
3540 }
3541 break;
3542 default:
3543 g_return_val_if_reached (0)do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "caja-file.c", 3543, ((const char*) (__func__))); return (0
); } while (0)
;
3544 }
3545
3546 if (reversed) {
3547 result = -result;
3548 }
3549 }
3550
3551 return result;
3552}
3553
3554int
3555caja_file_compare_for_sort_by_attribute_q (CajaFile *file_1,
3556 CajaFile *file_2,
3557 GQuark attribute,
3558 gboolean directories_first,
3559 gboolean reversed)
3560{
3561 int result;
3562
3563 if (file_1 == file_2) {
3564 return 0;
3565 }
3566
3567 /* Convert certain attributes into CajaFileSortTypes and use
3568 * caja_file_compare_for_sort()
3569 */
3570 if (attribute == 0 || attribute == attribute_name_q) {
3571 return caja_file_compare_for_sort (file_1, file_2,
3572 CAJA_FILE_SORT_BY_DISPLAY_NAME,
3573 directories_first,
3574 reversed);
3575 } else if (attribute == attribute_size_q) {
3576 return caja_file_compare_for_sort (file_1, file_2,
3577 CAJA_FILE_SORT_BY_SIZE,
3578 directories_first,
3579 reversed);
3580 } else if (attribute == attribute_size_on_disk_q) {
3581 return caja_file_compare_for_sort (file_1, file_2,
3582 CAJA_FILE_SORT_BY_SIZE_ON_DISK,
3583 directories_first,
3584 reversed);
3585 } else if (attribute == attribute_type_q) {
3586 return caja_file_compare_for_sort (file_1, file_2,
3587 CAJA_FILE_SORT_BY_TYPE,
3588 directories_first,
3589 reversed);
3590 } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q) {
3591 return caja_file_compare_for_sort (file_1, file_2,
3592 CAJA_FILE_SORT_BY_MTIME,
3593 directories_first,
3594 reversed);
3595 } else if (attribute == attribute_creation_date_q || attribute == attribute_date_created_q) {
3596 return caja_file_compare_for_sort (file_1, file_2,
3597 CAJA_FILE_SORT_BY_BTIME,
3598 directories_first,
3599 reversed);
3600 } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q) {
3601 return caja_file_compare_for_sort (file_1, file_2,
3602 CAJA_FILE_SORT_BY_ATIME,
3603 directories_first,
3604 reversed);
3605 } else if (attribute == attribute_trashed_on_q) {
3606 return caja_file_compare_for_sort (file_1, file_2,
3607 CAJA_FILE_SORT_BY_TRASHED_TIME,
3608 directories_first,
3609 reversed);
3610 } else if (attribute == attribute_emblems_q) {
3611 return caja_file_compare_for_sort (file_1, file_2,
3612 CAJA_FILE_SORT_BY_EMBLEMS,
3613 directories_first,
3614 reversed);
3615 } else if (attribute == attribute_extension_q) {
3616 return caja_file_compare_for_sort (file_1, file_2,
3617 CAJA_FILE_SORT_BY_EXTENSION,
3618 directories_first,
3619 reversed);
3620 }
3621
3622 /* it is a normal attribute, compare by strings */
3623
3624 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3625
3626 if (result == 0) {
3627 char *value_1;
3628 char *value_2;
3629
3630 value_1 = caja_file_get_string_attribute_q (file_1,
3631 attribute);
3632 value_2 = caja_file_get_string_attribute_q (file_2,
3633 attribute);
3634
3635 if (value_1 != NULL((void*)0) && value_2 != NULL((void*)0)) {
3636 result = strcmp (value_1, value_2);
3637 }
3638
3639 g_free (value_1);
3640 g_free (value_2);
3641
3642 if (reversed) {
3643 result = -result;
3644 }
3645 }
3646
3647 return result;
3648}
3649
3650int
3651caja_file_compare_for_sort_by_attribute (CajaFile *file_1,
3652 CajaFile *file_2,
3653 const char *attribute,
3654 gboolean directories_first,
3655 gboolean reversed)
3656{
3657 return caja_file_compare_for_sort_by_attribute_q (file_1, file_2,
3658 g_quark_from_string (attribute),
3659 directories_first,
3660 reversed);
3661}
3662
3663
3664/**
3665 * caja_file_compare_name:
3666 * @file: A file object
3667 * @pattern: A string we are comparing it with
3668 *
3669 * Return value: result of a comparison of the file name and the given pattern,
3670 * using the same sorting order as sort by name.
3671 **/
3672int
3673caja_file_compare_display_name (CajaFile *file,
3674 const char *pattern)
3675{
3676 const char *name;
3677 int result;
3678
3679 g_return_val_if_fail (pattern != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_471
; if (pattern != ((void*)0)) _g_boolean_var_471 = 1; else _g_boolean_var_471
= 0; _g_boolean_var_471; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "pattern != NULL"
); return (-1); } } while (0)
;
3680
3681 name = caja_file_peek_display_name (file);
3682 result = g_utf8_collate (name, pattern);
3683 return result;
3684}
3685
3686
3687gboolean
3688caja_file_is_hidden_file (CajaFile *file)
3689{
3690 return file->details->is_hidden;
3691}
3692
3693static gboolean
3694caja_file_is_backup_file (CajaFile *file)
3695{
3696 return file->details->is_backup;
3697}
3698
3699/**
3700 * caja_file_should_show:
3701 * @file: the file to check.
3702 * @show_hidden: whether we want to show hidden files or not.
3703 * @show_backup: whether we want to show backup files or not.
3704 *
3705 * Determines if a #CajaFile should be shown. Note that when browsing
3706 * a trash directory, this function will always return %TRUE.
3707 *
3708 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3709 */
3710gboolean
3711caja_file_should_show (CajaFile *file,
3712 gboolean show_hidden,
3713 gboolean show_foreign,
3714 gboolean show_backup)
3715{
3716 /* Never hide any files in trash. */
3717 if (caja_file_is_in_trash (file)) {
3718 return TRUE(!(0));
3719 } else {
3720 return (show_hidden || !caja_file_is_hidden_file (file)) &&
3721 (show_backup || !caja_file_is_backup_file (file)) &&
3722 (show_foreign || !(caja_file_is_in_desktop (file) && caja_file_is_foreign_link (file)));
3723 }
3724}
3725
3726gboolean
3727caja_file_is_home (CajaFile *file)
3728{
3729 GFile *dir;
3730
3731 dir = file->details->directory->details->location;
3732 if (dir == NULL((void*)0)) {
3733 return FALSE(0);
3734 }
3735
3736 return caja_is_home_directory_file (dir, file->details->name);
3737}
3738
3739gboolean
3740caja_file_is_in_desktop (CajaFile *file)
3741{
3742 if (file->details->directory->details->location) {
3743 return caja_is_desktop_directory (file->details->directory->details->location);
3744 }
3745 return FALSE(0);
3746
3747}
3748
3749static gboolean
3750filter_hidden_partition_callback (gpointer data,
3751 gpointer callback_data)
3752{
3753 CajaFile *file;
3754 FilterOptions options;
3755
3756 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
3757 options = GPOINTER_TO_INT (callback_data)((gint) (glong) (callback_data));
3758
3759 return caja_file_should_show (file,
3760 options & SHOW_HIDDEN,
3761 TRUE(!(0)),
3762 options & SHOW_BACKUP);
3763}
3764
3765GList *
3766caja_file_list_filter_hidden (GList *files,
3767 gboolean show_hidden)
3768{
3769 GList *filtered_files;
3770 GList *removed_files;
3771
3772 /* FIXME bugzilla.gnome.org 40653:
3773 * Eventually this should become a generic filtering thingy.
3774 */
3775
3776 filtered_files = caja_file_list_copy (files);
3777 filtered_files = eel_g_list_partition (filtered_files,
3778 filter_hidden_partition_callback,
3779 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0))((gpointer) (glong) ((show_hidden ? SHOW_HIDDEN : 0))),
3780 &removed_files);
3781 caja_file_list_free (removed_files);
3782
3783 return filtered_files;
3784}
3785
3786char *
3787caja_file_get_metadata (CajaFile *file,
3788 const char *key,
3789 const char *default_metadata)
3790{
3791 guint id;
3792 char *value;
3793
3794 g_return_val_if_fail (key != NULL, g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_472
; if (key != ((void*)0)) _g_boolean_var_472 = 1; else _g_boolean_var_472
= 0; _g_boolean_var_472; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(g_strdup_inline (default_metadata)); } } while (0)
;
3795 g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_473
; if (key[0] != '\0') _g_boolean_var_473 = 1; else _g_boolean_var_473
= 0; _g_boolean_var_473; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (g_strdup_inline (default_metadata)); } } while (0)
;
3796
3797 if (file == NULL((void*)0) ||
3798 file->details->metadata == NULL((void*)0)) {
3799 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3800 }
3801
3802 g_return_val_if_fail (CAJA_IS_FILE (file), g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_474
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_474
= 1; else _g_boolean_var_474 = 0; _g_boolean_var_474; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (g_strdup_inline
(default_metadata)); } } while (0)
;
3803
3804 id = caja_metadata_get_id (key);
3805 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3806
3807 if (value) {
3808 return g_strdup (value)g_strdup_inline (value);
3809 }
3810 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3811}
3812
3813GList *
3814caja_file_get_metadata_list (CajaFile *file,
3815 const char *key)
3816{
3817 guint id;
3818 char **value;
3819
3820 g_return_val_if_fail (key != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_475
; if (key != ((void*)0)) _g_boolean_var_475 = 1; else _g_boolean_var_475
= 0; _g_boolean_var_475; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(((void*)0)); } } while (0)
;
3821 g_return_val_if_fail (key[0] != '\0', NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_476
; if (key[0] != '\0') _g_boolean_var_476 = 1; else _g_boolean_var_476
= 0; _g_boolean_var_476; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (((void*)0)); } } while (0)
;
3822
3823 if (file == NULL((void*)0) ||
3824 file->details->metadata == NULL((void*)0)) {
3825 return NULL((void*)0);
3826 }
3827
3828 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_477
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_477
= 1; else _g_boolean_var_477 = 0; _g_boolean_var_477; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
3829
3830 id = caja_metadata_get_id (key);
3831 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
3832
3833 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3834
3835 if (value) {
3836 GList *res;
3837 int i;
3838
3839 res = NULL((void*)0);
3840 for (i = 0; value[i] != NULL((void*)0); i++) {
3841 res = g_list_prepend (res, g_strdup (value[i])g_strdup_inline (value[i]));
3842 }
3843 return g_list_reverse (res);
3844 }
3845
3846 return NULL((void*)0);
3847}
3848
3849void
3850caja_file_set_metadata (CajaFile *file,
3851 const char *key,
3852 const char *default_metadata,
3853 const char *metadata)
3854{
3855 const char *val;
3856
3857 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_478
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_478
= 1; else _g_boolean_var_478 = 0; _g_boolean_var_478; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3858 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_479
; if (key != ((void*)0)) _g_boolean_var_479 = 1; else _g_boolean_var_479
= 0; _g_boolean_var_479; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3859 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_480
; if (key[0] != '\0') _g_boolean_var_480 = 1; else _g_boolean_var_480
= 0; _g_boolean_var_480; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3860
3861 val = metadata;
3862 if (val == NULL((void*)0)) {
3863 val = default_metadata;
3864 }
3865
3866 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3867 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3868 set_metadata, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
;
3869}
3870
3871void
3872caja_file_set_metadata_list (CajaFile *file,
3873 const char *key,
3874 GList *list)
3875{
3876 char **val;
3877 int len, i;
3878 GList *l;
3879
3880 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_481
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_481
= 1; else _g_boolean_var_481 = 0; _g_boolean_var_481; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3881 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_482
; if (key != ((void*)0)) _g_boolean_var_482 = 1; else _g_boolean_var_482
= 0; _g_boolean_var_482; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3882 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_483
; if (key[0] != '\0') _g_boolean_var_483 = 1; else _g_boolean_var_483
= 0; _g_boolean_var_483; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3883
3884 len = g_list_length (list);
3885 val = g_new (char *, len + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
3886 for (l = list, i = 0; l != NULL((void*)0); l = l->next, i++) {
3887 val[i] = l->data;
3888 }
3889 val[i] = NULL((void*)0);
3890
3891 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3892 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3893 set_metadata_as_list, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
;
3894
3895 g_free (val);
3896}
3897
3898
3899gboolean
3900caja_file_get_boolean_metadata (CajaFile *file,
3901 const char *key,
3902 gboolean default_metadata)
3903{
3904 char *result_as_string;
3905 gboolean result;
3906
3907 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_484
; if (key != ((void*)0)) _g_boolean_var_484 = 1; else _g_boolean_var_484
= 0; _g_boolean_var_484; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3908 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_485
; if (key[0] != '\0') _g_boolean_var_485 = 1; else _g_boolean_var_485
= 0; _g_boolean_var_485; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3909
3910 if (file == NULL((void*)0)) {
3911 return default_metadata;
3912 }
3913
3914 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_486
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_486
= 1; else _g_boolean_var_486 = 0; _g_boolean_var_486; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3915
3916 result_as_string = caja_file_get_metadata
3917 (file, key, default_metadata ? "true" : "false");
3918 g_assert (result_as_string != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_487
; if (result_as_string != ((void*)0)) _g_boolean_var_487 = 1;
else _g_boolean_var_487 = 0; _g_boolean_var_487; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file.c", 3918,
((const char*) (__func__)), "result_as_string != NULL"); } while
(0)
;
3919
3920 if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3921 result = TRUE(!(0));
3922 } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3923 result = FALSE(0);
3924 } else {
3925 g_error ("boolean metadata with value other than true or false");
3926 result = default_metadata;
3927 }
3928
3929 g_free (result_as_string);
3930 return result;
3931}
3932
3933int
3934caja_file_get_integer_metadata (CajaFile *file,
3935 const char *key,
3936 int default_metadata)
3937{
3938 char *result_as_string;
3939 char default_as_string[32];
3940 int result;
3941 char c;
3942
3943 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_488
; if (key != ((void*)0)) _g_boolean_var_488 = 1; else _g_boolean_var_488
= 0; _g_boolean_var_488; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3944 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_489
; if (key[0] != '\0') _g_boolean_var_489 = 1; else _g_boolean_var_489
= 0; _g_boolean_var_489; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3945
3946 if (file == NULL((void*)0)) {
3947 return default_metadata;
3948 }
3949 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_490
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_490
= 1; else _g_boolean_var_490 = 0; _g_boolean_var_490; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3950
3951 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3952 result_as_string = caja_file_get_metadata
3953 (file, key, default_as_string);
3954
3955 /* Normally we can't get a a NULL, but we check for it here to
3956 * handle the oddball case of a non-existent directory.
3957 */
3958 if (result_as_string == NULL((void*)0)) {
3959 result = default_metadata;
3960 } else {
3961 if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3962 result = default_metadata;
3963 }
3964 g_free (result_as_string);
3965 }
3966
3967 return result;
3968}
3969
3970static gboolean
3971get_time_from_time_string (const char *time_string,
3972 time_t *time)
3973{
3974 long scanned_time;
3975 char c;
3976
3977 g_assert (time != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_491
; if (time != ((void*)0)) _g_boolean_var_491 = 1; else _g_boolean_var_491
= 0; _g_boolean_var_491; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3977, ((const char*) (__func__
)), "time != NULL"); } while (0)
;
3978
3979 /* Only accept string if it has one integer with nothing
3980 * afterwards.
3981 */
3982 if (time_string == NULL((void*)0) ||
3983 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3984 return FALSE(0);
3985 }
3986 *time = (time_t) scanned_time;
3987 return TRUE(!(0));
3988}
3989
3990time_t
3991caja_file_get_time_metadata (CajaFile *file,
3992 const char *key)
3993{
3994 time_t time;
3995 char *time_string;
3996
3997 time_string = caja_file_get_metadata (file, key, NULL((void*)0));
3998 if (!get_time_from_time_string (time_string, &time)) {
3999 time = UNDEFINED_TIME((time_t) (-1));
4000 }
4001 g_free (time_string);
4002
4003 return time;
4004}
4005
4006void
4007caja_file_set_time_metadata (CajaFile *file,
4008 const char *key,
4009 time_t time)
4010{
4011 char time_str[21];
4012 char *metadata;
4013
4014 if (time != UNDEFINED_TIME((time_t) (-1))) {
4015 /* 2^64 turns out to be 20 characters */
4016 g_snprintf (time_str, 20, "%ld", (long int)time);
4017 time_str[20] = '\0';
4018 metadata = time_str;
4019 } else {
4020 metadata = NULL((void*)0);
4021 }
4022
4023 caja_file_set_metadata (file, key, NULL((void*)0), metadata);
4024}
4025
4026
4027void
4028caja_file_set_boolean_metadata (CajaFile *file,
4029 const char *key,
4030 gboolean default_metadata,
4031 gboolean metadata)
4032{
4033 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_492
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_492
= 1; else _g_boolean_var_492 = 0; _g_boolean_var_492; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4034 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_493
; if (key != ((void*)0)) _g_boolean_var_493 = 1; else _g_boolean_var_493
= 0; _g_boolean_var_493; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4035 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_494
; if (key[0] != '\0') _g_boolean_var_494 = 1; else _g_boolean_var_494
= 0; _g_boolean_var_494; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4036
4037 caja_file_set_metadata (file, key,
4038 default_metadata ? "true" : "false",
4039 metadata ? "true" : "false");
4040}
4041
4042void
4043caja_file_set_integer_metadata (CajaFile *file,
4044 const char *key,
4045 int default_metadata,
4046 int metadata)
4047{
4048 char value_as_string[32];
4049 char default_as_string[32];
4050
4051 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_495
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_495
= 1; else _g_boolean_var_495 = 0; _g_boolean_var_495; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4052 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_496
; if (key != ((void*)0)) _g_boolean_var_496 = 1; else _g_boolean_var_496
= 0; _g_boolean_var_496; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4053 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_497
; if (key[0] != '\0') _g_boolean_var_497 = 1; else _g_boolean_var_497
= 0; _g_boolean_var_497; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4054
4055 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4056 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4057
4058 caja_file_set_metadata (file, key,
4059 default_as_string, value_as_string);
4060}
4061
4062static const char *
4063caja_file_peek_display_name_collation_key (CajaFile *file)
4064{
4065 const char *res;
4066
4067 res = file->details->display_name_collation_key;
4068 if (res == NULL((void*)0))
4069 res = "";
4070
4071 return res;
4072}
4073
4074static const char *
4075caja_file_peek_display_name (CajaFile *file)
4076{
4077 /*
4078 stefano-k: Imported 15_nautilus_file_peek_crash.patch from debian nautilus
4079 Date: Thu, 27 Jan 2011 10:22:10 +0000
4080 Subject: Prevent a crash in nautilus_file_peek_display_name() on invalid NautilusFile
4081 This is more a workaround only, expect assert failures at other
4082 places when something bad happens. There's a race condition somewhere,
4083 this patch only prevents immediate crash.
4084 Patch by Marcus Husar <marcus.husar@rose.uni-heidelberg.de>
4085 https://bugzilla.gnome.org/show_bug.cgi?id=602500
4086 */
4087 if (file == NULL((void*)0) || caja_file_is_gone (file))
4088 return "";
4089
4090 /* Default to display name based on filename if its not set yet */
4091
4092 if (file->details->display_name == NULL((void*)0)) {
4093 const char *name;
4094
4095 name = file->details->name;
4096 if (g_utf8_validate (name, -1, NULL((void*)0))) {
4097 caja_file_set_display_name (file,
4098 name,
4099 NULL((void*)0),
4100 FALSE(0));
4101 } else {
4102 char *escaped_name;
4103
4104 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
4105 caja_file_set_display_name (file,
4106 escaped_name,
4107 NULL((void*)0),
4108 FALSE(0));
4109 g_free (escaped_name);
4110 }
4111 }
4112
4113 return file->details->display_name;
4114}
4115
4116char *
4117caja_file_get_display_name (CajaFile *file)
4118{
4119 return g_strdup (caja_file_peek_display_name (file))g_strdup_inline (caja_file_peek_display_name (file));
4120}
4121
4122char *
4123caja_file_get_edit_name (CajaFile *file)
4124{
4125 const char *res;
4126
4127 res = file->details->edit_name;
4128 if (res == NULL((void*)0))
4129 res = "";
4130
4131 return g_strdup (res)g_strdup_inline (res);
4132}
4133
4134char *
4135caja_file_get_name (CajaFile *file)
4136{
4137 return g_strdup (file->details->name)g_strdup_inline (file->details->name);
4138}
4139
4140/**
4141 * caja_file_get_description:
4142 * @file: a #CajaFile.
4143 *
4144 * Gets the standard::description key from @file, if
4145 * it has been cached.
4146 *
4147 * Returns: a string containing the value of the standard::description
4148 * key, or %NULL.
4149 */
4150char *
4151caja_file_get_description (CajaFile *file)
4152{
4153 return g_strdup (file->details->description)g_strdup_inline (file->details->description);
4154}
4155
4156void
4157caja_file_monitor_add (CajaFile *file,
4158 gconstpointer client,
4159 CajaFileAttributes attributes)
4160{
4161 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_498
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_498
= 1; else _g_boolean_var_498 = 0; _g_boolean_var_498; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4162 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_499
; if (client != ((void*)0)) _g_boolean_var_499 = 1; else _g_boolean_var_499
= 0; _g_boolean_var_499; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4163
4164 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4165 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4166 monitor_add, (file, client, attributes))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
;
4167}
4168
4169void
4170caja_file_monitor_remove (CajaFile *file,
4171 gconstpointer client)
4172{
4173 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_500
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_500
= 1; else _g_boolean_var_500 = 0; _g_boolean_var_500; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4174 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_501
; if (client != ((void*)0)) _g_boolean_var_501 = 1; else _g_boolean_var_501
= 0; _g_boolean_var_501; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4175
4176 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4177 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4178 monitor_remove, (file, client))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
;
4179}
4180
4181gboolean
4182caja_file_is_launcher (CajaFile *file)
4183{
4184 return file->details->is_launcher;
4185}
4186
4187gboolean
4188caja_file_is_foreign_link (CajaFile *file)
4189{
4190 return file->details->is_foreign_link;
4191}
4192
4193gboolean
4194caja_file_is_trusted_link (CajaFile *file)
4195{
4196 return file->details->is_trusted_link;
4197}
4198
4199gboolean
4200caja_file_has_activation_uri (CajaFile *file)
4201{
4202 return file->details->activation_uri != NULL((void*)0);
4203}
4204
4205
4206/* Return the uri associated with the passed-in file, which may not be
4207 * the actual uri if the file is an desktop file or a caja
4208 * xml link file.
4209 */
4210char *
4211caja_file_get_activation_uri (CajaFile *file)
4212{
4213 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_502
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_502
= 1; else _g_boolean_var_502 = 0; _g_boolean_var_502; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4214
4215 if (file->details->activation_uri != NULL((void*)0)) {
4216 return g_strdup (file->details->activation_uri)g_strdup_inline (file->details->activation_uri);
4217 }
4218
4219 return caja_file_get_uri (file);
4220}
4221
4222GFile *
4223caja_file_get_activation_location (CajaFile *file)
4224{
4225 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_503
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_503
= 1; else _g_boolean_var_503 = 0; _g_boolean_var_503; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4226
4227 if (file->details->activation_uri != NULL((void*)0)) {
4228 return g_file_new_for_uri (file->details->activation_uri);
4229 }
4230
4231 return caja_file_get_location (file);
4232}
4233
4234
4235char *
4236caja_file_get_drop_target_uri (CajaFile *file)
4237{
4238 char *uri, *target_uri;
4239 GFile *location;
4240
4241 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_504
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_504
= 1; else _g_boolean_var_504 = 0; _g_boolean_var_504; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4242
4243 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
4244 CajaDesktopLink *link;
4245
4246 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
4247
4248 if (link != NULL((void*)0)) {
4249 location = caja_desktop_link_get_activation_location (link);
4250 g_object_unref (link);
4251 if (location != NULL((void*)0)) {
4252 uri = g_file_get_uri (location);
4253 g_object_unref (location);
4254 return uri;
4255 }
4256 }
4257 }
4258
4259 uri = caja_file_get_uri (file);
4260
4261 /* Check for Caja link */
4262 if (caja_file_is_caja_link (file)) {
4263 location = caja_file_get_location (file);
4264 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
4265 if (g_file_is_native (location)) {
4266 target_uri = caja_link_local_get_link_uri (uri);
4267 if (target_uri != NULL((void*)0)) {
4268 g_free (uri);
4269 uri = target_uri;
4270 }
4271 }
4272 g_object_unref (location);
4273 }
4274
4275 return uri;
4276}
4277
4278static gboolean
4279is_uri_relative (const char *uri)
4280{
4281 char *scheme;
4282 gboolean ret;
4283
4284 scheme = g_uri_parse_scheme (uri);
4285 ret = (scheme == NULL((void*)0));
4286 g_free (scheme);
4287 return ret;
4288}
4289
4290static char *
4291get_custom_icon_metadata_uri (CajaFile *file)
4292{
4293 char *custom_icon_uri;
4294 char *uri;
4295
4296 uri = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
4297 if (uri != NULL((void*)0) &&
4298 caja_file_is_directory (file) &&
4299 is_uri_relative (uri)) {
4300 char *dir_uri;
4301
4302 dir_uri = caja_file_get_uri (file);
4303 custom_icon_uri = g_build_filename (dir_uri, uri, NULL((void*)0));
4304 g_free (dir_uri);
4305 g_free (uri);
4306 } else {
4307 custom_icon_uri = uri;
4308 }
4309 return custom_icon_uri;
4310}
4311
4312static GIcon *
4313get_custom_icon (CajaFile *file)
4314{
4315 char *custom_icon_uri;
4316 GFile *icon_file;
4317 GIcon *icon;
4318
4319 if (file == NULL((void*)0)) {
4320 return NULL((void*)0);
4321 }
4322
4323 icon = NULL((void*)0);
4324
4325 /* Metadata takes precedence */
4326 custom_icon_uri = get_custom_icon_metadata_uri (file);
4327
4328 if (custom_icon_uri) {
4329 icon_file = g_file_new_for_uri (custom_icon_uri);
4330 icon = g_file_icon_new (icon_file);
4331 g_object_unref (icon_file);
4332 g_free (custom_icon_uri);
4333 }
4334
4335 if (icon == NULL((void*)0) && file->details->got_link_info && file->details->custom_icon != NULL((void*)0)) {
4336 if (g_path_is_absolute (file->details->custom_icon)) {
4337 icon_file = g_file_new_for_path (file->details->custom_icon);
4338 icon = g_file_icon_new (icon_file);
4339 g_object_unref (icon_file);
4340 } else {
4341 icon = g_themed_icon_new (file->details->custom_icon);
4342 }
4343 }
4344
4345 return icon;
4346}
4347
4348
4349static guint64 cached_thumbnail_limit;
4350int cached_thumbnail_size;
4351static int show_image_thumbs;
4352
4353GFilesystemPreviewType
4354caja_file_get_filesystem_use_preview (CajaFile *file)
4355{
4356 GFilesystemPreviewType use_preview;
4357 CajaFile *parent;
4358
4359 parent = caja_file_get_parent (file);
4360 if (parent != NULL((void*)0)) {
4361 use_preview = parent->details->filesystem_use_preview;
4362 g_object_unref (parent);
4363 } else {
4364 use_preview = 0;
4365 }
4366
4367 return use_preview;
4368}
4369
4370gboolean
4371caja_file_should_show_thumbnail (CajaFile *file)
4372{
4373 const char *mime_type;
4374 GFilesystemPreviewType use_preview;
4375
4376 use_preview = caja_file_get_filesystem_use_preview (file);
4377
4378 mime_type = file->details->mime_type;
4379 if (mime_type == NULL((void*)0)) {
4380 mime_type = "application/octet-stream";
4381 }
4382
4383 /* If the thumbnail has already been created, don't care about the size
4384 * of the original file.
4385 */
4386 if (caja_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4387 file->details->thumbnail_path == NULL((void*)0) &&
4388 caja_file_get_size (file) > cached_thumbnail_limit) {
4389 return FALSE(0);
4390 }
4391
4392 if (show_image_thumbs == CAJA_SPEED_TRADEOFF_ALWAYS) {
4393 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4394 return FALSE(0);
4395 } else {
4396 return TRUE(!(0));
4397 }
4398 } else if (show_image_thumbs == CAJA_SPEED_TRADEOFF_NEVER) {
4399 return FALSE(0);
4400 } else {
4401 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4402 /* file system says to never thumbnail anything */
4403 return FALSE(0);
4404 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4405 /* file system says we should treat file as if it's local */
4406 return TRUE(!(0));
4407 } else {
4408 /* only local files */
4409 return caja_file_is_local (file);
4410 }
4411 }
4412
4413 return FALSE(0);
4414}
4415
4416static void
4417prepend_icon_name (const char *name,
4418 GThemedIcon *icon)
4419{
4420 g_themed_icon_prepend_name(icon, name);
4421}
4422
4423GIcon *
4424caja_file_get_gicon (CajaFile *file,
4425 CajaFileIconFlags flags)
4426{
4427 const char * const * names;
4428 GIcon *icon, *mount_icon = NULL((void*)0), *emblemed_icon;
4429 gboolean is_folder = FALSE(0), is_preview = FALSE(0), is_inode_directory = FALSE(0);
4430
4431 if (file == NULL((void*)0)) {
4432 return NULL((void*)0);
4433 }
4434
4435 icon = get_custom_icon (file);
4436 if (icon != NULL((void*)0)) {
4437 return icon;
4438 }
4439
4440 if (file->details->icon) {
4441 icon = NULL((void*)0);
4442
4443 /* fetch the mount icon here, we'll use it later */
4444 if (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4445 flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4446 GMount *mount;
4447
4448 mount = caja_file_get_mount (file);
4449
4450 if (mount != NULL((void*)0)) {
4451 mount_icon = g_mount_get_icon (mount);
4452 g_object_unref (mount);
4453 }
4454 }
4455
4456 if (((flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4457 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4458 (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4459 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4460 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4461 ((flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4462 caja_file_has_open_window (file))) &&
4463 G_IS_THEMED_ICON (file->details->icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file->details->icon)); GType __t = ((g_themed_icon_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; }))))
) {
4464 GPtrArray *prepend_array;
4465 int i;
4466
4467 names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon)((((GThemedIcon*) (void *) ((file->details->icon))))));
4468 prepend_array = g_ptr_array_new ();
4469
4470 for (i = 0; names[i] != NULL((void*)0); i++) {
4471 const char *name;
4472
4473 name = names[i];
4474
4475 if (strcmp (name, "folder") == 0) {
4476 is_folder = TRUE(!(0));
4477 }
4478 if (strcmp (name, "inode-directory") == 0) {
4479 is_inode_directory = TRUE(!(0));
4480 }
4481 if (strcmp (name, "text-x-generic") == 0 &&
4482 (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4483 is_preview = TRUE(!(0));
4484 }
4485 }
4486
4487 /* Here, we add icons in reverse order of precedence,
4488 * because they are later prepended */
4489 if (is_preview) {
4490 g_ptr_array_add (prepend_array, "text-x-preview");
4491 }
4492
4493 /* "folder" should override "inode-directory", not the other way around */
4494 if (is_inode_directory) {
4495 g_ptr_array_add (prepend_array, "folder");
4496 }
4497 if (is_folder && (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4498 g_ptr_array_add (prepend_array, "folder-open");
4499 }
4500 if (is_folder &&
4501 (flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4502 caja_file_has_open_window (file)) {
4503 g_ptr_array_add (prepend_array, "folder-visiting");
4504 }
4505 if (is_folder &&
4506 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4507 g_ptr_array_add (prepend_array, "folder-drag-accept");
4508 }
4509
4510 if (prepend_array->len) {
4511 /* When constructing GThemed Icon, pointers from the array
4512 * are reused, but not the array itself, so the cast is safe */
4513 icon = g_themed_icon_new_from_names ((char**) names, -1);
4514 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4515 }
4516
4517 g_ptr_array_free (prepend_array, TRUE(!(0)));
4518 }
4519
4520 if (icon == NULL((void*)0)) {
4521 icon = g_object_ref (file->details->icon)((__typeof__ (file->details->icon)) (g_object_ref) (file
->details->icon))
;
4522 }
4523
4524 if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4525 mount_icon != NULL((void*)0)) {
4526 g_object_unref (icon);
4527 icon = mount_icon;
4528 } else if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4529 mount_icon != NULL((void*)0) && !g_icon_equal (mount_icon, icon)) {
4530 GEmblem *emblem;
4531
4532 emblem = g_emblem_new (mount_icon);
4533 emblemed_icon = g_emblemed_icon_new (icon, emblem);
4534
4535 g_object_unref (emblem);
4536 g_object_unref (icon);
4537 g_object_unref (mount_icon);
4538
4539 icon = emblemed_icon;
4540 } else if (mount_icon != NULL((void*)0)) {
4541 g_object_unref (mount_icon);
4542 }
4543
4544 return icon;
4545 }
4546
4547 return g_themed_icon_new ("text-x-generic");
4548}
4549
4550static GIcon *
4551get_default_file_icon (CajaFileIconFlags flags)
4552{
4553 static GIcon *fallback_icon = NULL((void*)0);
4554 static GIcon *fallback_icon_preview = NULL((void*)0);
4555 if (fallback_icon == NULL((void*)0)) {
4556 fallback_icon = g_themed_icon_new ("text-x-generic");
4557 fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4558 g_themed_icon_append_name (G_THEMED_ICON (fallback_icon_preview)((((GThemedIcon*) (void *) ((fallback_icon_preview))))), "text-x-generic");
4559 }
4560 if (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4561 return fallback_icon_preview;
4562 } else {
4563 return fallback_icon;
4564 }
4565}
4566
4567CajaIconInfo *
4568caja_file_get_icon (CajaFile *file,
4569 int size,
4570 int scale,
4571 CajaFileIconFlags flags)
4572{
4573 CajaIconInfo *icon;
4574 GIcon *gicon;
4575 GdkPixbuf *scaled_pixbuf;
4576
4577 if (file == NULL((void*)0)) {
4578 return NULL((void*)0);
4579 }
4580
4581 gicon = get_custom_icon (file);
4582 if (gicon) {
4583 GdkPixbuf *pixbuf;
4584
4585 icon = caja_icon_info_lookup (gicon, size, scale);
4586 g_object_unref (gicon);
4587
4588 pixbuf = caja_icon_info_get_pixbuf (icon);
4589 if (pixbuf != NULL((void*)0)) {
4590 if (!file->details->is_launcher && !gdk_pixbuf_get_has_alpha (pixbuf)) {
4591 caja_ui_frame_image (&pixbuf);
4592 }
4593 g_object_unref (icon);
4594
4595 icon = caja_icon_info_new_for_pixbuf (pixbuf, scale);
4596 g_object_unref (pixbuf);
4597 }
4598
4599 return icon;
4600 }
4601
4602 if (flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4603 caja_file_should_show_thumbnail (file)) {
4604 int modified_size;
4605
4606 if (flags & CAJA_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4607 modified_size = size * scale;
4608 } else {
4609 modified_size = size * scale * cached_thumbnail_size / CAJA_ICON_SIZE_STANDARD48;
4610 }
4611
4612 if (file->details->thumbnail) {
4613 int w, h, s;
4614 double thumb_scale;
4615 GdkPixbuf *raw_pixbuf;
4616
4617 raw_pixbuf = g_object_ref (file->details->thumbnail)((__typeof__ (file->details->thumbnail)) (g_object_ref)
(file->details->thumbnail))
;
4618
4619 w = gdk_pixbuf_get_width (raw_pixbuf);
4620 h = gdk_pixbuf_get_height (raw_pixbuf);
4621
4622 s = MAX (w, h)(((w) > (h)) ? (w) : (h));
4623 /* Don't scale up small thumbnails in the standard view */
4624 if (s <= cached_thumbnail_size) {
4625 thumb_scale = (double)size / CAJA_ICON_SIZE_STANDARD48;
4626 }
4627 else {
4628 thumb_scale = (double)modified_size / s;
4629 }
4630 /* Make sure that icons don't get smaller than CAJA_ICON_SIZE_SMALLEST */
4631 if (s*thumb_scale <= CAJA_ICON_SIZE_SMALLEST16) {
4632 thumb_scale = (double) CAJA_ICON_SIZE_SMALLEST16 / s;
4633 }
4634
4635 scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4636 MAX (w * thumb_scale, 1)(((w * thumb_scale) > (1)) ? (w * thumb_scale) : (1)),
4637 MAX (h * thumb_scale, 1)(((h * thumb_scale) > (1)) ? (h * thumb_scale) : (1)),
4638 GDK_INTERP_BILINEAR);
4639
4640 /* Render frames only for thumbnails of non-image files
4641 and for images with no alpha channel. */
4642 gboolean is_image = file->details->mime_type &&
4643 (strncmp (file->details->mime_type, "image/", 6) == 0);
4644 if (!is_image || !gdk_pixbuf_get_has_alpha (raw_pixbuf)) {
4645 caja_ui_frame_image (&scaled_pixbuf);
4646 }
4647
4648 g_object_unref (raw_pixbuf);
4649
4650 /* Don't scale up if more than 25%, then read the original
4651 image instead. We don't want to compare to exactly 100%,
4652 since the zoom level 150% gives thumbnails at 144, which is
4653 ok to scale up from 128. */
4654 if (modified_size > 128 * 1.25 * scale &&
4655 !file->details->thumbnail_wants_original &&
4656 caja_can_thumbnail_internally (file)) {
4657 /* Invalidate if we resize upward */
4658 file->details->thumbnail_wants_original = TRUE(!(0));
4659 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_THUMBNAIL);
4660 }
4661
4662 icon = caja_icon_info_new_for_pixbuf (scaled_pixbuf, scale);
4663 g_object_unref (scaled_pixbuf);
4664 return icon;
4665 } else if (file->details->thumbnail_path == NULL((void*)0) &&
4666 file->details->can_read &&
4667 !file->details->is_thumbnailing &&
4668 !file->details->thumbnailing_failed) {
4669 if (caja_can_thumbnail (file)) {
4670 caja_create_thumbnail (file);
4671 }
4672 }
4673 }
4674
4675 if (file->details->is_thumbnailing &&
4676 flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS)
4677 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING"image-loading");
4678 else
4679 gicon = caja_file_get_gicon (file, flags);
4680
4681 if (gicon) {
4682 icon = caja_icon_info_lookup (gicon, size, scale);
4683 g_object_unref (gicon);
4684 return icon;
4685 } else {
4686 return caja_icon_info_lookup (get_default_file_icon (flags), size, scale);
4687 }
4688}
4689
4690cairo_surface_t *
4691caja_file_get_icon_surface (CajaFile *file,
4692 int size,
4693 gboolean force_size,
4694 int scale,
4695 CajaFileIconFlags flags)
4696{
4697 CajaIconInfo *info;
4698 cairo_surface_t *surface;
4699
4700 info = caja_file_get_icon (file, size, scale, flags);
4701 if (force_size) {
4702 surface = caja_icon_info_get_surface_at_size (info, size);
4703 } else {
4704 surface = caja_icon_info_get_surface (info);
4705 }
4706 g_object_unref (info);
4707
4708 return surface;
4709}
4710
4711char *
4712caja_file_get_custom_icon (CajaFile *file)
4713{
4714 char *custom_icon;
4715
4716 if (file == NULL((void*)0)) {
4717 return NULL((void*)0);
4718 }
4719
4720 /* Metadata takes precedence */
4721 custom_icon = get_custom_icon_metadata_uri (file);
4722
4723 if (custom_icon == NULL((void*)0) && file->details->got_link_info) {
4724 custom_icon = g_strdup (file->details->custom_icon)g_strdup_inline (file->details->custom_icon);
4725 }
4726
4727 return custom_icon;
4728}
4729
4730
4731gboolean
4732caja_file_get_date (CajaFile *file,
4733 CajaDateType date_type,
4734 time_t *date)
4735{
4736 if (date != NULL((void*)0)) {
4737 *date = 0;
4738 }
4739
4740 g_return_val_if_fail (date_type == CAJA_DATE_TYPE_CHANGEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_505
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_505 = 1; else _g_boolean_var_505 = 0; _g_boolean_var_505
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4741 || date_type == CAJA_DATE_TYPE_ACCESSEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_505
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_505 = 1; else _g_boolean_var_505 = 0; _g_boolean_var_505
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4742 || date_type == CAJA_DATE_TYPE_MODIFIEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_505
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_505 = 1; else _g_boolean_var_505 = 0; _g_boolean_var_505
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4743 || date_type == CAJA_DATE_TYPE_CREATEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_505
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_505 = 1; else _g_boolean_var_505 = 0; _g_boolean_var_505
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4744 || date_type == CAJA_DATE_TYPE_TRASHEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_505
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_505 = 1; else _g_boolean_var_505 = 0; _g_boolean_var_505
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4745 || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_505
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_505 = 1; else _g_boolean_var_505 = 0; _g_boolean_var_505
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
;
4746
4747 if (file == NULL((void*)0)) {
4748 return FALSE(0);
4749 }
4750
4751 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_506
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_506
= 1; else _g_boolean_var_506 = 0; _g_boolean_var_506; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
4752
4753 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4754 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4755 get_date, (file, date_type, date))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
;
4756}
4757
4758static char *
4759caja_file_get_where_string (CajaFile *file)
4760{
4761 if (file == NULL((void*)0)) {
4762 return NULL((void*)0);
4763 }
4764
4765 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_507
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_507
= 1; else _g_boolean_var_507 = 0; _g_boolean_var_507; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4766
4767 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4768 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4769 get_where_string, (file))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
;
4770}
4771
4772static const char *TODAY_TIME_FORMATS [] = {
4773 /* Today, use special word.
4774 * strftime patterns preceeded with the widest
4775 * possible resulting string for that pattern.
4776 *
4777 * Note to localizers: You can look at man strftime
4778 * for details on the format, but you should only use
4779 * the specifiers from the C standard, not extensions.
4780 * These include "%" followed by one of
4781 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
4782 * in the Caja version of strftime that can be
4783 * used (and match GNU extensions). Putting a "-"
4784 * between the "%" and any numeric directive will turn
4785 * off zero padding, and putting a "_" there will use
4786 * space padding instead of zero padding.
4787 */
4788 N_("today at 00:00:00 PM")("today at 00:00:00 PM"),
4789 N_("today at %-I:%M:%S %p")("today at %-I:%M:%S %p"),
4790
4791 N_("today at 00:00 PM")("today at 00:00 PM"),
4792 N_("today at %-I:%M %p")("today at %-I:%M %p"),
4793
4794 N_("today, 00:00 PM")("today, 00:00 PM"),
4795 N_("today, %-I:%M %p")("today, %-I:%M %p"),
4796
4797 N_("today")("today"),
4798 N_("today")("today"),
4799
4800 NULL((void*)0)
4801};
4802
4803static const char *YESTERDAY_TIME_FORMATS [] = {
4804 /* Yesterday, use special word.
4805 * Note to localizers: Same issues as "today" string.
4806 */
4807 N_("yesterday at 00:00:00 PM")("yesterday at 00:00:00 PM"),
4808 N_("yesterday at %-I:%M:%S %p")("yesterday at %-I:%M:%S %p"),
4809
4810 N_("yesterday at 00:00 PM")("yesterday at 00:00 PM"),
4811 N_("yesterday at %-I:%M %p")("yesterday at %-I:%M %p"),
4812
4813 N_("yesterday, 00:00 PM")("yesterday, 00:00 PM"),
4814 N_("yesterday, %-I:%M %p")("yesterday, %-I:%M %p"),
4815
4816 N_("yesterday")("yesterday"),
4817 N_("yesterday")("yesterday"),
4818
4819 NULL((void*)0)
4820};
4821
4822static const char *CURRENT_WEEK_TIME_FORMATS [] = {
4823 /* Current week, include day of week.
4824 * Note to localizers: Same issues as "today" string.
4825 * The width measurement templates correspond to
4826 * the day/month name with the most letters.
4827 */
4828 N_("Wednesday, September 00 0000 at 00:00:00 PM")("Wednesday, September 00 0000 at 00:00:00 PM"),
4829 N_("%A, %B %-d %Y at %-I:%M:%S %p")("%A, %B %-d %Y at %-I:%M:%S %p"),
4830
4831 N_("Mon, Oct 00 0000 at 00:00:00 PM")("Mon, Oct 00 0000 at 00:00:00 PM"),
4832 N_("%a, %b %-d %Y at %-I:%M:%S %p")("%a, %b %-d %Y at %-I:%M:%S %p"),
4833
4834 N_("Mon, Oct 00 0000 at 00:00 PM")("Mon, Oct 00 0000 at 00:00 PM"),
4835 N_("%a, %b %-d %Y at %-I:%M %p")("%a, %b %-d %Y at %-I:%M %p"),
4836
4837 N_("Oct 00 0000 at 00:00 PM")("Oct 00 0000 at 00:00 PM"),
4838 N_("%b %-d %Y at %-I:%M %p")("%b %-d %Y at %-I:%M %p"),
4839
4840 N_("Oct 00 0000, 00:00 PM")("Oct 00 0000, 00:00 PM"),
4841 N_("%b %-d %Y, %-I:%M %p")("%b %-d %Y, %-I:%M %p"),
4842
4843 N_("00/00/00, 00:00 PM")("00/00/00, 00:00 PM"),
4844 N_("%m/%-d/%y, %-I:%M %p")("%m/%-d/%y, %-I:%M %p"),
4845
4846 N_("00/00/00")("00/00/00"),
4847 N_("%m/%d/%y")("%m/%d/%y"),
4848
4849 NULL((void*)0)
4850};
4851
4852static char *
4853caja_file_fit_date_as_string (CajaFile *file,
4854 CajaDateType date_type,
4855 int width,
4856 CajaWidthMeasureCallback measure_callback,
4857 CajaTruncateCallback truncate_callback,
4858 void *measure_context)
4859{
4860 time_t file_time_raw;
4861 const char **formats;
4862 const char *format;
4863 char *date_string;
4864 gchar *result = NULL((void*)0);
4865 int i;
4866 GDateTime *date_time, *today, *end_of_today;
4867 GTimeSpan file_date_age;
4868
4869 if (!caja_file_get_date (file, date_type, &file_time_raw)) {
4870 return NULL((void*)0);
4871 }
4872
4873 date_time = g_date_time_new_from_unix_local (file_time_raw);
4874
4875 if (date_format_pref == CAJA_DATE_FORMAT_LOCALE) {
4876 result = g_date_time_format (date_time, "%c");
4877 goto out;
4878 } else if (date_format_pref == CAJA_DATE_FORMAT_ISO) {
4879 result = g_date_time_format (date_time, "%Y-%m-%d %H:%M:%S");
4880 goto out;
4881 }
4882
4883 today = g_date_time_new_now_local ();
4884 end_of_today = g_date_time_add_full (today, 0, 0, 1,
4885 -1 * g_date_time_get_hour (today),
4886 -1 * g_date_time_get_minute (today),
4887 -1.0 * g_date_time_get_seconds (today));
4888 g_date_time_unref (today);
4889
4890 file_date_age = g_date_time_difference (end_of_today, date_time);
4891 g_date_time_unref (end_of_today);
4892
4893 /* Format varies depending on how old the date is. This minimizes
4894 * the length (and thus clutter & complication) of typical dates
4895 * while providing sufficient detail for recent dates to make
4896 * them maximally understandable at a glance. Keep all format
4897 * strings separate rather than combining bits & pieces for
4898 * internationalization's sake.
4899 */
4900
4901 if (file_date_age <= 0 || file_date_age > 2 * G_TIME_SPAN_DAY((86400000000L))) {
4902 formats = CURRENT_WEEK_TIME_FORMATS;
4903 } else if (file_date_age > G_TIME_SPAN_DAY((86400000000L))) {
4904 formats = YESTERDAY_TIME_FORMATS;
4905 } else {
4906 formats = TODAY_TIME_FORMATS;
4907 }
4908
4909 /* Find the date format that just fits the required width. Instead of measuring
4910 * the resulting string width directly, measure the width of a template that represents
4911 * the widest possible version of a date in a given format. This is done by using M, m
4912 * and 0 for the variable letters/digits respectively.
4913 */
4914 format = NULL((void*)0);
4915
4916 for (i = 0; ; i += 2) {
4917 const char *width_template;
4918
4919 width_template = (formats [i] ? _(formats [i])dcgettext (((void*)0), formats [i], 5) : NULL((void*)0));
4920 if (width_template == NULL((void*)0)) {
4921 /* no more formats left */
4922 g_assert (format != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_508
; if (format != ((void*)0)) _g_boolean_var_508 = 1; else _g_boolean_var_508
= 0; _g_boolean_var_508; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 4922, ((const char*) (__func__
)), "format != NULL"); } while (0)
;
4923
4924 /* Can't fit even the shortest format -- return an ellipsized form in the
4925 * shortest format
4926 */
4927
4928 date_string = g_date_time_format (date_time, format);
4929
4930 if (truncate_callback == NULL((void*)0)) {
4931 result = date_string;
4932 break;
4933 }
4934
4935 result = (* truncate_callback) (date_string, width, measure_context);
4936 g_free (date_string);
4937 break;
4938 }
4939
4940 format = _(formats [i + 1])dcgettext (((void*)0), formats [i + 1], 5);
4941
4942 if (measure_callback == NULL((void*)0)) {
4943 /* don't care about fitting the width */
4944 break;
4945 }
4946
4947 if ((* measure_callback) (width_template, measure_context) <= width) {
4948 /* The template fits, this is the format we can fit. */
4949 break;
4950 }
4951 }
4952
4953 if (result == NULL((void*)0)) {
4954 result = g_date_time_format (date_time, format);
4955 }
4956
4957out:
4958 g_date_time_unref (date_time);
4959 return result;
4960}
4961
4962/**
4963 * caja_file_fit_modified_date_as_string:
4964 *
4965 * Get a user-displayable string representing a file modification date,
4966 * truncated to @width using the measuring and truncating callbacks.
4967 * @file: CajaFile representing the file in question.
4968 * @width: The desired resulting string width.
4969 * @measure_callback: The callback used to measure the string width.
4970 * @truncate_callback: The callback used to truncate the string to a desired width.
4971 * @measure_context: Data neede when measuring and truncating.
4972 *
4973 * Returns: Newly allocated string ready to display to the user.
4974 *
4975 **/
4976char *
4977caja_file_fit_modified_date_as_string (CajaFile *file,
4978 int width,
4979 CajaWidthMeasureCallback measure_callback,
4980 CajaTruncateCallback truncate_callback,
4981 void *measure_context)
4982{
4983 return caja_file_fit_date_as_string (file, CAJA_DATE_TYPE_MODIFIED,
4984 width, measure_callback, truncate_callback, measure_context);
4985}
4986
4987static char *
4988caja_file_get_trash_original_file_parent_as_string (CajaFile *file)
4989{
4990 if (file->details->trash_orig_path != NULL((void*)0)) {
4991 CajaFile *orig_file, *parent;
4992 GFile *location;
4993 char *filename;
4994
4995 orig_file = caja_file_get_trash_original_file (file);
4996 parent = caja_file_get_parent (orig_file);
4997 location = caja_file_get_location (parent);
4998
4999 filename = g_file_get_parse_name (location);
5000
5001 g_object_unref (location);
5002 caja_file_unref (parent);
5003 caja_file_unref (orig_file);
5004
5005 return filename;
5006 }
5007
5008 return NULL((void*)0);
5009}
5010
5011/**
5012 * caja_file_get_date_as_string:
5013 *
5014 * Get a user-displayable string representing a file modification date.
5015 * The caller is responsible for g_free-ing this string.
5016 * @file: CajaFile representing the file in question.
5017 *
5018 * Returns: Newly allocated string ready to display to the user.
5019 *
5020 **/
5021static char *
5022caja_file_get_date_as_string (CajaFile *file, CajaDateType date_type)
5023{
5024 return caja_file_fit_date_as_string (file, date_type,
5025 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5026}
5027
5028static CajaSpeedTradeoffValue show_directory_item_count;
5029static CajaSpeedTradeoffValue show_text_in_icons;
5030
5031static void
5032show_text_in_icons_changed_callback (gpointer callback_data)
5033{
5034 show_text_in_icons = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS"show-icon-text");
5035}
5036
5037static void
5038show_directory_item_count_changed_callback (gpointer callback_data)
5039{
5040 show_directory_item_count = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS"show-directory-item-counts");
5041}
5042
5043static gboolean
5044get_speed_tradeoff_preference_for_file (CajaFile *file, CajaSpeedTradeoffValue value)
5045{
5046 GFilesystemPreviewType use_preview;
5047
5048 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_509
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_509
= 1; else _g_boolean_var_509 = 0; _g_boolean_var_509; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5049
5050 use_preview = caja_file_get_filesystem_use_preview (file);
5051
5052 if (value == CAJA_SPEED_TRADEOFF_ALWAYS) {
5053 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5054 return FALSE(0);
5055 } else {
5056 return TRUE(!(0));
5057 }
5058 }
5059
5060 if (value == CAJA_SPEED_TRADEOFF_NEVER) {
5061 return FALSE(0);
5062 }
5063
5064 g_assert (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_510
; if (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY) _g_boolean_var_510
= 1; else _g_boolean_var_510 = 0; _g_boolean_var_510; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5064, ((const char*) (__func__)), "value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY"
); } while (0)
;
5065
5066 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5067 /* file system says to never preview anything */
5068 return FALSE(0);
5069 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
5070 /* file system says we should treat file as if it's local */
5071 return TRUE(!(0));
5072 } else {
5073 /* only local files */
5074 return caja_file_is_local (file);
5075 }
5076}
5077
5078gboolean
5079caja_file_should_show_directory_item_count (CajaFile *file)
5080{
5081 static gboolean show_directory_item_count_callback_added = FALSE(0);
5082
5083 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_511
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_511
= 1; else _g_boolean_var_511 = 0; _g_boolean_var_511; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5084
5085 if (file->details->mime_type &&
5086 strcmp (file->details->mime_type, "x-directory/smb-share") == 0) {
5087 return FALSE(0);
5088 }
5089
5090 /* Add the callback once for the life of our process */
5091 if (!show_directory_item_count_callback_added) {
5092 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5093 "changed::" CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5094 G_CALLBACK(show_directory_item_count_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5095 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5096 show_directory_item_count_callback_added = TRUE(!(0));
5097
5098 /* Peek for the first time */
5099 show_directory_item_count_changed_callback (NULL((void*)0));
5100 }
5101
5102 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5103}
5104
5105gboolean
5106caja_file_should_show_type (CajaFile *file)
5107{
5108 char *uri;
5109 gboolean ret;
5110
5111 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_512
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_512
= 1; else _g_boolean_var_512 = 0; _g_boolean_var_512; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5112
5113 uri = caja_file_get_uri (file);
5114 ret = ((strcmp (uri, "computer:///") != 0) &&
5115 (strcmp (uri, "network:///") != 0) &&
5116 (strcmp (uri, "smb:///") != 0));
5117 g_free (uri);
5118
5119 return ret;
5120}
5121
5122gboolean
5123caja_file_should_get_top_left_text (CajaFile *file)
5124{
5125 static gboolean show_text_in_icons_callback_added = FALSE(0);
5126
5127 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_513
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_513
= 1; else _g_boolean_var_513 = 0; _g_boolean_var_513; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5128
5129 /* Add the callback once for the life of our process */
5130 if (!show_text_in_icons_callback_added) {
5131 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5132 "changed::" CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5133 G_CALLBACK (show_text_in_icons_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5134 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5135 show_text_in_icons_callback_added = TRUE(!(0));
5136
5137 /* Peek for the first time */
5138 show_text_in_icons_changed_callback (NULL((void*)0));
5139 }
5140
5141 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_ALWAYS) {
5142 return TRUE(!(0));
5143 }
5144
5145 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_NEVER) {
5146 return FALSE(0);
5147 }
5148
5149 return get_speed_tradeoff_preference_for_file (file, show_text_in_icons);
5150}
5151
5152/**
5153 * caja_file_get_directory_item_count
5154 *
5155 * Get the number of items in a directory.
5156 * @file: CajaFile representing a directory.
5157 * @count: Place to put count.
5158 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5159 * the item count from being read on this directory. Otherwise set to FALSE.
5160 *
5161 * Returns: TRUE if count is available.
5162 *
5163 **/
5164gboolean
5165caja_file_get_directory_item_count (CajaFile *file,
5166 guint *count,
5167 gboolean *count_unreadable)
5168{
5169 if (count != NULL((void*)0)) {
5170 *count = 0;
5171 }
5172 if (count_unreadable != NULL((void*)0)) {
5173 *count_unreadable = FALSE(0);
5174 }
5175
5176 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_514
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_514
= 1; else _g_boolean_var_514 = 0; _g_boolean_var_514; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5177
5178 if (!caja_file_is_directory (file)) {
5179 return FALSE(0);
5180 }
5181
5182 if (!caja_file_should_show_directory_item_count (file)) {
5183 return FALSE(0);
5184 }
5185
5186 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5187 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5188 get_item_count, (file, count, count_unreadable))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
;
5189}
5190
5191/**
5192 * caja_file_get_deep_counts
5193 *
5194 * Get the statistics about items inside a directory.
5195 * @file: CajaFile representing a directory or file.
5196 * @directory_count: Place to put count of directories inside.
5197 * @files_count: Place to put count of files inside.
5198 * @unreadable_directory_count: Number of directories encountered
5199 * that were unreadable.
5200 * @total_size: Total size of all files and directories visited.
5201 * @total_size_on_disk: Total size on disk of all files and directories visited.
5202 * @force: Whether the deep counts should even be collected if
5203 * caja_file_should_show_directory_item_count returns FALSE
5204 * for this file.
5205 *
5206 * Returns: Status to indicate whether sizes are available.
5207 *
5208 **/
5209CajaRequestStatus
5210caja_file_get_deep_counts (CajaFile *file,
5211 guint *directory_count,
5212 guint *file_count,
5213 guint *unreadable_directory_count,
5214 goffset *total_size,
5215 goffset *total_size_on_disk,
5216 gboolean force)
5217{
5218 if (directory_count != NULL((void*)0)) {
5219 *directory_count = 0;
5220 }
5221 if (file_count != NULL((void*)0)) {
5222 *file_count = 0;
5223 }
5224 if (unreadable_directory_count != NULL((void*)0)) {
5225 *unreadable_directory_count = 0;
5226 }
5227 if (total_size != NULL((void*)0)) {
5228 *total_size = 0;
5229 }
5230 if (total_size_on_disk != NULL((void*)0)) {
5231 *total_size_on_disk = 0;
5232 }
5233
5234 g_return_val_if_fail (CAJA_IS_FILE (file), CAJA_REQUEST_DONE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_515
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_515
= 1; else _g_boolean_var_515 = 0; _g_boolean_var_515; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (CAJA_REQUEST_DONE
); } } while (0)
;
5235
5236 if (!force && !caja_file_should_show_directory_item_count (file)) {
5237 /* Set field so an existing value isn't treated as up-to-date
5238 * when preference changes later.
5239 */
5240 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5241 return file->details->deep_counts_status;
5242 }
5243
5244 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5245 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5246 get_deep_counts, (file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5247 directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5248 file_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5249 unreadable_directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5250 total_size,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5251 total_size_on_disk))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
;
5252}
5253
5254void
5255caja_file_recompute_deep_counts (CajaFile *file)
5256{
5257 if (file->details->deep_counts_status != CAJA_REQUEST_IN_PROGRESS) {
5258 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5259 if (file->details->directory != NULL((void*)0)) {
5260 caja_directory_add_file_to_work_queue (file->details->directory, file);
5261 caja_directory_async_state_changed (file->details->directory);
5262 }
5263 }
5264}
5265
5266gboolean
5267caja_file_can_get_size (CajaFile *file)
5268{
5269 return file->details->size == -1;
5270}
5271
5272
5273/**
5274 * caja_file_get_size
5275 *
5276 * Get the file size.
5277 * @file: CajaFile representing the file in question.
5278 *
5279 * Returns: Size in bytes.
5280 *
5281 **/
5282goffset
5283caja_file_get_size (CajaFile *file)
5284{
5285 /* Before we have info on the file, we don't know the size. */
5286 if (file->details->size == -1)
5287 return 0;
5288 return file->details->size;
5289}
5290
5291/**
5292 * caja_file_get_size_on_disk
5293 *
5294 * Get the file size on disk (how many bytes is using on the filesystem).
5295 * e.g.: usually files with 1 byte will use a whole inode so it will return the
5296 * size of 1 inode. If the file is sparse the size on disk will be equal or less
5297 * than the size of the file.
5298 * @file: CajaFile representing the file in question.
5299 *
5300 * Returns: Size in bytes.
5301 *
5302 **/
5303goffset
5304caja_file_get_size_on_disk (CajaFile *file)
5305{
5306 /* Before we have info on the file, we don't know the size. */
5307 if (file->details->size_on_disk == -1)
5308 return 0;
5309 return file->details->size_on_disk;
5310}
5311
5312time_t
5313caja_file_get_mtime (CajaFile *file)
5314{
5315 return file->details->mtime;
5316}
5317
5318
5319static void
5320set_attributes_get_info_callback (GObject *source_object,
5321 GAsyncResult *res,
5322 gpointer callback_data)
5323{
5324 CajaFileOperation *op;
5325 GFileInfo *new_info;
5326 GError *error;
5327
5328 op = callback_data;
5329
5330 error = NULL((void*)0);
5331 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
5332 if (new_info != NULL((void*)0)) {
5333 if (caja_file_update_info (op->file, new_info)) {
5334 caja_file_changed (op->file);
5335 }
5336 g_object_unref (new_info);
5337 }
5338 caja_file_operation_complete (op, NULL((void*)0), error);
5339 if (error) {
5340 g_error_free (error);
5341 }
5342}
5343
5344
5345static void
5346set_attributes_callback (GObject *source_object,
5347 GAsyncResult *result,
5348 gpointer callback_data)
5349{
5350 CajaFileOperation *op;
5351 GError *error;
5352 gboolean res;
5353
5354 op = callback_data;
5355
5356 error = NULL((void*)0);
5357 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5358 result,
5359 NULL((void*)0),
5360 &error);
5361
5362 if (res) {
5363 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5364 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
5365 0,
5366 G_PRIORITY_DEFAULT0,
5367 op->cancellable,
5368 set_attributes_get_info_callback, op);
5369 } else {
5370 caja_file_operation_complete (op, NULL((void*)0), error);
5371 g_error_free (error);
5372 }
5373}
5374
5375void
5376caja_file_set_attributes (CajaFile *file,
5377 GFileInfo *attributes,
5378 CajaFileOperationCallback callback,
5379 gpointer callback_data)
5380{
5381 CajaFileOperation *op;
5382 GFile *location;
5383
5384 op = caja_file_operation_new (file, callback, callback_data);
5385
5386 location = caja_file_get_location (file);
5387 g_file_set_attributes_async (location,
5388 attributes,
5389 0,
5390 G_PRIORITY_DEFAULT0,
5391 op->cancellable,
5392 set_attributes_callback,
5393 op);
5394 g_object_unref (location);
5395}
5396
5397
5398/**
5399 * caja_file_can_get_permissions:
5400 *
5401 * Check whether the permissions for a file are determinable.
5402 * This might not be the case for files on non-UNIX file systems.
5403 *
5404 * @file: The file in question.
5405 *
5406 * Return value: TRUE if the permissions are valid.
5407 */
5408gboolean
5409caja_file_can_get_permissions (CajaFile *file)
5410{
5411 return file->details->has_permissions;
5412}
5413
5414/**
5415 * caja_file_can_set_permissions:
5416 *
5417 * Check whether the current user is allowed to change
5418 * the permissions of a file.
5419 *
5420 * @file: The file in question.
5421 *
5422 * Return value: TRUE if the current user can change the
5423 * permissions of @file, FALSE otherwise. It's always possible
5424 * that when you actually try to do it, you will fail.
5425 */
5426gboolean
5427caja_file_can_set_permissions (CajaFile *file)
5428{
5429 uid_t user_id;
5430
5431 if (file->details->uid != -1 &&
5432 caja_file_is_local (file)) {
5433 /* Check the user. */
5434 user_id = geteuid();
5435
5436 /* Owner is allowed to set permissions. */
5437 if (user_id == (uid_t) file->details->uid) {
5438 return TRUE(!(0));
5439 }
5440
5441 /* Root is also allowed to set permissions. */
5442 if (user_id == 0) {
5443 return TRUE(!(0));
5444 }
5445
5446 /* Nobody else is allowed. */
5447 return FALSE(0);
5448 }
5449
5450 /* pretend to have full chmod rights when no info is available, relevant when
5451 * the FS can't provide ownership info, for instance for FTP */
5452 return TRUE(!(0));
5453}
5454
5455guint
5456caja_file_get_permissions (CajaFile *file)
5457{
5458 g_return_val_if_fail (caja_file_can_get_permissions (file), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_516
; if (caja_file_can_get_permissions (file)) _g_boolean_var_516
= 1; else _g_boolean_var_516 = 0; _g_boolean_var_516; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "caja_file_can_get_permissions (file)");
return (0); } } while (0)
;
5459
5460 return file->details->permissions;
5461}
5462
5463/**
5464 * caja_file_set_permissions:
5465 *
5466 * Change a file's permissions. This should only be called if
5467 * caja_file_can_set_permissions returned TRUE.
5468 *
5469 * @file: CajaFile representing the file in question.
5470 * @new_permissions: New permissions value. This is the whole
5471 * set of permissions, not a delta.
5472 **/
5473void
5474caja_file_set_permissions (CajaFile *file,
5475 guint32 new_permissions,
5476 CajaFileOperationCallback callback,
5477 gpointer callback_data)
5478{
5479 GFileInfo *info;
5480
5481 if (!caja_file_can_set_permissions (file)) {
5482 GError *error;
5483
5484 /* Claim that something changed even if the permission change failed.
5485 * This makes it easier for some clients who see the "reverting"
5486 * to the old permissions as "changing back".
5487 */
5488 caja_file_changed (file);
5489 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5490 _("Not allowed to set permissions")dcgettext (((void*)0), "Not allowed to set permissions", 5));
5491 (* callback) (file, NULL((void*)0), error, callback_data);
5492 g_error_free (error);
5493 return;
5494 }
5495
5496 /* Test the permissions-haven't-changed case explicitly
5497 * because we don't want to send the file-changed signal if
5498 * nothing changed.
5499 */
5500 if (new_permissions == file->details->permissions) {
5501 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5502 return;
5503 }
5504
5505 // Start UNDO-REDO
5506 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5507 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_SETPERMISSIONS, 1);
5508 caja_undostack_manager_data_set_file_permissions(undo_redo_data, caja_file_get_uri(file), file->details->permissions, new_permissions);
5509 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5510 undo_redo_data);
5511 }
5512 // End UNDO-REDO
5513
5514 info = g_file_info_new ();
5515 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode", new_permissions);
5516 caja_file_set_attributes (file, info, callback, callback_data);
5517 g_object_unref (info);
5518}
5519
5520/**
5521 * caja_file_can_get_selinux_context:
5522 *
5523 * Check whether the selinux context for a file are determinable.
5524 * This might not be the case for files on non-UNIX file systems,
5525 * files without a context or systems that don't support selinux.
5526 *
5527 * @file: The file in question.
5528 *
5529 * Return value: TRUE if the permissions are valid.
5530 */
5531gboolean
5532caja_file_can_get_selinux_context (CajaFile *file)
5533{
5534 return file->details->selinux_context != NULL((void*)0);
5535}
5536
5537
5538/**
5539 * caja_file_get_selinux_context:
5540 *
5541 * Get a user-displayable string representing a file's selinux
5542 * context
5543 * @file: CajaFile representing the file in question.
5544 *
5545 * Returns: Newly allocated string ready to display to the user.
5546 *
5547 **/
5548char *
5549caja_file_get_selinux_context (CajaFile *file)
5550{
5551 char *translated;
5552 char *raw;
5553
5554 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_517
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_517
= 1; else _g_boolean_var_517 = 0; _g_boolean_var_517; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
5555
5556 if (!caja_file_can_get_selinux_context (file)) {
5557 return NULL((void*)0);
5558 }
5559
5560 raw = file->details->selinux_context;
5561
5562#ifdef HAVE_SELINUX1
5563 if (selinux_raw_to_trans_context (raw, &translated) == 0) {
5564 char *tmp;
5565 tmp = g_strdup (translated)g_strdup_inline (translated);
5566 freecon (translated);
5567 translated = tmp;
5568 }
5569 else
5570#endif
5571 {
5572 translated = g_strdup (raw)g_strdup_inline (raw);
5573 }
5574
5575 return translated;
5576}
5577
5578static char *
5579get_real_name (const char *name, const char *gecos)
5580{
5581 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
5582
5583 if (gecos == NULL((void*)0)) {
5584 return NULL((void*)0);
5585 }
5586
5587 locale_string = eel_str_strip_substring_and_after (gecos, ",");
5588 if (!g_utf8_validate (locale_string, -1, NULL((void*)0))) {
5589 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5590 g_free (locale_string);
5591 } else {
5592 part_before_comma = locale_string;
5593 }
5594
5595 if (!g_utf8_validate (name, -1, NULL((void*)0))) {
5596 locale_string = g_locale_to_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5597 } else {
5598 locale_string = g_strdup (name)g_strdup_inline (name);
5599 }
5600
5601 capitalized_login_name = eel_str_capitalize (locale_string);
5602 g_free (locale_string);
5603
5604 if (capitalized_login_name == NULL((void*)0)) {
5605 real_name = part_before_comma;
5606 } else {
5607 real_name = eel_str_replace_substring
5608 (part_before_comma, "&", capitalized_login_name);
5609 g_free (part_before_comma);
5610 }
5611
5612
5613 if (eel_str_is_empty (real_name)
5614 || eel_strcmp (name, real_name) == 0
5615 || eel_strcmp (capitalized_login_name, real_name) == 0) {
5616 g_free (real_name);
5617 real_name = NULL((void*)0);
5618 }
5619
5620 g_free (capitalized_login_name);
5621
5622 return real_name;
5623}
5624
5625static gboolean
5626get_group_id_from_group_name (const char *group_name, uid_t *gid)
5627{
5628 struct group *group;
5629
5630 g_assert (gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_518
; if (gid != ((void*)0)) _g_boolean_var_518 = 1; else _g_boolean_var_518
= 0; _g_boolean_var_518; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5630, ((const char*) (__func__
)), "gid != NULL"); } while (0)
;
5631
5632 group = getgrnam (group_name);
5633
5634 if (group == NULL((void*)0)) {
5635 return FALSE(0);
5636 }
5637
5638 *gid = group->gr_gid;
5639
5640 return TRUE(!(0));
5641}
5642
5643static gboolean
5644get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid)
5645{
5646 struct passwd *password_info;
5647
5648 g_assert (uid != NULL || gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_519
; if (uid != ((void*)0) || gid != ((void*)0)) _g_boolean_var_519
= 1; else _g_boolean_var_519 = 0; _g_boolean_var_519; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5648, ((const char*) (__func__)), "uid != NULL || gid != NULL"
); } while (0)
;
5649
5650 password_info = getpwnam (user_name);
5651
5652 if (password_info == NULL((void*)0)) {
5653 return FALSE(0);
5654 }
5655
5656 if (uid != NULL((void*)0)) {
5657 *uid = password_info->pw_uid;
5658 }
5659
5660 if (gid != NULL((void*)0)) {
5661 *gid = password_info->pw_gid;
5662 }
5663
5664 return TRUE(!(0));
5665}
5666
5667static gboolean
5668get_user_id_from_user_name (const char *user_name, uid_t *id)
5669{
5670 return get_ids_from_user_name (user_name, id, NULL((void*)0));
5671}
5672
5673static gboolean
5674get_id_from_digit_string (const char *digit_string, uid_t *id)
5675{
5676 long scanned_id;
5677 char c;
5678
5679 g_assert (id != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_520
; if (id != ((void*)0)) _g_boolean_var_520 = 1; else _g_boolean_var_520
= 0; _g_boolean_var_520; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5679, ((const char*) (__func__
)), "id != NULL"); } while (0)
;
5680
5681 /* Only accept string if it has one integer with nothing
5682 * afterwards.
5683 */
5684 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) {
5685 return FALSE(0);
5686 }
5687 *id = scanned_id;
5688 return TRUE(!(0));
5689}
5690
5691/**
5692 * caja_file_can_get_owner:
5693 *
5694 * Check whether the owner a file is determinable.
5695 * This might not be the case for files on non-UNIX file systems.
5696 *
5697 * @file: The file in question.
5698 *
5699 * Return value: TRUE if the owner is valid.
5700 */
5701gboolean
5702caja_file_can_get_owner (CajaFile *file)
5703{
5704 /* Before we have info on a file, the owner is unknown. */
5705 return file->details->uid != -1;
5706}
5707
5708/**
5709 * caja_file_get_owner_name:
5710 *
5711 * Get the user name of the file's owner. If the owner has no
5712 * name, returns the userid as a string. The caller is responsible
5713 * for g_free-ing this string.
5714 *
5715 * @file: The file in question.
5716 *
5717 * Return value: A newly-allocated string.
5718 */
5719char *
5720caja_file_get_owner_name (CajaFile *file)
5721{
5722 return caja_file_get_owner_as_string (file, FALSE(0));
5723}
5724
5725/**
5726 * caja_file_can_set_owner:
5727 *
5728 * Check whether the current user is allowed to change
5729 * the owner of a file.
5730 *
5731 * @file: The file in question.
5732 *
5733 * Return value: TRUE if the current user can change the
5734 * owner of @file, FALSE otherwise. It's always possible
5735 * that when you actually try to do it, you will fail.
5736 */
5737gboolean
5738caja_file_can_set_owner (CajaFile *file)
5739{
5740 /* Not allowed to set the owner if we can't
5741 * even read it. This can happen on non-UNIX file
5742 * systems.
5743 */
5744 if (!caja_file_can_get_owner (file)) {
5745 return FALSE(0);
5746 }
5747
5748 /* Only root is also allowed to set the owner. */
5749 return geteuid() == 0;
5750}
5751
5752/**
5753 * caja_file_set_owner:
5754 *
5755 * Set the owner of a file. This will only have any effect if
5756 * caja_file_can_set_owner returns TRUE.
5757 *
5758 * @file: The file in question.
5759 * @user_name_or_id: The user name to set the owner to.
5760 * If the string does not match any user name, and the
5761 * string is an integer, the owner will be set to the
5762 * userid represented by that integer.
5763 * @callback: Function called when asynch owner change succeeds or fails.
5764 * @callback_data: Parameter passed back with callback function.
5765 */
5766void
5767caja_file_set_owner (CajaFile *file,
5768 const char *user_name_or_id,
5769 CajaFileOperationCallback callback,
5770 gpointer callback_data)
5771{
5772 GError *error;
5773 GFileInfo *info;
5774 uid_t new_id;
5775
5776 if (!caja_file_can_set_owner (file)) {
5777 /* Claim that something changed even if the permission
5778 * change failed. This makes it easier for some
5779 * clients who see the "reverting" to the old owner as
5780 * "changing back".
5781 */
5782 caja_file_changed (file);
5783 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5784 _("Not allowed to set owner")dcgettext (((void*)0), "Not allowed to set owner", 5));
5785 (* callback) (file, NULL((void*)0), error, callback_data);
5786 g_error_free (error);
5787 return;
5788 }
5789
5790 /* If no match treating user_name_or_id as name, try treating
5791 * it as id.
5792 */
5793 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
5794 && !get_id_from_digit_string (user_name_or_id, &new_id)) {
5795 /* Claim that something changed even if the permission
5796 * change failed. This makes it easier for some
5797 * clients who see the "reverting" to the old owner as
5798 * "changing back".
5799 */
5800 caja_file_changed (file);
5801 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
5802 _("Specified owner '%s' doesn't exist")dcgettext (((void*)0), "Specified owner '%s' doesn't exist", 5
)
, user_name_or_id);
5803 (* callback) (file, NULL((void*)0), error, callback_data);
5804 g_error_free (error);
5805 return;
5806 }
5807
5808 /* Test the owner-hasn't-changed case explicitly because we
5809 * don't want to send the file-changed signal if nothing
5810 * changed.
5811 */
5812 if (new_id == (uid_t) file->details->uid) {
5813 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5814 return;
5815 }
5816
5817 // Start UNDO-REDO
5818 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5819 char* current_owner = caja_file_get_owner_as_string (file, FALSE(0));
5820 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEOWNER, 1);
5821 caja_undostack_manager_data_set_owner_change_information(undo_redo_data, caja_file_get_uri(file), current_owner, user_name_or_id);
5822 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5823 undo_redo_data);
5824 g_free(current_owner);
5825 }
5826 // End UNDO-REDO
5827
5828 info = g_file_info_new ();
5829 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid", new_id);
5830 caja_file_set_attributes (file, info, callback, callback_data);
5831 g_object_unref (info);
5832}
5833
5834/**
5835 * caja_get_user_names:
5836 *
5837 * Get a list of user names. For users with a different associated
5838 * "real name", the real name follows the standard user name, separated
5839 * by a carriage return. The caller is responsible for freeing this list
5840 * and its contents.
5841 */
5842GList *
5843caja_get_user_names (void)
5844{
5845 GList *list;
5846 char *name;
5847 struct passwd *user;
5848
5849 list = NULL((void*)0);
5850
5851 setpwent ();
5852
5853 while ((user = getpwent ()) != NULL((void*)0)) {
5854 char *real_name;
5855
5856 real_name = get_real_name (user->pw_name, user->pw_gecos);
5857 if (real_name != NULL((void*)0)) {
5858 name = g_strconcat (user->pw_name, "\n", real_name, NULL((void*)0));
5859 } else {
5860 name = g_strdup (user->pw_name)g_strdup_inline (user->pw_name);
5861 }
5862 g_free (real_name);
5863 list = g_list_prepend (list, name);
5864 }
5865
5866 endpwent ();
5867
5868 return eel_g_str_list_alphabetize (list);
5869}
5870
5871/**
5872 * caja_file_can_get_group:
5873 *
5874 * Check whether the group a file is determinable.
5875 * This might not be the case for files on non-UNIX file systems.
5876 *
5877 * @file: The file in question.
5878 *
5879 * Return value: TRUE if the group is valid.
5880 */
5881gboolean
5882caja_file_can_get_group (CajaFile *file)
5883{
5884 /* Before we have info on a file, the group is unknown. */
5885 return file->details->gid != -1;
5886}
5887
5888/**
5889 * caja_file_get_group_name:
5890 *
5891 * Get the name of the file's group. If the group has no
5892 * name, returns the groupid as a string. The caller is responsible
5893 * for g_free-ing this string.
5894 *
5895 * @file: The file in question.
5896 *
5897 * Return value: A newly-allocated string.
5898 **/
5899char *
5900caja_file_get_group_name (CajaFile *file)
5901{
5902 return g_strdup (file->details->group)g_strdup_inline (file->details->group);
5903}
5904
5905/**
5906 * caja_file_can_set_group:
5907 *
5908 * Check whether the current user is allowed to change
5909 * the group of a file.
5910 *
5911 * @file: The file in question.
5912 *
5913 * Return value: TRUE if the current user can change the
5914 * group of @file, FALSE otherwise. It's always possible
5915 * that when you actually try to do it, you will fail.
5916 */
5917gboolean
5918caja_file_can_set_group (CajaFile *file)
5919{
5920 uid_t user_id;
5921
5922 /* Not allowed to set the permissions if we can't
5923 * even read them. This can happen on non-UNIX file
5924 * systems.
5925 */
5926 if (!caja_file_can_get_group (file)) {
5927 return FALSE(0);
5928 }
5929
5930 /* Check the user. */
5931 user_id = geteuid();
5932
5933 /* Owner is allowed to set group (with restrictions). */
5934 if (user_id == (uid_t) file->details->uid) {
5935 return TRUE(!(0));
5936 }
5937
5938 /* Root is also allowed to set group. */
5939 if (user_id == 0) {
5940 return TRUE(!(0));
5941 }
5942
5943 /* Nobody else is allowed. */
5944 return FALSE(0);
5945}
5946
5947/* Get a list of group names, filtered to only the ones
5948 * that contain the given username. If the username is
5949 * NULL, returns a list of all group names.
5950 */
5951static GList *
5952caja_get_group_names_for_user (void)
5953{
5954 GList *list;
5955 int count, i;
5956 gid_t gid_list[NGROUPS_MAX65536 + 1];
5957 struct group *group = NULL((void*)0);
5958
5959
5960 list = NULL((void*)0);
5961
5962 count = getgroups (NGROUPS_MAX65536 + 1, gid_list);
5963 for (i = 0; i < count; i++) {
5964 group = getgrgid (gid_list[i]);
5965 if (group == NULL((void*)0))
5966 break;
5967
5968 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5969 }
5970
5971 return eel_g_str_list_alphabetize (list);
5972}
5973
5974/**
5975 * caja_get_group_names:
5976 *
5977 * Get a list of all group names.
5978 */
5979GList *
5980caja_get_all_group_names (void)
5981{
5982 GList *list;
5983 struct group *group;
5984
5985 list = NULL((void*)0);
5986
5987 setgrent ();
5988
5989 while ((group = getgrent ()) != NULL((void*)0))
5990 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5991
5992 endgrent ();
5993
5994 return eel_g_str_list_alphabetize (list);
5995}
5996
5997/**
5998 * caja_file_get_settable_group_names:
5999 *
6000 * Get a list of all group names that the current user
6001 * can set the group of a specific file to.
6002 *
6003 * @file: The CajaFile in question.
6004 */
6005GList *
6006caja_file_get_settable_group_names (CajaFile *file)
6007{
6008 uid_t user_id;
6009 GList *result;
6010
6011 if (!caja_file_can_set_group (file)) {
6012 return NULL((void*)0);
6013 }
6014
6015 /* Check the user. */
6016 user_id = geteuid();
6017
6018 if (user_id == 0) {
6019 /* Root is allowed to set group to anything. */
6020 result = caja_get_all_group_names ();
6021 } else if (user_id == (uid_t) file->details->uid) {
6022 /* Owner is allowed to set group to any that owner is member of. */
6023 result = caja_get_group_names_for_user ();
6024 } else {
6025 g_warning ("unhandled case in caja_get_settable_group_names");
6026 result = NULL((void*)0);
6027 }
6028
6029 return result;
6030}
6031
6032/**
6033 * caja_file_set_group:
6034 *
6035 * Set the group of a file. This will only have any effect if
6036 * caja_file_can_set_group returns TRUE.
6037 *
6038 * @file: The file in question.
6039 * @group_name_or_id: The group name to set the owner to.
6040 * If the string does not match any group name, and the
6041 * string is an integer, the group will be set to the
6042 * group id represented by that integer.
6043 * @callback: Function called when asynch group change succeeds or fails.
6044 * @callback_data: Parameter passed back with callback function.
6045 */
6046void
6047caja_file_set_group (CajaFile *file,
6048 const char *group_name_or_id,
6049 CajaFileOperationCallback callback,
6050 gpointer callback_data)
6051{
6052 GError *error;
6053 GFileInfo *info;
6054 uid_t new_id;
6055
6056 if (!caja_file_can_set_group (file)) {
6057 /* Claim that something changed even if the group
6058 * change failed. This makes it easier for some
6059 * clients who see the "reverting" to the old group as
6060 * "changing back".
6061 */
6062 caja_file_changed (file);
6063 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
6064 _("Not allowed to set group")dcgettext (((void*)0), "Not allowed to set group", 5));
6065 (* callback) (file, NULL((void*)0), error, callback_data);
6066 g_error_free (error);
6067 return;
6068 }
6069
6070 /* If no match treating group_name_or_id as name, try treating
6071 * it as id.
6072 */
6073 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6074 && !get_id_from_digit_string (group_name_or_id, &new_id)) {
6075 /* Claim that something changed even if the group
6076 * change failed. This makes it easier for some
6077 * clients who see the "reverting" to the old group as
6078 * "changing back".
6079 */
6080 caja_file_changed (file);
6081 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
6082 _("Specified group '%s' doesn't exist")dcgettext (((void*)0), "Specified group '%s' doesn't exist", 5
)
, group_name_or_id);
6083 (* callback) (file, NULL((void*)0), error, callback_data);
6084 g_error_free (error);
6085 return;
6086 }
6087
6088 if (new_id == (gid_t) file->details->gid) {
6089 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
6090 return;
6091 }
6092
6093 // Start UNDO-REDO
6094 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6095 char* current_group = caja_file_get_group_name (file);
6096 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEGROUP, 1);
6097 caja_undostack_manager_data_set_group_change_information(undo_redo_data, caja_file_get_uri(file), current_group, group_name_or_id);
6098 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
6099 undo_redo_data);
6100 g_free(current_group);
6101 }
6102 // End UNDO-REDO
6103
6104 info = g_file_info_new ();
6105 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid", new_id);
6106 caja_file_set_attributes (file, info, callback, callback_data);
6107 g_object_unref (info);
6108}
6109
6110/**
6111 * caja_file_get_octal_permissions_as_string:
6112 *
6113 * Get a user-displayable string representing a file's permissions
6114 * as an octal number. The caller
6115 * is responsible for g_free-ing this string.
6116 * @file: CajaFile representing the file in question.
6117 *
6118 * Returns: Newly allocated string ready to display to the user.
6119 *
6120 **/
6121static char *
6122caja_file_get_octal_permissions_as_string (CajaFile *file)
6123{
6124 guint32 permissions;
6125
6126 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_521
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_521
= 1; else _g_boolean_var_521 = 0; _g_boolean_var_521; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6126, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6127
6128 if (!caja_file_can_get_permissions (file)) {
6129 return NULL((void*)0);
6130 }
6131
6132 permissions = file->details->permissions;
6133 return g_strdup_printf ("%03o", permissions);
6134}
6135
6136/**
6137 * caja_file_get_permissions_as_string:
6138 *
6139 * Get a user-displayable string representing a file's permissions. The caller
6140 * is responsible for g_free-ing this string.
6141 * @file: CajaFile representing the file in question.
6142 *
6143 * Returns: Newly allocated string ready to display to the user.
6144 *
6145 **/
6146static char *
6147caja_file_get_permissions_as_string (CajaFile *file)
6148{
6149 guint32 permissions;
6150 gboolean is_directory;
6151 gboolean is_link;
6152 gboolean suid, sgid, sticky;
6153
6154 if (!caja_file_can_get_permissions (file)) {
6155 return NULL((void*)0);
6156 }
6157
6158 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_522
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_522
= 1; else _g_boolean_var_522 = 0; _g_boolean_var_522; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6158, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6159
6160 permissions = file->details->permissions;
6161 is_directory = caja_file_is_directory (file);
6162 is_link = caja_file_is_symbolic_link (file);
6163
6164 /* We use ls conventions for displaying these three obscure flags */
6165 suid = permissions & S_ISUID04000;
6166 sgid = permissions & S_ISGID02000;
6167 sticky = permissions & S_ISVTX01000;
6168
6169 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6170 is_link ? 'l' : is_directory ? 'd' : '-',
6171 permissions & S_IRUSR0400 ? 'r' : '-',
6172 permissions & S_IWUSR0200 ? 'w' : '-',
6173 permissions & S_IXUSR0100
6174 ? (suid ? 's' : 'x')
6175 : (suid ? 'S' : '-'),
6176 permissions & S_IRGRP(0400 >> 3) ? 'r' : '-',
6177 permissions & S_IWGRP(0200 >> 3) ? 'w' : '-',
6178 permissions & S_IXGRP(0100 >> 3)
6179 ? (sgid ? 's' : 'x')
6180 : (sgid ? 'S' : '-'),
6181 permissions & S_IROTH((0400 >> 3) >> 3) ? 'r' : '-',
6182 permissions & S_IWOTH((0200 >> 3) >> 3) ? 'w' : '-',
6183 permissions & S_IXOTH((0100 >> 3) >> 3)
6184 ? (sticky ? 't' : 'x')
6185 : (sticky ? 'T' : '-'));
6186}
6187
6188/**
6189 * caja_file_get_owner_as_string:
6190 *
6191 * Get a user-displayable string representing a file's owner. The caller
6192 * is responsible for g_free-ing this string.
6193 * @file: CajaFile representing the file in question.
6194 * @include_real_name: Whether or not to append the real name (if any)
6195 * for this user after the user name.
6196 *
6197 * Returns: Newly allocated string ready to display to the user.
6198 *
6199 **/
6200static char *
6201caja_file_get_owner_as_string (CajaFile *file, gboolean include_real_name)
6202{
6203 char *user_name;
6204
6205 /* Before we have info on a file, the owner is unknown. */
6206 if (file->details->owner == NULL((void*)0) &&
6207 file->details->owner_real == NULL((void*)0)) {
6208 return NULL((void*)0);
6209 }
6210
6211 if (file->details->owner_real == NULL((void*)0)) {
6212 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6213 } else if (file->details->owner == NULL((void*)0)) {
6214 user_name = g_strdup (file->details->owner_real)g_strdup_inline (file->details->owner_real);
6215 } else if (include_real_name &&
6216 strcmp (file->details->owner, file->details->owner_real) != 0) {
6217 user_name = g_strdup_printf ("%s - %s",
6218 file->details->owner,
6219 file->details->owner_real);
6220 } else {
6221 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6222 }
6223
6224 return user_name;
6225}
6226
6227static char *
6228format_item_count_for_display (guint item_count,
6229 gboolean includes_directories,
6230 gboolean includes_files)
6231{
6232 g_assert (includes_directories || includes_files)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_523
; if (includes_directories || includes_files) _g_boolean_var_523
= 1; else _g_boolean_var_523 = 0; _g_boolean_var_523; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6232, ((const char*) (__func__)), "includes_directories || includes_files"
); } while (0)
;
6233
6234 return g_strdup_printf (includes_directories
6235 ? (includes_files
6236 ? ngettext ("%'u item", "%'u items", item_count)dcngettext (((void*)0), "%'u item", "%'u items", item_count, 5
)
6237 : ngettext ("%'u folder", "%'u folders", item_count)dcngettext (((void*)0), "%'u folder", "%'u folders", item_count
, 5)
)
6238 : ngettext ("%'u file", "%'u files", item_count)dcngettext (((void*)0), "%'u file", "%'u files", item_count, 5
)
, item_count);
6239}
6240
6241/**
6242 * caja_file_get_size_as_string:
6243 *
6244 * Get a user-displayable string representing a file size. The caller
6245 * is responsible for g_free-ing this string. The string is an item
6246 * count for directories.
6247 * @file: CajaFile representing the file in question.
6248 * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
6249 *
6250 * Returns: Newly allocated string ready to display to the user.
6251 *
6252 **/
6253static char *
6254caja_file_get_size_as_string (CajaFile *file,
6255 gboolean size_on_disk)
6256{
6257 guint item_count;
6258 gboolean count_unreadable;
6259 goffset size;
6260
6261 if (file == NULL((void*)0)) {
6262 return NULL((void*)0);
6263 }
6264
6265 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_524
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_524
= 1; else _g_boolean_var_524 = 0; _g_boolean_var_524; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6265, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6266
6267 if (caja_file_is_directory (file)) {
6268 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6269 return NULL((void*)0);
6270 }
6271 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6272 }
6273
6274 if (size_on_disk) {
6275 size = file->details->size_on_disk;
6276 } else {
6277 size = file->details->size;
6278 }
6279
6280 if (size == -1) {
6281 return NULL((void*)0);
6282 }
6283
6284 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6285 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6286 else
6287 return g_format_size (size);
6288}
6289
6290/**
6291 * caja_file_get_size_as_string_with_real_size:
6292 *
6293 * Get a user-displayable string representing a file size. The caller
6294 * is responsible for g_free-ing this string. The string is an item
6295 * count for directories.
6296 * This function adds the real size in the string.
6297 * @file: CajaFile representing the file in question.
6298 *
6299 * Returns: Newly allocated string ready to display to the user.
6300 *
6301 **/
6302static char *
6303caja_file_get_size_as_string_with_real_size (CajaFile *file,
6304 gboolean size_on_disk)
6305{
6306 guint item_count;
6307 gboolean count_unreadable;
6308 goffset size;
6309 char * formatted;
6310 char * formatted_plus_real;
6311 char * real_size;
6312
6313 if (file == NULL((void*)0)) {
6314 return NULL((void*)0);
6315 }
6316
6317 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_525
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_525
= 1; else _g_boolean_var_525 = 0; _g_boolean_var_525; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6317, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6318
6319 if (caja_file_is_directory (file)) {
6320 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6321 return NULL((void*)0);
6322 }
6323 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6324 }
6325
6326 if (size_on_disk) {
6327 size = file->details->size_on_disk;
6328 } else {
6329 size = file->details->size;
6330 }
6331
6332 if (size == -1) {
6333 return NULL((void*)0);
6334 }
6335
6336 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6337 formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6338 else
6339 formatted = g_format_size(size);
6340
6341 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
6342 real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT)dcgettext (((void*)0), "%""lu", 5), (guint64) size);
6343 formatted_plus_real = g_strdup_printf (_("%s (%s bytes)")dcgettext (((void*)0), "%s (%s bytes)", 5), formatted, real_size);
6344 g_free (real_size);
6345 g_free (formatted);
6346 return formatted_plus_real;
6347}
6348
6349static char *
6350caja_file_get_deep_count_as_string_internal (CajaFile *file,
6351 gboolean report_size,
6352 gboolean report_size_on_disk,
6353 gboolean report_directory_count,
6354 gboolean report_file_count)
6355{
6356 CajaRequestStatus status;
6357 guint directory_count;
6358 guint file_count;
6359 guint unreadable_count;
6360 guint total_count;
6361 goffset total_size;
6362 goffset total_size_on_disk;
6363
6364 /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
6365 g_assert (!(report_size && report_size_on_disk))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_526
; if (!(report_size && report_size_on_disk)) _g_boolean_var_526
= 1; else _g_boolean_var_526 = 0; _g_boolean_var_526; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6365, ((const char*) (__func__)), "!(report_size && report_size_on_disk)"
); } while (0)
;
6366 g_assert (!(report_size && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_527
; if (!(report_size && (report_directory_count || report_file_count
))) _g_boolean_var_527 = 1; else _g_boolean_var_527 = 0; _g_boolean_var_527
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6366, ((const char*) (__func__)), "!(report_size && (report_directory_count || report_file_count))"
); } while (0)
;
6367 g_assert (!(report_size_on_disk && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_528
; if (!(report_size_on_disk && (report_directory_count
|| report_file_count))) _g_boolean_var_528 = 1; else _g_boolean_var_528
= 0; _g_boolean_var_528; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6367, ((const char*) (__func__
)), "!(report_size_on_disk && (report_directory_count || report_file_count))"
); } while (0)
;
6368
6369 /* Must ask for something */
6370 g_assert (report_size || report_size_on_disk || report_directory_count || report_file_count)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_529
; if (report_size || report_size_on_disk || report_directory_count
|| report_file_count) _g_boolean_var_529 = 1; else _g_boolean_var_529
= 0; _g_boolean_var_529; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6370, ((const char*) (__func__
)), "report_size || report_size_on_disk || report_directory_count || report_file_count"
); } while (0)
;
6371
6372 if (file == NULL((void*)0)) {
6373 return NULL((void*)0);
6374 }
6375
6376 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_530
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_530
= 1; else _g_boolean_var_530 = 0; _g_boolean_var_530; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6376, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6377 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_531
; if (caja_file_is_directory (file)) _g_boolean_var_531 = 1; else
_g_boolean_var_531 = 0; _g_boolean_var_531; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6377, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
6378
6379 status = caja_file_get_deep_counts (file,
6380 &directory_count,
6381 &file_count,
6382 &unreadable_count,
6383 &total_size,
6384 &total_size_on_disk,
6385 FALSE(0));
6386
6387 /* Check whether any info is available. */
6388 if (status == CAJA_REQUEST_NOT_STARTED) {
6389 return NULL((void*)0);
6390 }
6391
6392 total_count = file_count + directory_count;
6393
6394 if (total_count == 0) {
6395 switch (status) {
6396 case CAJA_REQUEST_IN_PROGRESS:
6397 /* Don't return confident "zero" until we're finished looking,
6398 * because of next case.
6399 */
6400 return NULL((void*)0);
6401 case CAJA_REQUEST_DONE:
6402 /* Don't return "zero" if we there were contents but we couldn't read them. */
6403 if (unreadable_count != 0) {
6404 return NULL((void*)0);
6405 }
6406 default: break;
6407 }
6408 }
6409
6410 /* Note that we don't distinguish the "everything was readable" case
6411 * from the "some things but not everything was readable" case here.
6412 * Callers can distinguish them using caja_file_get_deep_counts
6413 * directly if desired.
6414 */
6415 if (report_size)
6416 {
6417 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6418 return g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
6419 else
6420 return g_format_size(total_size);
6421 }
6422
6423 if (report_size_on_disk)
6424 {
6425 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6426 return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
6427 else
6428 return g_format_size (total_size_on_disk);
6429 }
6430
6431 return format_item_count_for_display (report_directory_count
6432 ? (report_file_count ? total_count : directory_count)
6433 : file_count,
6434 report_directory_count, report_file_count);
6435}
6436
6437/**
6438 * caja_file_get_deep_size_as_string:
6439 *
6440 * Get a user-displayable string representing the size of all contained
6441 * items (only makes sense for directories). The caller
6442 * is responsible for g_free-ing this string.
6443 * @file: CajaFile representing the file in question.
6444 * @size_on_disk: if TRUE will return the size on disk, else return size of file.
6445 *
6446 * Returns: Newly allocated string ready to display to the user.
6447 *
6448 **/
6449static char *
6450caja_file_get_deep_size_as_string (CajaFile *file, gboolean size_on_disk)
6451{
6452 if (size_on_disk) {
6453 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), TRUE(!(0)), FALSE(0), FALSE(0));
6454 } else {
6455 return caja_file_get_deep_count_as_string_internal (file, TRUE(!(0)), FALSE(0), FALSE(0), FALSE(0));
6456 }
6457}
6458
6459/**
6460 * caja_file_get_deep_total_count_as_string:
6461 *
6462 * Get a user-displayable string representing the count of all contained
6463 * items (only makes sense for directories). The caller
6464 * is responsible for g_free-ing this string.
6465 * @file: CajaFile representing the file in question.
6466 *
6467 * Returns: Newly allocated string ready to display to the user.
6468 *
6469 **/
6470static char *
6471caja_file_get_deep_total_count_as_string (CajaFile *file)
6472{
6473 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), TRUE(!(0)));
6474}
6475
6476/**
6477 * caja_file_get_deep_file_count_as_string:
6478 *
6479 * Get a user-displayable string representing the count of all contained
6480 * items, not including directories. It only makes sense to call this
6481 * function on a directory. The caller
6482 * is responsible for g_free-ing this string.
6483 * @file: CajaFile representing the file in question.
6484 *
6485 * Returns: Newly allocated string ready to display to the user.
6486 *
6487 **/
6488static char *
6489caja_file_get_deep_file_count_as_string (CajaFile *file)
6490{
6491 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), FALSE(0), TRUE(!(0)));
6492}
6493
6494/**
6495 * caja_file_get_deep_directory_count_as_string:
6496 *
6497 * Get a user-displayable string representing the count of all contained
6498 * directories. It only makes sense to call this
6499 * function on a directory. The caller
6500 * is responsible for g_free-ing this string.
6501 * @file: CajaFile representing the file in question.
6502 *
6503 * Returns: Newly allocated string ready to display to the user.
6504 *
6505 **/
6506static char *
6507caja_file_get_deep_directory_count_as_string (CajaFile *file)
6508{
6509 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), FALSE(0));
6510}
6511
6512/**
6513 * caja_file_get_string_attribute:
6514 *
6515 * Get a user-displayable string from a named attribute. Use g_free to
6516 * free this string. If the value is unknown, returns NULL. You can call
6517 * caja_file_get_string_attribute_with_default if you want a non-NULL
6518 * default.
6519 *
6520 * @file: CajaFile representing the file in question.
6521 * @attribute_name: The name of the desired attribute. The currently supported
6522 * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
6523 * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
6524 * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
6525 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
6526 *
6527 * Returns: Newly allocated string ready to display to the user, or NULL
6528 * if the value is unknown or @attribute_name is not supported.
6529 *
6530 **/
6531char *
6532caja_file_get_string_attribute_q (CajaFile *file, GQuark attribute_q)
6533{
6534 char *extension_attribute;
6535
6536 if (attribute_q == attribute_name_q) {
6537 return caja_file_get_display_name (file);
6538 }
6539 if (attribute_q == attribute_type_q) {
6540 return caja_file_get_type_as_string (file);
6541 }
6542 if (attribute_q == attribute_mime_type_q) {
6543 return caja_file_get_mime_type (file);
6544 }
6545 if (attribute_q == attribute_size_q) {
6546 return caja_file_get_size_as_string (file, FALSE(0));
6547 }
6548 if (attribute_q == attribute_size_on_disk_q) {
6549 return caja_file_get_size_as_string (file, TRUE(!(0)));
6550 }
6551 if (attribute_q == attribute_size_detail_q) {
6552 return caja_file_get_size_as_string_with_real_size (file, FALSE(0));
6553 }
6554 if (attribute_q == attribute_size_on_disk_detail_q) {
6555 return caja_file_get_size_as_string_with_real_size (file, TRUE(!(0)));
6556 }
6557 if (attribute_q == attribute_deep_size_q) {
6558 return caja_file_get_deep_size_as_string (file, FALSE(0));
6559 }
6560 if (attribute_q == attribute_deep_size_on_disk_q) {
6561 return caja_file_get_deep_size_as_string (file, TRUE(!(0)));
6562 }
6563 if (attribute_q == attribute_deep_file_count_q) {
6564 return caja_file_get_deep_file_count_as_string (file);
6565 }
6566 if (attribute_q == attribute_deep_directory_count_q) {
6567 return caja_file_get_deep_directory_count_as_string (file);
6568 }
6569 if (attribute_q == attribute_deep_total_count_q) {
6570 return caja_file_get_deep_total_count_as_string (file);
6571 }
6572 if (attribute_q == attribute_trash_orig_path_q) {
6573 return caja_file_get_trash_original_file_parent_as_string (file);
6574 }
6575 if (attribute_q == attribute_date_modified_q) {
6576 return caja_file_get_date_as_string (file,
6577 CAJA_DATE_TYPE_MODIFIED);
6578 }
6579 if (attribute_q == attribute_date_changed_q) {
6580 return caja_file_get_date_as_string (file,
6581 CAJA_DATE_TYPE_CHANGED);
6582 }
6583 if (attribute_q == attribute_date_accessed_q) {
6584 return caja_file_get_date_as_string (file,
6585 CAJA_DATE_TYPE_ACCESSED);
6586 }
6587 if (attribute_q == attribute_date_created_q) {
6588 return caja_file_get_date_as_string (file,
6589 CAJA_DATE_TYPE_CREATED);
6590 }
6591 if (attribute_q == attribute_trashed_on_q) {
6592 return caja_file_get_date_as_string (file,
6593 CAJA_DATE_TYPE_TRASHED);
6594 }
6595 if (attribute_q == attribute_date_permissions_q) {
6596 return caja_file_get_date_as_string (file,
6597 CAJA_DATE_TYPE_PERMISSIONS_CHANGED);
6598 }
6599 if (attribute_q == attribute_extension_q) {
6600 return caja_file_get_extension_as_string (file);
6601 }
6602 if (attribute_q == attribute_permissions_q) {
6603 return caja_file_get_permissions_as_string (file);
6604 }
6605 if (attribute_q == attribute_selinux_context_q) {
6606 return caja_file_get_selinux_context (file);
6607 }
6608 if (attribute_q == attribute_octal_permissions_q) {
6609 return caja_file_get_octal_permissions_as_string (file);
6610 }
6611 if (attribute_q == attribute_owner_q) {
6612 return caja_file_get_owner_as_string (file, TRUE(!(0)));
6613 }
6614 if (attribute_q == attribute_group_q) {
6615 return caja_file_get_group_name (file);
6616 }
6617 if (attribute_q == attribute_uri_q) {
6618 return caja_file_get_uri (file);
6619 }
6620 if (attribute_q == attribute_where_q) {
6621 return caja_file_get_where_string (file);
6622 }
6623 if (attribute_q == attribute_link_target_q) {
6624 return caja_file_get_symbolic_link_target_path (file);
6625 }
6626 if (attribute_q == attribute_volume_q) {
6627 return caja_file_get_volume_name (file);
6628 }
6629 if (attribute_q == attribute_free_space_q) {
6630 return caja_file_get_volume_free_space (file);
6631 }
6632
6633 extension_attribute = NULL((void*)0);
6634
6635 if (file->details->pending_extension_attributes) {
6636 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
6637 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6638 }
6639
6640 if (extension_attribute == NULL((void*)0) && file->details->extension_attributes) {
6641 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
6642 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6643 }
6644
6645 return g_strdup (extension_attribute)g_strdup_inline (extension_attribute);
6646}
6647
6648char *
6649caja_file_get_string_attribute (CajaFile *file, const char *attribute_name)
6650{
6651 return caja_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
6652}
6653
6654
6655/**
6656 * caja_file_get_string_attribute_with_default:
6657 *
6658 * Get a user-displayable string from a named attribute. Use g_free to
6659 * free this string. If the value is unknown, returns a string representing
6660 * the unknown value, which varies with attribute. You can call
6661 * caja_file_get_string_attribute if you want NULL instead of a default
6662 * result.
6663 *
6664 * @file: CajaFile representing the file in question.
6665 * @attribute_name: The name of the desired attribute. See the description of
6666 * caja_file_get_string for the set of available attributes.
6667 *
6668 * Returns: Newly allocated string ready to display to the user, or a string
6669 * such as "unknown" if the value is unknown or @attribute_name is not supported.
6670 *
6671 **/
6672char *
6673caja_file_get_string_attribute_with_default_q (CajaFile *file, GQuark attribute_q)
6674{
6675 char *result;
6676 guint item_count;
6677 gboolean count_unreadable;
6678 CajaRequestStatus status;
6679
6680 result = caja_file_get_string_attribute_q (file, attribute_q);
6681 if (result != NULL((void*)0)) {
6682 return result;
6683 }
6684
6685 /* Supply default values for the ones we know about. */
6686 /* FIXME bugzilla.gnome.org 40646:
6687 * Use hash table and switch statement or function pointers for speed?
6688 */
6689 if (attribute_q == attribute_size_q) {
6690 if (!caja_file_should_show_directory_item_count (file)) {
6691 return g_strdup ("--")g_strdup_inline ("--");
6692 }
6693 count_unreadable = FALSE(0);
6694 if (caja_file_is_directory (file)) {
6695 caja_file_get_directory_item_count (file, &item_count, &count_unreadable);
6696 }
6697 return g_strdup (count_unreadable ? _("? items") : "...")g_strdup_inline (count_unreadable ? dcgettext (((void*)0), "? items"
, 5) : "...")
;
6698 }
6699 if (attribute_q == attribute_deep_size_q) {
6700 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6701 if (status == CAJA_REQUEST_DONE) {
6702 /* This means no contents at all were readable */
6703 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6704 }
6705 return g_strdup ("...")g_strdup_inline ("...");
6706 }
6707 if (attribute_q == attribute_deep_size_on_disk_q) {
6708 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6709 if (status == CAJA_REQUEST_DONE) {
6710 /* This means no contents at all were readable */
6711 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6712 }
6713 return g_strdup ("...")g_strdup_inline ("...");
6714 }
6715 if (attribute_q == attribute_deep_file_count_q
6716 || attribute_q == attribute_deep_directory_count_q
6717 || attribute_q == attribute_deep_total_count_q) {
6718 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6719 if (status == CAJA_REQUEST_DONE) {
6720 /* This means no contents at all were readable */
6721 return g_strdup (_("? items"))g_strdup_inline (dcgettext (((void*)0), "? items", 5));
6722 }
6723 return g_strdup ("...")g_strdup_inline ("...");
6724 }
6725 if (attribute_q == attribute_type_q) {
6726 return g_strdup (_("unknown type"))g_strdup_inline (dcgettext (((void*)0), "unknown type", 5));
6727 }
6728 if (attribute_q == attribute_mime_type_q) {
6729 return g_strdup (_("unknown MIME type"))g_strdup_inline (dcgettext (((void*)0), "unknown MIME type", 5
))
;
6730 }
6731 if (attribute_q == attribute_trashed_on_q) {
6732 /* If n/a */
6733 return g_strdup ("")g_strdup_inline ("");
6734 }
6735 if (attribute_q == attribute_trash_orig_path_q) {
6736 /* If n/a */
6737 return g_strdup ("")g_strdup_inline ("");
6738 }
6739
6740 /* Fallback, use for both unknown attributes and attributes
6741 * for which we have no more appropriate default.
6742 */
6743 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
6744}
6745
6746char *
6747caja_file_get_string_attribute_with_default (CajaFile *file, const char *attribute_name)
6748{
6749 return caja_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
6750}
6751
6752gboolean
6753caja_file_is_date_sort_attribute_q (GQuark attribute_q)
6754{
6755 if (attribute_q == attribute_modification_date_q ||
6756 attribute_q == attribute_date_modified_q ||
6757 attribute_q == attribute_creation_date_q ||
6758 attribute_q == attribute_date_created_q ||
6759 attribute_q == attribute_accessed_date_q ||
6760 attribute_q == attribute_date_accessed_q ||
6761 attribute_q == attribute_date_changed_q ||
6762 attribute_q == attribute_trashed_on_q ||
6763 attribute_q == attribute_date_permissions_q) {
6764 return TRUE(!(0));
6765 }
6766
6767 return FALSE(0);
6768}
6769
6770/**
6771 * get_description:
6772 *
6773 * Get a user-displayable string representing a file type. The caller
6774 * is responsible for g_free-ing this string.
6775 * @file: CajaFile representing the file in question.
6776 *
6777 * Returns: Newly allocated string ready to display to the user.
6778 *
6779 **/
6780static char *
6781get_description (CajaFile *file)
6782{
6783 const char *mime_type;
6784 char *description;
6785
6786 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_532
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_532
= 1; else _g_boolean_var_532 = 0; _g_boolean_var_532; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6786, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6787
6788 mime_type = file->details->mime_type;
6789 if (eel_str_is_empty (mime_type)) {
6790 return NULL((void*)0);
6791 }
6792
6793 if (g_content_type_is_unknown (mime_type) &&
6794 caja_file_is_executable (file)) {
6795 return g_strdup (_("program"))g_strdup_inline (dcgettext (((void*)0), "program", 5));
6796 }
6797
6798 description = g_content_type_get_description (mime_type);
6799 if (!eel_str_is_empty (description)) {
6800 return description;
6801 }
6802
6803 return g_strdup (mime_type)g_strdup_inline (mime_type);
6804}
6805
6806/* Takes ownership of string */
6807static char *
6808update_description_for_link (CajaFile *file, char *string)
6809{
6810 if (caja_file_is_symbolic_link (file)) {
6811 char *res;
6812
6813 g_assert (!caja_file_is_broken_symbolic_link (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_533
; if (!caja_file_is_broken_symbolic_link (file)) _g_boolean_var_533
= 1; else _g_boolean_var_533 = 0; _g_boolean_var_533; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6813, ((const char*) (__func__)), "!caja_file_is_broken_symbolic_link (file)"
); } while (0)
;
6814 if (string == NULL((void*)0)) {
6815 return g_strdup (_("link"))g_strdup_inline (dcgettext (((void*)0), "link", 5));
6816 }
6817 /* Note to localizers: convert file type string for file
6818 * (e.g. "folder", "plain text") to file type for symbolic link
6819 * to that kind of file (e.g. "link to folder").
6820 */
6821 res = g_strdup_printf (_("Link to %s")dcgettext (((void*)0), "Link to %s", 5), string);
6822 g_free (string);
6823 return res;
6824 }
6825
6826 return string;
6827}
6828
6829static char *
6830caja_file_get_type_as_string (CajaFile *file)
6831{
6832 if (file == NULL((void*)0)) {
6833 return NULL((void*)0);
6834 }
6835
6836 if (caja_file_is_broken_symbolic_link (file)) {
6837 return g_strdup (_("link (broken)"))g_strdup_inline (dcgettext (((void*)0), "link (broken)", 5));
6838 }
6839
6840 return update_description_for_link (file, get_description (file));
6841}
6842
6843/**
6844 * caja_file_get_file_type
6845 *
6846 * Return this file's type.
6847 * @file: CajaFile representing the file in question.
6848 *
6849 * Returns: The type.
6850 *
6851 **/
6852GFileType
6853caja_file_get_file_type (CajaFile *file)
6854{
6855 if (file == NULL((void*)0)) {
6856 return G_FILE_TYPE_UNKNOWN;
6857 }
6858
6859 return file->details->type;
6860}
6861
6862/**
6863 * caja_file_get_mime_type
6864 *
6865 * Return this file's default mime type.
6866 * @file: CajaFile representing the file in question.
6867 *
6868 * Returns: The mime type.
6869 *
6870 **/
6871char *
6872caja_file_get_mime_type (CajaFile *file)
6873{
6874 if (file != NULL((void*)0)) {
6875 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_534
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_534
= 1; else _g_boolean_var_534 = 0; _g_boolean_var_534; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6876 if (file->details->mime_type != NULL((void*)0)) {
6877 return g_strdup (file->details->mime_type)g_strdup_inline (file->details->mime_type);
6878 }
6879 }
6880 return g_strdup ("application/octet-stream")g_strdup_inline ("application/octet-stream");
6881}
6882
6883/**
6884 * caja_file_is_mime_type
6885 *
6886 * Check whether a file is of a particular MIME type, or inherited
6887 * from it.
6888 * @file: CajaFile representing the file in question.
6889 * @mime_type: The MIME-type string to test (e.g. "text/plain")
6890 *
6891 * Return value: TRUE if @mime_type exactly matches the
6892 * file's MIME type.
6893 *
6894 **/
6895gboolean
6896caja_file_is_mime_type (CajaFile *file, const char *mime_type)
6897{
6898 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_535
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_535
= 1; else _g_boolean_var_535 = 0; _g_boolean_var_535; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
6899 g_return_val_if_fail (mime_type != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_536
; if (mime_type != ((void*)0)) _g_boolean_var_536 = 1; else _g_boolean_var_536
= 0; _g_boolean_var_536; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "mime_type != NULL"
); return ((0)); } } while (0)
;
6900
6901 if (file->details->mime_type == NULL((void*)0)) {
6902 return FALSE(0);
6903 }
6904 return g_content_type_is_a (file->details->mime_type,
6905 mime_type);
6906}
6907
6908gboolean
6909caja_file_is_launchable (CajaFile *file)
6910{
6911 gboolean type_can_be_executable;
6912
6913 type_can_be_executable = FALSE(0);
6914 if (file->details->mime_type != NULL((void*)0)) {
6915 type_can_be_executable =
6916 g_content_type_can_be_executable (file->details->mime_type);
6917 }
6918
6919 return type_can_be_executable &&
6920 caja_file_can_get_permissions (file) &&
6921 caja_file_can_execute (file) &&
6922 caja_file_is_executable (file) &&
6923 !caja_file_is_directory (file);
6924}
6925
6926
6927/**
6928 * caja_file_get_emblem_icons
6929 *
6930 * Return the list of names of emblems that this file should display,
6931 * in canonical order.
6932 * @file: CajaFile representing the file in question.
6933 *
6934 * Returns: A list of emblem names.
6935 *
6936 **/
6937GList *
6938caja_file_get_emblem_icons (CajaFile *file,
6939 char **exclude)
6940{
6941 GList *keywords, *l;
6942 GList *icons;
6943 char *icon_names[2];
6944 char *keyword;
6945 int i;
6946 GIcon *icon;
6947
6948 if (file == NULL((void*)0)) {
6949 return NULL((void*)0);
6950 }
6951
6952 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_537
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_537
= 1; else _g_boolean_var_537 = 0; _g_boolean_var_537; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6953
6954 keywords = caja_file_get_keywords (file);
6955 keywords = prepend_automatic_keywords (file, keywords);
6956
6957 icons = NULL((void*)0);
6958 for (l = keywords; l != NULL((void*)0); l = l->next) {
6959 keyword = l->data;
6960
6961#ifdef TRASH_IS_FAST_ENOUGH
6962 if (strcmp (keyword, CAJA_FILE_EMBLEM_NAME_TRASH"trash") == 0) {
6963 char *uri;
6964 gboolean file_is_trash;
6965 /* Leave out the trash emblem for the trash itself, since
6966 * putting a trash emblem on a trash icon is gilding the
6967 * lily.
6968 */
6969 uri = caja_file_get_uri (file);
6970 file_is_trash = strcmp (uri, EEL_TRASH_URI"trash:") == 0;
6971 g_free (uri);
6972 if (file_is_trash) {
6973 continue;
6974 }
6975 }
6976#endif
6977 if (exclude) {
6978 for (i = 0; exclude[i] != NULL((void*)0); i++) {
6979 if (strcmp (exclude[i], keyword) == 0) {
6980 continue;
6981 }
6982 }
6983 }
6984
6985
6986 icon_names[0] = g_strconcat ("emblem-", keyword, NULL((void*)0));
6987 icon_names[1] = keyword;
6988 icon = g_themed_icon_new_from_names (icon_names, 2);
6989 g_free (icon_names[0]);
6990
6991 icons = g_list_prepend (icons, icon);
6992 }
6993
6994 g_list_free_full (keywords, g_free);
6995
6996 return icons;
6997}
6998
6999GList *
7000caja_file_get_emblem_pixbufs (CajaFile *file,
7001 int size,
7002 gboolean force_size,
7003 char **exclude)
7004{
7005 GList *icons, *l;
7006 GList *pixbufs;
7007 GdkPixbuf *pixbuf;
7008 GIcon *icon = NULL((void*)0);
7009 CajaIconInfo *icon_info = NULL((void*)0);
7010
7011 icons = caja_file_get_emblem_icons (file, exclude);
7012 pixbufs = NULL((void*)0);
7013
7014 for (l = icons; l != NULL((void*)0); l = l->next) {
7015 icon = l->data;
7016
7017 icon_info = caja_icon_info_lookup (icon, size, 1);
7018 if (force_size) {
7019 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (icon_info, size);
7020 } else {
7021 pixbuf = caja_icon_info_get_pixbuf_nodefault (icon_info);
7022 }
7023
7024 if (pixbuf) {
7025 pixbufs = g_list_prepend (pixbufs, pixbuf);
7026 }
7027
7028
7029 g_object_unref (icon_info);
7030 g_object_unref (icon);
7031 }
7032 g_list_free (icons);
7033
7034 return g_list_reverse (pixbufs);
7035
7036
7037}
7038
7039static GList *
7040sort_keyword_list_and_remove_duplicates (GList *keywords)
7041{
7042 GList *p;
7043
7044 if (keywords != NULL((void*)0)) {
7045 GList *duplicate_link = NULL((void*)0);
7046
7047 keywords = eel_g_str_list_alphabetize (keywords);
7048
7049 p = keywords;
7050 while (p->next != NULL((void*)0)) {
7051 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) {
7052 duplicate_link = p->next;
7053 keywords = g_list_remove_link (keywords, duplicate_link);
7054 g_list_free_full (duplicate_link, g_free);
7055 } else {
7056 p = p->next;
7057 }
7058 }
7059 }
7060
7061 return keywords;
7062}
7063
7064/**
7065 * caja_file_get_keywords
7066 *
7067 * Return this file's keywords.
7068 * @file: CajaFile representing the file in question.
7069 *
7070 * Returns: A list of keywords.
7071 *
7072 **/
7073GList *
7074caja_file_get_keywords (CajaFile *file)
7075{
7076 GList *keywords;
7077
7078 if (file == NULL((void*)0)) {
7079 return NULL((void*)0);
7080 }
7081
7082 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_538
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_538
= 1; else _g_boolean_var_538 = 0; _g_boolean_var_538; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7083
7084 /* Put all the keywords into a list. */
7085 keywords = caja_file_get_metadata_list
7086 (file, CAJA_METADATA_KEY_EMBLEMS"emblems");
7087
7088 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7089 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7090
7091 return sort_keyword_list_and_remove_duplicates (keywords);
7092}
7093
7094/**
7095 * caja_file_set_keywords
7096 *
7097 * Change this file's keywords.
7098 * @file: CajaFile representing the file in question.
7099 * @keywords: New set of keywords (a GList of strings).
7100 *
7101 **/
7102void
7103caja_file_set_keywords (CajaFile *file, GList *keywords)
7104{
7105 GList *canonical_keywords;
7106
7107 /* Invalidate the emblem compare cache */
7108 g_free (file->details->compare_by_emblem_cache);
7109 file->details->compare_by_emblem_cache = NULL((void*)0);
7110
7111 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_539
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_539
= 1; else _g_boolean_var_539 = 0; _g_boolean_var_539; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7112
7113 canonical_keywords = sort_keyword_list_and_remove_duplicates
7114 (g_list_copy (keywords));
7115 caja_file_set_metadata_list
7116 (file, CAJA_METADATA_KEY_EMBLEMS"emblems", canonical_keywords);
7117 g_list_free (canonical_keywords);
7118}
7119
7120/**
7121 * caja_file_is_symbolic_link
7122 *
7123 * Check if this file is a symbolic link.
7124 * @file: CajaFile representing the file in question.
7125 *
7126 * Returns: True if the file is a symbolic link.
7127 *
7128 **/
7129gboolean
7130caja_file_is_symbolic_link (CajaFile *file)
7131{
7132 return file->details->is_symlink;
7133}
7134
7135gboolean
7136caja_file_is_mountpoint (CajaFile *file)
7137{
7138 return file->details->is_mountpoint;
7139}
7140
7141GMount *
7142caja_file_get_mount (CajaFile *file)
7143{
7144 if (file->details->mount) {
7145 return g_object_ref (file->details->mount)((__typeof__ (file->details->mount)) (g_object_ref) (file
->details->mount))
;
7146 }
7147 return NULL((void*)0);
7148}
7149
7150static void
7151file_mount_unmounted (GMount *mount,
7152 gpointer data)
7153{
7154 CajaFile *file;
7155
7156 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
7157
7158 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_MOUNT);
7159}
7160
7161void
7162caja_file_set_mount (CajaFile *file,
7163 GMount *mount)
7164{
7165 if (file->details->mount) {
7166 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
7167 g_object_unref (file->details->mount);
7168 file->details->mount = NULL((void*)0);
7169 }
7170
7171 if (mount) {
7172 file->details->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
7173 g_signal_connect (mount, "unmounted",g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
7174 G_CALLBACK (file_mount_unmounted), file)g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
;
7175 }
7176}
7177
7178/**
7179 * caja_file_is_broken_symbolic_link
7180 *
7181 * Check if this file is a symbolic link with a missing target.
7182 * @file: CajaFile representing the file in question.
7183 *
7184 * Returns: True if the file is a symbolic link with a missing target.
7185 *
7186 **/
7187gboolean
7188caja_file_is_broken_symbolic_link (CajaFile *file)
7189{
7190 if (file == NULL((void*)0)) {
7191 return FALSE(0);
7192 }
7193
7194 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_540
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_540
= 1; else _g_boolean_var_540 = 0; _g_boolean_var_540; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7195
7196 /* Non-broken symbolic links return the target's type for get_file_type. */
7197 return caja_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7198}
7199
7200static void
7201get_fs_free_cb (GObject *source_object,
7202 GAsyncResult *res,
7203 gpointer user_data)
7204{
7205 CajaDirectory *directory;
7206 guint64 free_space;
7207 GFileInfo *info;
7208
7209 directory = CAJA_DIRECTORY (user_data)((((CajaDirectory*) (void *) ((user_data)))));
7210
7211 free_space = (guint64)-1;
7212 info = g_file_query_filesystem_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
7213 res, NULL((void*)0));
7214 if (info) {
7215 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
7216 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
7217 }
7218 g_object_unref (info);
7219 }
7220
7221 if (directory->details->free_space != free_space) {
7222 CajaFile *file;
7223
7224 directory->details->free_space = free_space;
7225 file = caja_directory_get_existing_corresponding_file (directory);
7226 if (file) {
7227 caja_file_emit_changed (file);
7228 caja_file_unref (file);
7229 }
7230 }
7231 caja_directory_unref (directory);
7232}
7233
7234/**
7235 * caja_file_get_volume_free_space
7236 * Get a nicely formatted char with free space on the file's volume
7237 * @file: CajaFile representing the file in question.
7238 *
7239 * Returns: newly-allocated copy of file size in a formatted string
7240 */
7241char *
7242caja_file_get_volume_free_space (CajaFile *file)
7243{
7244 CajaDirectory *directory;
7245 char *res;
7246 time_t now;
7247
7248 directory = caja_directory_get_for_file (file);
7249
7250 now = time (NULL((void*)0));
7251 /* Update first time and then every 2 seconds */
7252 if (directory->details->free_space_read == 0 ||
7253 (now - directory->details->free_space_read) > 2) {
7254 GFile *location;
7255
7256 directory->details->free_space_read = now;
7257 location = caja_file_get_location (file);
7258 g_file_query_filesystem_info_async (location,
7259 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free",
7260 0, NULL((void*)0),
7261 get_fs_free_cb,
7262 directory); /* Inherits ref */
7263 g_object_unref (location);
7264 } else {
7265 caja_directory_unref (directory);
7266 }
7267
7268
7269 res = NULL((void*)0);
7270
7271 if (directory->details->free_space != (guint64) -1)
7272 {
7273 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
7274 res = g_format_size_full (directory->details->free_space, G_FORMAT_SIZE_IEC_UNITS);
7275 else
7276 res = g_format_size(directory->details->free_space);
7277 }
7278
7279 return res;
7280}
7281
7282/**
7283 * caja_file_get_volume_name
7284 * Get the path of the volume the file resides on
7285 * @file: CajaFile representing the file in question.
7286 *
7287 * Returns: newly-allocated copy of the volume name of the target file,
7288 * if the volume name isn't set, it returns the mount path of the volume
7289 */
7290char *
7291caja_file_get_volume_name (CajaFile *file)
7292{
7293 GFile *location;
7294 char *res;
7295 GMount *mount;
7296
7297 res = NULL((void*)0);
7298
7299 location = caja_file_get_location (file);
7300 mount = g_file_find_enclosing_mount (location, NULL((void*)0), NULL((void*)0));
7301 if (mount) {
7302 res = g_strdup (g_mount_get_name (mount))g_strdup_inline (g_mount_get_name (mount));
7303 g_object_unref (mount);
7304 }
7305 g_object_unref (location);
7306
7307 return res;
7308}
7309
7310/**
7311 * caja_file_get_symbolic_link_target_path
7312 *
7313 * Get the file path of the target of a symbolic link. It is an error
7314 * to call this function on a file that isn't a symbolic link.
7315 * @file: CajaFile representing the symbolic link in question.
7316 *
7317 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7318 */
7319char *
7320caja_file_get_symbolic_link_target_path (CajaFile *file)
7321{
7322 if (!caja_file_is_symbolic_link (file)) {
7323 g_warning ("File has symlink target, but is not marked as symlink");
7324 }
7325
7326 return g_strdup (file->details->symlink_name)g_strdup_inline (file->details->symlink_name);
7327}
7328
7329/**
7330 * caja_file_get_symbolic_link_target_uri
7331 *
7332 * Get the uri of the target of a symbolic link. It is an error
7333 * to call this function on a file that isn't a symbolic link.
7334 * @file: CajaFile representing the symbolic link in question.
7335 *
7336 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7337 */
7338char *
7339caja_file_get_symbolic_link_target_uri (CajaFile *file)
7340{
7341 if (!caja_file_is_symbolic_link (file)) {
7342 g_warning ("File has symlink target, but is not marked as symlink");
7343 }
7344
7345 if (file->details->symlink_name == NULL((void*)0)) {
7346 return NULL((void*)0);
7347 } else {
7348 GFile *location, *parent, *target;
7349 char *target_uri;
7350
7351 target = NULL((void*)0);
7352
7353 location = caja_file_get_location (file);
7354 parent = g_file_get_parent (location);
7355 g_object_unref (location);
7356 if (parent) {
7357 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7358 g_object_unref (parent);
7359 }
7360
7361 target_uri = NULL((void*)0);
7362 if (target) {
7363 target_uri = g_file_get_uri (target);
7364 g_object_unref (target);
7365 }
7366 return target_uri;
7367 }
7368}
7369
7370/**
7371 * caja_file_is_caja_link
7372 *
7373 * Check if this file is a "caja link", meaning a historical
7374 * caja xml link file or a desktop file.
7375 * @file: CajaFile representing the file in question.
7376 *
7377 * Returns: True if the file is a caja link.
7378 *
7379 **/
7380gboolean
7381caja_file_is_caja_link (CajaFile *file)
7382{
7383 if (file->details->mime_type == NULL((void*)0))
7384 {
7385 return FALSE(0);
7386 }
7387 return g_content_type_equals (file->details->mime_type,
7388 "application/x-desktop");
7389}
7390
7391/**
7392 * caja_file_is_directory
7393 *
7394 * Check if this file is a directory.
7395 * @file: CajaFile representing the file in question.
7396 *
7397 * Returns: TRUE if @file is a directory.
7398 *
7399 **/
7400gboolean
7401caja_file_is_directory (CajaFile *file)
7402{
7403 return caja_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
7404}
7405
7406/**
7407 * caja_file_is_user_special_directory
7408 *
7409 * Check if this file is a special platform directory.
7410 * @file: CajaFile representing the file in question.
7411 * @special_directory: GUserDirectory representing the type to test for
7412 *
7413 * Returns: TRUE if @file is a special directory of the given kind.
7414 */
7415gboolean
7416caja_file_is_user_special_directory (CajaFile *file,
7417 GUserDirectory special_directory)
7418{
7419 gboolean is_special_dir;
7420 const gchar *special_dir;
7421
7422 special_dir = g_get_user_special_dir (special_directory);
7423 is_special_dir = FALSE(0);
7424
7425 if (special_dir) {
7426 GFile *loc;
7427 GFile *special_gfile;
7428
7429 loc = caja_file_get_location (file);
7430 special_gfile = g_file_new_for_path (special_dir);
7431 is_special_dir = g_file_equal (loc, special_gfile);
7432 g_object_unref (special_gfile);
7433 g_object_unref (loc);
7434 }
7435
7436 return is_special_dir;
7437}
7438
7439gboolean
7440caja_file_is_archive (CajaFile *file)
7441{
7442 char *mime_type;
7443 int i;
7444 static const char * archive_mime_types[] = { "application/x-gtar",
7445 "application/x-zip",
7446 "application/x-zip-compressed",
7447 "application/zip",
7448 "application/x-zip",
7449 "application/x-tar",
7450 "application/x-7z-compressed",
7451 "application/x-rar",
7452 "application/x-rar-compressed",
7453 "application/x-jar",
7454 "application/x-java-archive",
7455 "application/x-war",
7456 "application/x-ear",
7457 "application/x-arj",
7458 "application/x-gzip",
7459 "application/x-bzip-compressed-tar",
7460 "application/x-compressed-tar" };
7461
7462 g_return_val_if_fail (file != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_541
; if (file != ((void*)0)) _g_boolean_var_541 = 1; else _g_boolean_var_541
= 0; _g_boolean_var_541; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file != NULL"); return
((0)); } } while (0)
;
7463
7464 mime_type = caja_file_get_mime_type (file);
7465 for (i = 0; i < G_N_ELEMENTS (archive_mime_types)(sizeof (archive_mime_types) / sizeof ((archive_mime_types)[0
]))
; i++) {
7466 if (!strcmp (mime_type, archive_mime_types[i])) {
7467 g_free (mime_type);
7468 return TRUE(!(0));
7469 }
7470 }
7471 g_free (mime_type);
7472
7473 return FALSE(0);
7474}
7475
7476
7477/**
7478 * caja_file_is_in_trash
7479 *
7480 * Check if this file is a file in trash.
7481 * @file: CajaFile representing the file in question.
7482 *
7483 * Returns: TRUE if @file is in a trash.
7484 *
7485 **/
7486gboolean
7487caja_file_is_in_trash (CajaFile *file)
7488{
7489 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_542
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_542
= 1; else _g_boolean_var_542 = 0; _g_boolean_var_542; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7489, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7490
7491 return caja_directory_is_in_trash (file->details->directory);
7492}
7493
7494GError *
7495caja_file_get_file_info_error (CajaFile *file)
7496{
7497 if (!file->details->get_info_failed) {
7498 return NULL((void*)0);
7499 }
7500
7501 return file->details->get_info_error;
7502}
7503
7504/**
7505 * caja_file_contains_text
7506 *
7507 * Check if this file contains text.
7508 * This is private and is used to decide whether or not to read the top left text.
7509 * @file: CajaFile representing the file in question.
7510 *
7511 * Returns: TRUE if @file has a text MIME type.
7512 *
7513 **/
7514gboolean
7515caja_file_contains_text (CajaFile *file)
7516{
7517 if (file == NULL((void*)0)) {
7518 return FALSE(0);
7519 }
7520
7521 /* All text files inherit from text/plain */
7522 return caja_file_is_mime_type (file, "text/plain");
7523}
7524
7525/**
7526 * caja_file_is_binary
7527 *
7528 * Check if this file is a binary file.
7529 * This is private and is used to decide whether or not to show the diff
7530 * button in the file conflict dialog.
7531 * @file: CajaFile representing the file in question.
7532 *
7533 * Returns: TRUE if @file is a binary file.
7534 *
7535 **/
7536gboolean
7537caja_file_is_binary (CajaFile *file)
7538{
7539 if (!caja_file_can_read(file))
7540 {
7541 return FALSE(0);
7542 }
7543
7544 gboolean is_binary = FALSE(0);
7545 int i = 0;
7546 FILE *fp;
7547
7548 /* Check the first 4096 bytes of the files. If these contains a 0,
7549 * we can assume the file is binary.
7550 * This idea is taken from python code of meld.
7551 */
7552
7553 fp = g_fopenfopen (g_file_get_path (caja_file_get_location (file)), "r");
7554 if (fp == NULL((void*)0))
7555 {
7556 return FALSE(0);
7557 }
7558
7559 while (!feof (fp)) {
7560 int c;
7561
7562 if (i > 4096) {
7563 break;
7564 }
7565 c = fgetc(fp);
7566 if (c == 0) {
7567 is_binary = TRUE(!(0));
7568 break;
7569 }
7570 i++;
7571 }
7572 fclose(fp);
7573
7574 return is_binary;
7575}
7576
7577/**
7578 * caja_file_is_executable
7579 *
7580 * Check if this file is executable at all.
7581 * @file: CajaFile representing the file in question.
7582 *
7583 * Returns: TRUE if any of the execute bits are set. FALSE if
7584 * not, or if the permissions are unknown.
7585 *
7586 **/
7587gboolean
7588caja_file_is_executable (CajaFile *file)
7589{
7590 if (!file->details->has_permissions) {
7591 /* File's permissions field is not valid.
7592 * Can't access specific permissions, so return FALSE.
7593 */
7594 return FALSE(0);
7595 }
7596
7597 return file->details->can_execute;
7598}
7599
7600/**
7601 * caja_file_peek_top_left_text
7602 *
7603 * Peek at the text from the top left of the file.
7604 * @file: CajaFile representing the file in question.
7605 *
7606 * Returns: NULL if there is no text readable, otherwise, the text.
7607 * This string is owned by the file object and should not
7608 * be kept around or freed.
7609 *
7610 **/
7611char *
7612caja_file_peek_top_left_text (CajaFile *file,
7613 gboolean need_large_text,
7614 gboolean *needs_loading)
7615{
7616 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_543
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_543
= 1; else _g_boolean_var_543 = 0; _g_boolean_var_543; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7617
7618 if (!caja_file_should_get_top_left_text (file)) {
7619 if (needs_loading) {
7620 *needs_loading = FALSE(0);
7621 }
7622 return NULL((void*)0);
7623 }
7624
7625 if (needs_loading) {
7626 *needs_loading = !file->details->top_left_text_is_up_to_date;
7627 if (need_large_text) {
7628 *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text;
7629 }
7630 }
7631
7632 /* Show " ..." in the file until we read the contents in. */
7633 if (!file->details->got_top_left_text) {
7634
7635 if (caja_file_contains_text (file)) {
7636 return " ...";
7637 }
7638 return NULL((void*)0);
7639 }
7640
7641 /* Show what we read in. */
7642 return file->details->top_left_text;
7643}
7644
7645/**
7646 * caja_file_get_top_left_text
7647 *
7648 * Get the text from the top left of the file.
7649 * @file: CajaFile representing the file in question.
7650 *
7651 * Returns: NULL if there is no text readable, otherwise, the text.
7652 *
7653 **/
7654char *
7655caja_file_get_top_left_text (CajaFile *file)
7656{
7657 return g_strdup (caja_file_peek_top_left_text (file, FALSE, NULL))g_strdup_inline (caja_file_peek_top_left_text (file, (0), ((void
*)0)))
;
7658}
7659
7660char *
7661caja_file_get_filesystem_id (CajaFile *file)
7662{
7663 return g_strdup (file->details->filesystem_id)g_strdup_inline (file->details->filesystem_id);
7664}
7665
7666CajaFile *
7667caja_file_get_trash_original_file (CajaFile *file)
7668{
7669 CajaFile *original_file;
7670
7671 original_file = NULL((void*)0);
7672
7673 if (file->details->trash_orig_path != NULL((void*)0)) {
7674 GFile *location;
7675
7676 location = g_file_new_for_path (file->details->trash_orig_path);
7677 original_file = caja_file_get (location);
7678 g_object_unref (location);
7679 }
7680
7681 return original_file;
7682
7683}
7684
7685void
7686caja_file_mark_gone (CajaFile *file)
7687{
7688 CajaDirectory *directory;
7689
7690 if (file->details->is_gone)
7691 return;
7692
7693 file->details->is_gone = TRUE(!(0));
7694
7695 update_links_if_target (file);
7696
7697 /* Drop it from the symlink hash ! */
7698 remove_from_link_hash_table (file);
7699
7700 /* Let the directory know it's gone. */
7701 directory = file->details->directory;
7702 if (!caja_file_is_self_owned (file)) {
7703 caja_directory_remove_file (directory, file);
7704 }
7705
7706 caja_file_clear_info (file);
7707
7708 /* FIXME bugzilla.gnome.org 42429:
7709 * Maybe we can get rid of the name too eventually, but
7710 * for now that would probably require too many if statements
7711 * everywhere anyone deals with the name. Maybe we can give it
7712 * a hard-coded "<deleted>" name or something.
7713 */
7714}
7715
7716/**
7717 * caja_file_changed
7718 *
7719 * Notify the user that this file has changed.
7720 * @file: CajaFile representing the file in question.
7721 **/
7722void
7723caja_file_changed (CajaFile *file)
7724{
7725 GList fake_list;
7726
7727 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_544
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_544
= 1; else _g_boolean_var_544 = 0; _g_boolean_var_544; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7728
7729 if (caja_file_is_self_owned (file)) {
7730 caja_file_emit_changed (file);
7731 } else {
7732 fake_list.data = file;
7733 fake_list.next = NULL((void*)0);
7734 fake_list.prev = NULL((void*)0);
7735 caja_directory_emit_change_signals
7736 (file->details->directory, &fake_list);
7737 }
7738}
7739
7740/**
7741 * caja_file_updated_deep_count_in_progress
7742 *
7743 * Notify clients that a newer deep count is available for
7744 * the directory in question.
7745 */
7746void
7747caja_file_updated_deep_count_in_progress (CajaFile *file) {
7748 GList *link_files, *node;
7749
7750 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_545
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_545
= 1; else _g_boolean_var_545 = 0; _g_boolean_var_545; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7750, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7751 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_546
; if (caja_file_is_directory (file)) _g_boolean_var_546 = 1; else
_g_boolean_var_546 = 0; _g_boolean_var_546; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 7751, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
7752
7753 /* Send out a signal. */
7754 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
7755
7756 /* Tell link files pointing to this object about the change. */
7757 link_files = get_link_files (file);
7758 for (node = link_files; node != NULL((void*)0); node = node->next) {
7759 caja_file_updated_deep_count_in_progress (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))));
7760 }
7761 caja_file_list_free (link_files);
7762}
7763
7764/**
7765 * caja_file_emit_changed
7766 *
7767 * Emit a file changed signal.
7768 * This can only be called by the directory, since the directory
7769 * also has to emit a files_changed signal.
7770 *
7771 * @file: CajaFile representing the file in question.
7772 **/
7773void
7774caja_file_emit_changed (CajaFile *file)
7775{
7776 GList *link_files, *p;
7777
7778 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_547
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_547
= 1; else _g_boolean_var_547 = 0; _g_boolean_var_547; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7778, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7779
7780
7781 /* Invalidate the emblem compare cache. -- This is not the cleanest
7782 * place to do it but it is the one guaranteed bottleneck through
7783 * which all change notifications pass.
7784 */
7785 g_free (file->details->compare_by_emblem_cache);
7786 file->details->compare_by_emblem_cache = NULL((void*)0);
7787
7788 /* Send out a signal. */
7789 g_signal_emit (file, signals[CHANGED], 0, file);
7790
7791 /* Tell link files pointing to this object about the change. */
7792 link_files = get_link_files (file);
7793 for (p = link_files; p != NULL((void*)0); p = p->next) {
7794 if (p->data != file) {
7795 caja_file_changed (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
7796 }
7797 }
7798 caja_file_list_free (link_files);
7799}
7800
7801/**
7802 * caja_file_is_gone
7803 *
7804 * Check if a file has already been deleted.
7805 * @file: CajaFile representing the file in question.
7806 *
7807 * Returns: TRUE if the file is already gone.
7808 **/
7809gboolean
7810caja_file_is_gone (CajaFile *file)
7811{
7812 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_548
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_548
= 1; else _g_boolean_var_548 = 0; _g_boolean_var_548; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7813
7814 return file->details->is_gone;
7815}
7816
7817/**
7818 * caja_file_is_not_yet_confirmed
7819 *
7820 * Check if we're in a state where we don't know if a file really
7821 * exists or not, before the initial I/O is complete.
7822 * @file: CajaFile representing the file in question.
7823 *
7824 * Returns: TRUE if the file is already gone.
7825 **/
7826gboolean
7827caja_file_is_not_yet_confirmed (CajaFile *file)
7828{
7829 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_549
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_549
= 1; else _g_boolean_var_549 = 0; _g_boolean_var_549; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7830
7831 return !file->details->got_file_info;
7832}
7833
7834/**
7835 * caja_file_check_if_ready
7836 *
7837 * Check whether the values for a set of file attributes are
7838 * currently available, without doing any additional work. This
7839 * is useful for callers that want to reflect updated information
7840 * when it is ready but don't want to force the work required to
7841 * obtain the information, which might be slow network calls, e.g.
7842 *
7843 * @file: The file being queried.
7844 * @file_attributes: A bit-mask with the desired information.
7845 *
7846 * Return value: TRUE if all of the specified attributes are currently readable.
7847 */
7848gboolean
7849caja_file_check_if_ready (CajaFile *file,
7850 CajaFileAttributes file_attributes)
7851{
7852 /* To be parallel with call_when_ready, return
7853 * TRUE for NULL file.
7854 */
7855 if (file == NULL((void*)0)) {
7856 return TRUE(!(0));
7857 }
7858
7859 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_550
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_550
= 1; else _g_boolean_var_550 = 0; _g_boolean_var_550; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7860
7861 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7862 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7863 check_if_ready, (file, file_attributes))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
;
7864}
7865
7866void
7867caja_file_call_when_ready (CajaFile *file,
7868 CajaFileAttributes file_attributes,
7869 CajaFileCallback callback,
7870 gpointer callback_data)
7871
7872{
7873 if (file == NULL((void*)0)) {
7874 (* callback) (file, callback_data);
7875 return;
7876 }
7877
7878 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_551
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_551
= 1; else _g_boolean_var_551 = 0; _g_boolean_var_551; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7879
7880 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7881 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7882 call_when_ready, (file, file_attributes,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7883 callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
;
7884}
7885
7886void
7887caja_file_cancel_call_when_ready (CajaFile *file,
7888 CajaFileCallback callback,
7889 gpointer callback_data)
7890{
7891 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_552
; if (callback != ((void*)0)) _g_boolean_var_552 = 1; else _g_boolean_var_552
= 0; _g_boolean_var_552; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
7892
7893 if (file == NULL((void*)0)) {
7894 return;
7895 }
7896
7897 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_553
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_553
= 1; else _g_boolean_var_553 = 0; _g_boolean_var_553; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7898
7899 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7900 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7901 cancel_call_when_ready, (file, callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
;
7902}
7903
7904static void
7905invalidate_directory_count (CajaFile *file)
7906{
7907 file->details->directory_count_is_up_to_date = FALSE(0);
7908}
7909
7910static void
7911invalidate_deep_counts (CajaFile *file)
7912{
7913 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
7914}
7915
7916static void
7917invalidate_mime_list (CajaFile *file)
7918{
7919 file->details->mime_list_is_up_to_date = FALSE(0);
7920}
7921
7922static void
7923invalidate_top_left_text (CajaFile *file)
7924{
7925 file->details->top_left_text_is_up_to_date = FALSE(0);
7926}
7927
7928static void
7929invalidate_file_info (CajaFile *file)
7930{
7931 file->details->file_info_is_up_to_date = FALSE(0);
7932}
7933
7934static void
7935invalidate_link_info (CajaFile *file)
7936{
7937 file->details->link_info_is_up_to_date = FALSE(0);
7938}
7939
7940static void
7941invalidate_thumbnail (CajaFile *file)
7942{
7943 file->details->thumbnail_is_up_to_date = FALSE(0);
7944}
7945
7946static void
7947invalidate_mount (CajaFile *file)
7948{
7949 file->details->mount_is_up_to_date = FALSE(0);
7950}
7951
7952void
7953caja_file_invalidate_extension_info_internal (CajaFile *file)
7954{
7955 if (file->details->pending_info_providers)
7956 g_list_free_full (file->details->pending_info_providers, g_object_unref);
7957
7958 file->details->pending_info_providers =
7959 caja_extensions_get_for_type (CAJA_TYPE_INFO_PROVIDER(caja_info_provider_get_type ()));
7960}
7961
7962void
7963caja_file_invalidate_attributes_internal (CajaFile *file,
7964 CajaFileAttributes file_attributes)
7965{
7966 Request request;
7967
7968 if (file == NULL((void*)0)) {
7969 return;
7970 }
7971
7972 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
7973 /* Desktop icon files are always up to date.
7974 * If we invalidate their attributes they
7975 * will lose data, so we just ignore them.
7976 */
7977 return;
7978 }
7979
7980 request = caja_directory_set_up_request (file_attributes);
7981
7982 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)((request) & (1<<(REQUEST_DIRECTORY_COUNT)))) {
7983 invalidate_directory_count (file);
7984 }
7985 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)((request) & (1<<(REQUEST_DEEP_COUNT)))) {
7986 invalidate_deep_counts (file);
7987 }
7988 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)((request) & (1<<(REQUEST_MIME_LIST)))) {
7989 invalidate_mime_list (file);
7990 }
7991 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)((request) & (1<<(REQUEST_FILE_INFO)))) {
7992 invalidate_file_info (file);
7993 }
7994 if (REQUEST_WANTS_TYPE (request, REQUEST_TOP_LEFT_TEXT)((request) & (1<<(REQUEST_TOP_LEFT_TEXT)))) {
7995 invalidate_top_left_text (file);
7996 }
7997 if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)((request) & (1<<(REQUEST_LINK_INFO)))) {
7998 invalidate_link_info (file);
7999 }
8000 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)((request) & (1<<(REQUEST_EXTENSION_INFO)))) {
8001 caja_file_invalidate_extension_info_internal (file);
8002 }
8003 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)((request) & (1<<(REQUEST_THUMBNAIL)))) {
8004 invalidate_thumbnail (file);
8005 }
8006 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)((request) & (1<<(REQUEST_MOUNT)))) {
8007 invalidate_mount (file);
8008 }
8009
8010 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
8011}
8012
8013gboolean
8014caja_file_has_open_window (CajaFile *file)
8015{
8016 return file->details->has_open_window;
8017}
8018
8019void
8020caja_file_set_has_open_window (CajaFile *file,
8021 gboolean has_open_window)
8022{
8023 has_open_window = (has_open_window != FALSE(0));
8024
8025 if (file->details->has_open_window != has_open_window) {
8026 file->details->has_open_window = has_open_window;
8027 caja_file_changed (file);
8028 }
8029}
8030
8031
8032gboolean
8033caja_file_is_thumbnailing (CajaFile *file)
8034{
8035 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_554
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_554
= 1; else _g_boolean_var_554 = 0; _g_boolean_var_554; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
8036
8037 return file->details->is_thumbnailing;
8038}
8039
8040void
8041caja_file_set_is_thumbnailing (CajaFile *file,
8042 gboolean is_thumbnailing)
8043{
8044 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_555
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_555
= 1; else _g_boolean_var_555 = 0; _g_boolean_var_555; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
8045
8046 file->details->is_thumbnailing = is_thumbnailing;
8047}
8048
8049
8050/**
8051 * caja_file_invalidate_attributes
8052 *
8053 * Invalidate the specified attributes and force a reload.
8054 * @file: CajaFile representing the file in question.
8055 * @file_attributes: attributes to froget.
8056 **/
8057
8058void
8059caja_file_invalidate_attributes (CajaFile *file,
8060 CajaFileAttributes file_attributes)
8061{
8062 /* Cancel possible in-progress loads of any of these attributes */
8063 caja_directory_cancel_loading_file_attributes (file->details->directory,
8064 file,
8065 file_attributes);
8066
8067 /* Actually invalidate the values */
8068 caja_file_invalidate_attributes_internal (file, file_attributes);
8069
8070 caja_directory_add_file_to_work_queue (file->details->directory, file);
8071
8072 /* Kick off I/O if necessary */
8073 caja_directory_async_state_changed (file->details->directory);
8074}
8075
8076CajaFileAttributes
8077caja_file_get_all_attributes (void)
8078{
8079 return CAJA_FILE_ATTRIBUTE_INFO |
8080 CAJA_FILE_ATTRIBUTE_LINK_INFO |
8081 CAJA_FILE_ATTRIBUTE_DEEP_COUNTS |
8082 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8083 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8084 CAJA_FILE_ATTRIBUTE_TOP_LEFT_TEXT |
8085 CAJA_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
8086 CAJA_FILE_ATTRIBUTE_EXTENSION_INFO |
8087 CAJA_FILE_ATTRIBUTE_THUMBNAIL |
8088 CAJA_FILE_ATTRIBUTE_MOUNT;
8089}
8090
8091void
8092caja_file_invalidate_all_attributes (CajaFile *file)
8093{
8094 CajaFileAttributes all_attributes;
8095
8096 all_attributes = caja_file_get_all_attributes ();
8097 caja_file_invalidate_attributes (file, all_attributes);
8098}
8099
8100
8101/**
8102 * caja_file_dump
8103 *
8104 * Debugging call, prints out the contents of the file
8105 * fields.
8106 *
8107 * @file: file to dump.
8108 **/
8109void
8110caja_file_dump (CajaFile *file)
8111{
8112 long size = file->details->deep_size;
8113 long size_on_disk = file->details->deep_size_on_disk;
8114 char *uri;
8115 const char *file_kind;
8116
8117 uri = caja_file_get_uri (file);
8118 g_print ("uri: %s \n", uri);
8119 if (!file->details->got_file_info) {
8120 g_print ("no file info \n");
8121 } else if (file->details->get_info_failed) {
8122 g_print ("failed to get file info \n");
8123 } else {
8124 g_print ("size: %ld \n", size);
8125 g_print ("disk size: %ld \n", size_on_disk);
8126 switch (file->details->type) {
8127 case G_FILE_TYPE_REGULAR:
8128 file_kind = "regular file";
8129 break;
8130 case G_FILE_TYPE_DIRECTORY:
8131 file_kind = "folder";
8132 break;
8133 case G_FILE_TYPE_SPECIAL:
8134 file_kind = "special";
8135 break;
8136 case G_FILE_TYPE_SYMBOLIC_LINK:
8137 file_kind = "symbolic link";
8138 break;
8139 case G_FILE_TYPE_UNKNOWN:
8140 default:
8141 file_kind = "unknown";
8142 break;
8143 }
8144 g_print ("kind: %s \n", file_kind);
8145 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) {
8146 g_print ("link to %s \n", file->details->symlink_name);
8147 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8148 }
8149 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8150 }
8151 g_free (uri);
8152}
8153
8154/**
8155 * caja_file_list_ref
8156 *
8157 * Ref all the files in a list.
8158 * @list: GList of files.
8159 **/
8160GList *
8161caja_file_list_ref (GList *list)
8162{
8163 g_list_foreach (list, (GFunc) caja_file_ref, NULL((void*)0));
8164 return list;
8165}
8166
8167/**
8168 * caja_file_list_unref
8169 *
8170 * Unref all the files in a list.
8171 * @list: GList of files.
8172 **/
8173void
8174caja_file_list_unref (GList *list)
8175{
8176 g_list_foreach (list, (GFunc) caja_file_unref, NULL((void*)0));
8177}
8178
8179/**
8180 * caja_file_list_free
8181 *
8182 * Free a list of files after unrefing them.
8183 * @list: GList of files.
8184 **/
8185void
8186caja_file_list_free (GList *list)
8187{
8188 caja_file_list_unref (list);
8189 g_list_free (list);
8190}
8191
8192/**
8193 * caja_file_list_copy
8194 *
8195 * Copy the list of files, making a new ref of each,
8196 * @list: GList of files.
8197 **/
8198GList *
8199caja_file_list_copy (GList *list)
8200{
8201 return g_list_copy (caja_file_list_ref (list));
8202}
8203
8204static gboolean
8205get_attributes_for_default_sort_type (CajaFile *file,
8206 gboolean *is_download,
8207 gboolean *is_trash)
8208{
8209 gboolean is_download_dir, is_desktop_dir, is_trash_dir, retval;
8210
8211 *is_download = FALSE(0);
8212 *is_trash = FALSE(0);
8213 retval = FALSE(0);
8214
8215 /* special handling for certain directories */
8216 if (file && caja_file_is_directory (file)) {
8217 is_download_dir =
8218 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8219 is_desktop_dir =
8220 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP);
8221 is_trash_dir =
8222 caja_file_is_in_trash (file);
8223
8224 if (is_download_dir && !is_desktop_dir) {
8225 *is_download = TRUE(!(0));
8226 retval = TRUE(!(0));
8227 } else if (is_trash_dir) {
8228 *is_trash = TRUE(!(0));
8229 retval = TRUE(!(0));
8230 }
8231 }
8232
8233 return retval;
8234}
8235
8236CajaFileSortType
8237caja_file_get_default_sort_type (CajaFile *file,
8238 gboolean *reversed)
8239{
8240 CajaFileSortType retval;
8241 gboolean is_download, is_trash, res;
8242
8243 retval = CAJA_FILE_SORT_NONE;
8244 is_download = is_trash = FALSE(0);
8245 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8246
8247 if (res) {
8248 if (is_download) {
8249 retval = CAJA_FILE_SORT_BY_MTIME;
8250 } else if (is_trash) {
8251 retval = CAJA_FILE_SORT_BY_TRASHED_TIME;
8252 }
8253
8254 if (reversed != NULL((void*)0)) {
8255 *reversed = res;
8256 }
8257 }
8258
8259 return retval;
8260}
8261
8262const gchar *
8263caja_file_get_default_sort_attribute (CajaFile *file,
8264 gboolean *reversed)
8265{
8266 const gchar *retval;
8267 gboolean is_download, is_trash, res;
8268
8269 retval = NULL((void*)0);
8270 is_download = is_trash = FALSE(0);
8271 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8272
8273 if (res) {
8274 if (is_download) {
8275 retval = g_quark_to_string (attribute_date_modified_q);
8276 } else if (is_trash) {
8277 retval = g_quark_to_string (attribute_trashed_on_q);
8278 }
8279
8280 if (reversed != NULL((void*)0)) {
8281 *reversed = res;
8282 }
8283 }
8284
8285 return retval;
8286}
8287
8288static int
8289compare_by_display_name_cover (gconstpointer a, gconstpointer b)
8290{
8291 return compare_by_display_name (CAJA_FILE (a)((((CajaFile*) (void *) ((a))))), CAJA_FILE (b)((((CajaFile*) (void *) ((b))))));
8292}
8293
8294/**
8295 * caja_file_list_sort_by_display_name
8296 *
8297 * Sort the list of files by file name.
8298 * @list: GList of files.
8299 **/
8300GList *
8301caja_file_list_sort_by_display_name (GList *list)
8302{
8303 return g_list_sort (list, compare_by_display_name_cover);
8304}
8305
8306static GList *ready_data_list = NULL((void*)0);
8307
8308typedef struct
8309{
8310 GList *file_list;
8311 GList *remaining_files;
8312 CajaFileListCallback callback;
8313 gpointer callback_data;
8314} FileListReadyData;
8315
8316static void
8317file_list_ready_data_free (FileListReadyData *data)
8318{
8319 GList *l;
8320
8321 l = g_list_find (ready_data_list, data);
8322 if (l != NULL((void*)0)) {
8323 ready_data_list = g_list_delete_link (ready_data_list, l);
8324
8325 caja_file_list_free (data->file_list);
8326 g_list_free (data->remaining_files);
8327 g_free (data);
8328 }
8329}
8330
8331static FileListReadyData *
8332file_list_ready_data_new (GList *file_list,
8333 CajaFileListCallback callback,
8334 gpointer callback_data)
8335{
8336 FileListReadyData *data;
8337
8338 data = g_new0 (FileListReadyData, 1)(FileListReadyData *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (FileListReadyData); 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; }))
;
8339 data->file_list = caja_file_list_copy (file_list);
8340 data->remaining_files = g_list_copy (file_list);
8341 data->callback = callback;
8342 data->callback_data = callback_data;
8343
8344 ready_data_list = g_list_prepend (ready_data_list, data);
8345
8346 return data;
8347}
8348
8349static void
8350file_list_file_ready_callback (CajaFile *file,
8351 gpointer user_data)
8352{
8353 FileListReadyData *data;
8354
8355 data = user_data;
8356 data->remaining_files = g_list_remove (data->remaining_files, file);
8357
8358 if (data->remaining_files == NULL((void*)0)) {
8359 if (data->callback) {
8360 (*data->callback) (data->file_list, data->callback_data);
8361 }
8362
8363 file_list_ready_data_free (data);
8364 }
8365}
8366
8367void
8368caja_file_list_call_when_ready (GList *file_list,
8369 CajaFileAttributes attributes,
8370 CajaFileListHandle **handle,
8371 CajaFileListCallback callback,
8372 gpointer callback_data)
8373{
8374 GList *l;
8375 FileListReadyData *data;
8376 CajaFile *file = NULL((void*)0);
8377
8378 g_return_if_fail (file_list != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_556
; if (file_list != ((void*)0)) _g_boolean_var_556 = 1; else _g_boolean_var_556
= 0; _g_boolean_var_556; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_list != NULL"
); return; } } while (0)
;
8379
8380 data = file_list_ready_data_new
8381 (file_list, callback, callback_data);
8382
8383 if (handle) {
8384 *handle = (CajaFileListHandle *) data;
8385 }
8386
8387
8388 l = file_list;
8389 while (l != NULL((void*)0)) {
8390 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8391 /* Need to do this here, as the list can be modified by this call */
8392 l = l->next;
8393
8394 if (file)
8395 caja_file_call_when_ready (file,
8396 attributes,
8397 file_list_file_ready_callback,
8398 data);
8399 }
8400}
8401
8402void
8403caja_file_list_cancel_call_when_ready (CajaFileListHandle *handle)
8404{
8405 GList *l;
8406 FileListReadyData *data;
8407
8408 g_return_if_fail (handle != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_557
; if (handle != ((void*)0)) _g_boolean_var_557 = 1; else _g_boolean_var_557
= 0; _g_boolean_var_557; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "handle != NULL")
; return; } } while (0)
;
8409
8410 data = (FileListReadyData *) handle;
8411
8412 l = g_list_find (ready_data_list, data);
8413 if (l != NULL((void*)0)) {
8414 CajaFile *file = NULL((void*)0);
8415
8416 for (l = data->remaining_files; l != NULL((void*)0); l = l->next) {
8417 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8418
8419 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8420 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8421 cancel_call_when_ready, (file, file_list_file_ready_callback, data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
;
8422 }
8423
8424 file_list_ready_data_free (data);
8425 }
8426}
8427
8428static char *
8429try_to_make_utf8 (const char *text, int *length)
8430{
8431 static const char *encodings_to_try[2];
8432 static int n_encodings_to_try = 0;
8433 gsize converted_length;
8434 GError *conversion_error;
8435 char *utf8_text;
8436 int i;
8437
8438 if (n_encodings_to_try == 0) {
8439 const char *charset;
8440 gboolean charset_is_utf8;
8441
8442 charset_is_utf8 = g_get_charset (&charset);
8443 if (!charset_is_utf8) {
8444 encodings_to_try[n_encodings_to_try++] = charset;
8445 }
8446
8447 if (g_ascii_strcasecmp (charset, "ISO-8859-1") != 0) {
8448 encodings_to_try[n_encodings_to_try++] = "ISO-8859-1";
8449 }
8450 }
8451
8452 utf8_text = NULL((void*)0);
8453 for (i = 0; i < n_encodings_to_try; i++) {
8454 conversion_error = NULL((void*)0);
8455 utf8_text = g_convert (text, *length,
8456 "UTF-8", encodings_to_try[i],
8457 NULL((void*)0), &converted_length, &conversion_error);
8458 if (utf8_text != NULL((void*)0)) {
8459 *length = converted_length;
8460 break;
8461 }
8462 g_error_free (conversion_error);
8463 }
8464
8465 return utf8_text;
8466}
8467
8468
8469
8470/* Extract the top left part of the read-in text. */
8471char *
8472caja_extract_top_left_text (const char *text,
8473 gboolean large,
8474 int length)
8475{
8476 GString* buffer;
8477 const gchar *in;
8478 const gchar *end;
8479 int line, i;
8480 gunichar c;
8481 char *text_copy;
8482 const char *utf8_end;
8483 gboolean validated;
8484 int max_bytes, max_lines, max_cols;
8485
8486 if (large) {
8487 max_bytes = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES10000;
8488 max_lines = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES24;
8489 max_cols = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE80;
8490 } else {
8491 max_bytes = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES1024;
8492 max_lines = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES5;
8493 max_cols = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE10;
8494 }
8495
8496
8497
8498 text_copy = NULL((void*)0);
8499 if (text != NULL((void*)0)) {
8500 /* Might be a partial utf8 character at the end if we didn't read whole file */
8501 validated = g_utf8_validate (text, length, &utf8_end);
8502 if (!validated &&
8503 !(length >= max_bytes &&
8504 text + length - utf8_end < 6)) {
8505 text_copy = try_to_make_utf8 (text, &length);
8506 text = text_copy;
8507 } else if (!validated) {
8508 length = utf8_end - text;
8509 }
8510 }
8511
8512 if (text == NULL((void*)0) || length == 0) {
8513 return NULL((void*)0);
8514 }
8515
8516 buffer = g_string_new ("");
8517 end = text + length; in = text;
8518
8519 for (line = 0; line < max_lines; line++) {
8520 /* Extract one line. */
8521 for (i = 0; i < max_cols; ) {
8522 if (*in == '\n') {
8523 break;
8524 }
8525
8526 c = g_utf8_get_char (in);
8527
8528 if (g_unichar_isprint (c)) {
8529 g_string_append_unichar (buffer, c);
8530 i++;
8531 }
8532
8533 in = g_utf8_next_char (in)(char *)((in) + g_utf8_skip[*(const guchar *)(in)]);
8534 if (in == end) {
8535 goto done;
8536 }
8537 }
8538
8539 /* Skip the rest of the line. */
8540 while (*in != '\n') {
8541 if (++in == end) {
8542 goto done;
8543 }
8544 }
8545 if (++in == end) {
8546 goto done;
8547 }
8548
8549 /* Put a new-line separator in. */
8550 g_string_append_c(buffer, '\n')g_string_append_c_inline (buffer, '\n');
8551 }
8552 done:
8553 g_free (text_copy);
8554
8555 return g_string_free(buffer, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((buffer
), ((0))) : g_string_free_and_steal (buffer)) : (g_string_free
) ((buffer), ((0))))
;
8556}
8557
8558static void
8559thumbnail_limit_changed_callback (gpointer user_data)
8560{
8561 g_settings_get (caja_preferences,
8562 CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT"thumbnail-limit",
8563 "t", &cached_thumbnail_limit);
8564
8565 /* Tell the world that icons might have changed. We could invent a narrower-scope
8566 * signal to mean only "thumbnails might have changed" if this ends up being slow
8567 * for some reason.
8568 */
8569 emit_change_signals_for_all_files_in_all_directories ();
8570}
8571
8572static void
8573thumbnail_size_changed_callback (gpointer user_data)
8574{
8575 cached_thumbnail_size = g_settings_get_int (caja_icon_view_preferences, CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE"thumbnail-size");
8576
8577 /* Tell the world that icons might have changed. We could invent a narrower-scope
8578 * signal to mean only "thumbnails might have changed" if this ends up being slow
8579 * for some reason.
8580 */
8581 emit_change_signals_for_all_files_in_all_directories ();
8582}
8583
8584static void
8585show_thumbnails_changed_callback (gpointer user_data)
8586{
8587 show_image_thumbs = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS"show-image-thumbnails");
8588
8589 /* Tell the world that icons might have changed. We could invent a narrower-scope
8590 * signal to mean only "thumbnails might have changed" if this ends up being slow
8591 * for some reason.
8592 */
8593 emit_change_signals_for_all_files_in_all_directories ();
8594}
8595
8596static void
8597mime_type_data_changed_callback (GObject *signaller, gpointer user_data)
8598{
8599 /* Tell the world that icons might have changed. We could invent a narrower-scope
8600 * signal to mean only "thumbnails might have changed" if this ends up being slow
8601 * for some reason.
8602 */
8603 emit_change_signals_for_all_files_in_all_directories ();
8604}
8605
8606static void
8607icon_theme_changed_callback (GtkIconTheme *icon_theme,
8608 gpointer user_data)
8609{
8610 /* Clear all pixmap caches as the icon => pixmap lookup changed */
8611 caja_icon_info_clear_caches ();
8612
8613 /* Tell the world that icons might have changed. We could invent a narrower-scope
8614 * signal to mean only "thumbnails might have changed" if this ends up being slow
8615 * for some reason.
8616 */
8617 emit_change_signals_for_all_files_in_all_directories ();
8618}
8619
8620static void
8621caja_file_class_init (CajaFileClass *class)
8622{
8623 GtkIconTheme *icon_theme;
8624
8625 caja_file_info_getter = caja_file_get_internal;
8626
8627 attribute_name_q = g_quark_from_static_string ("name");
8628 attribute_size_q = g_quark_from_static_string ("size");
8629 attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
8630 attribute_type_q = g_quark_from_static_string ("type");
8631 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
8632 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
8633 attribute_creation_date_q = g_quark_from_static_string ("creation_date");
8634 attribute_date_created_q = g_quark_from_static_string ("date_created");
8635 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
8636 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
8637 attribute_emblems_q = g_quark_from_static_string ("emblems");
8638 attribute_extension_q = g_quark_from_static_string ("extension");
8639 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
8640 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
8641 attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
8642 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
8643 attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
8644 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
8645 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
8646 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
8647 attribute_date_changed_q = g_quark_from_static_string ("date_changed");
8648 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
8649 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
8650 attribute_date_permissions_q = g_quark_from_static_string ("date_permissions");
8651 attribute_permissions_q = g_quark_from_static_string ("permissions");
8652 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
8653 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
8654 attribute_owner_q = g_quark_from_static_string ("owner");
8655 attribute_group_q = g_quark_from_static_string ("group");
8656 attribute_uri_q = g_quark_from_static_string ("uri");
8657 attribute_where_q = g_quark_from_static_string ("where");
8658 attribute_link_target_q = g_quark_from_static_string ("link_target");
8659 attribute_volume_q = g_quark_from_static_string ("volume");
8660 attribute_free_space_q = g_quark_from_static_string ("free_space");
8661
8662 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = finalize;
8663 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->constructor = caja_file_constructor;
8664
8665 signals[CHANGED] =
8666 g_signal_new ("changed",
8667 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8668 G_SIGNAL_RUN_LAST,
8669 G_STRUCT_OFFSET (CajaFileClass, changed)((glong) __builtin_offsetof(CajaFileClass, changed)),
8670 NULL((void*)0), NULL((void*)0),
8671 g_cclosure_marshal_VOID__VOID,
8672 G_TYPE_NONE((GType) ((1) << (2))), 0);
8673
8674 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
8675 g_signal_new ("updated_deep_count_in_progress",
8676 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8677 G_SIGNAL_RUN_LAST,
8678 G_STRUCT_OFFSET (CajaFileClass, updated_deep_count_in_progress)((glong) __builtin_offsetof(CajaFileClass, updated_deep_count_in_progress
))
,
8679 NULL((void*)0), NULL((void*)0),
8680 g_cclosure_marshal_VOID__VOID,
8681 G_TYPE_NONE((GType) ((1) << (2))), 0);
8682
8683 eel_g_settings_add_auto_enum (caja_preferences,
8684 CAJA_PREFERENCES_DATE_FORMAT"date-format",
8685 &date_format_pref);
8686
8687 thumbnail_limit_changed_callback (NULL((void*)0));
8688 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8689 "changed::" CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8690 G_CALLBACK (thumbnail_limit_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8691 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8692 thumbnail_size_changed_callback (NULL((void*)0));
8693 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8694 "changed::" CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8695 G_CALLBACK (thumbnail_size_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8696 NULL)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8697 show_thumbnails_changed_callback (NULL((void*)0));
8698 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8699 "changed::" CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8700 G_CALLBACK (show_thumbnails_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8701 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8702
8703 icon_theme = gtk_icon_theme_get_default ();
8704 g_signal_connect_object (icon_theme,
8705 "changed",
8706 G_CALLBACK (icon_theme_changed_callback)((GCallback) (icon_theme_changed_callback)),
8707 NULL((void*)0), 0);
8708
8709 g_signal_connect (caja_signaller_get_current (),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8710 "mime_data_changed",g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8711 G_CALLBACK (mime_type_data_changed_callback),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8712 NULL)g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
8713}
8714
8715static void
8716caja_file_add_emblem (CajaFile *file,
8717 const char *emblem_name)
8718{
8719 if (file->details->pending_info_providers) {
8720 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
8721 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8722 } else {
8723 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
8724 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8725 }
8726
8727 caja_file_changed (file);
8728}
8729
8730static void
8731caja_file_add_string_attribute (CajaFile *file,
8732 const char *attribute_name,
8733 const char *value)
8734{
8735 if (file->details->pending_info_providers) {
8736 /* Lazily create hashtable */
8737 if (!file->details->pending_extension_attributes) {
8738 file->details->pending_extension_attributes =
8739 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8740 NULL((void*)0),
8741 (GDestroyNotify)g_free);
8742 }
8743 g_hash_table_insert (file->details->pending_extension_attributes,
8744 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8745 g_strdup (value)g_strdup_inline (value));
8746 } else {
8747 if (!file->details->extension_attributes) {
8748 file->details->extension_attributes =
8749 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8750 NULL((void*)0),
8751 (GDestroyNotify)g_free);
8752 }
8753 g_hash_table_insert (file->details->extension_attributes,
8754 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8755 g_strdup (value)g_strdup_inline (value));
8756 }
8757
8758 caja_file_changed (file);
8759}
8760
8761static void
8762caja_file_invalidate_extension_info (CajaFile *file)
8763{
8764 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_EXTENSION_INFO);
8765}
8766
8767void
8768caja_file_info_providers_done (CajaFile *file)
8769{
8770 g_list_free_full (file->details->extension_emblems, g_free);
8771 file->details->extension_emblems = file->details->pending_extension_emblems;
8772 file->details->pending_extension_emblems = NULL((void*)0);
8773
8774 if (file->details->extension_attributes) {
8775 g_hash_table_destroy (file->details->extension_attributes);
8776 }
8777
8778 file->details->extension_attributes = file->details->pending_extension_attributes;
8779 file->details->pending_extension_attributes = NULL((void*)0);
8780
8781 caja_file_changed (file);
8782}
8783
8784static void
8785caja_file_info_iface_init (CajaFileInfoIface *iface)
8786{
8787 iface->is_gone = caja_file_is_gone;
8788 iface->get_name = caja_file_get_name;
8789 iface->get_file_type = caja_file_get_file_type;
8790 iface->get_location = caja_file_get_location;
8791 iface->get_uri = caja_file_get_uri;
8792 iface->get_parent_location = caja_file_get_parent_location;
8793 iface->get_parent_uri = caja_file_get_parent_uri;
8794 iface->get_parent_info = caja_file_get_parent;
8795 iface->get_mount = caja_file_get_mount;
8796 iface->get_uri_scheme = caja_file_get_uri_scheme;
8797 iface->get_activation_uri = caja_file_get_activation_uri;
8798 iface->get_mime_type = caja_file_get_mime_type;
8799 iface->is_mime_type = caja_file_is_mime_type;
8800 iface->is_directory = caja_file_is_directory;
8801 iface->can_write = caja_file_can_write;
8802 iface->add_emblem = caja_file_add_emblem;
8803 iface->get_string_attribute = caja_file_get_string_attribute;
8804 iface->add_string_attribute = caja_file_add_string_attribute;
8805 iface->invalidate_extension_info = caja_file_invalidate_extension_info;
8806}
8807
8808#if !defined (CAJA_OMIT_SELF_CHECK)
8809
8810void
8811caja_self_check_file (void)
8812{
8813 CajaFile *file_1;
8814 CajaFile *file_2;
8815 GList *list;
8816
8817 /* refcount checks */
8818
8819 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8819); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8820
8821 file_1 = caja_file_get_by_uri ("file:///home/");
8822
8823 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8823); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8824 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1->details->directory)))))->ref_count"
, "caja-file.c", 8824); eel_check_integer_result (((((GObject
*) (void *) ((file_1->details->directory)))))->ref_count
, 1); } while (0)
;
8825 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 1)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8825); eel_check_integer_result (caja_directory_number_outstanding
(), 1); } while (0)
;
8826
8827 caja_file_unref (file_1);
8828
8829 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8829); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8830
8831 file_1 = caja_file_get_by_uri ("file:///etc");
8832 file_2 = caja_file_get_by_uri ("file:///usr");
8833
8834 list = NULL((void*)0);
8835 list = g_list_prepend (list, file_1);
8836 list = g_list_prepend (list, file_2);
8837
8838 caja_file_list_ref (list);
8839
8840 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8840); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 2); } while (0)
;
8841 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8841); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 2); } while (0)
;
8842
8843 caja_file_list_unref (list);
8844
8845 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8845); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8846 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8846); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8847
8848 caja_file_list_free (list);
8849
8850 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8850); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8851
8852
8853 /* name checks */
8854 file_1 = caja_file_get_by_uri ("file:///home/");
8855
8856 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8856); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8857
8858 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home/") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home/\") == file_1"
, "caja-file.c", 8858); eel_check_boolean_result (caja_file_get_by_uri
("file:///home/") == file_1, (!(0))); } while (0)
;
8859 caja_file_unref (file_1);
8860
8861 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home\") == file_1"
, "caja-file.c", 8861); eel_check_boolean_result (caja_file_get_by_uri
("file:///home") == file_1, (!(0))); } while (0)
;
8862 caja_file_unref (file_1);
8863
8864 caja_file_unref (file_1);
8865
8866 file_1 = caja_file_get_by_uri ("file:///home");
8867 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8867); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8868 caja_file_unref (file_1);
8869
8870#if 0
8871 /* ALEX: I removed this, because it was breaking distchecks.
8872 * It used to work, but when canonical uris changed from
8873 * foo: to foo:/// it broke. I don't expect it to matter
8874 * in real life */
8875 file_1 = caja_file_get_by_uri (":");
8876 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), ":")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8876); eel_check_string_result (caja_file_get_name (file_1)
, ":"); } while (0)
;
8877 caja_file_unref (file_1);
8878#endif
8879
8880 file_1 = caja_file_get_by_uri ("eazel:");
8881 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "eazel")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8881); eel_check_string_result (caja_file_get_name (file_1)
, "eazel"); } while (0)
;
8882 caja_file_unref (file_1);
8883
8884 /* sorting */
8885 file_1 = caja_file_get_by_uri ("file:///etc");
8886 file_2 = caja_file_get_by_uri ("file:///usr");
8887
8888 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8888); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8889 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8889); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8890
8891 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) < 0"
, "caja-file.c", 8891); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) <
0, (!(0))); } while (0)
;
8892 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) > 0"
, "caja-file.c", 8892); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) > 0, (!(0))); } while (0)
;
8893 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) == 0"
, "caja-file.c", 8893); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) ==
0, (!(0))); } while (0)
;
8894 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)) == 0"
, "caja-file.c", 8894); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)
) == 0, (!(0))); } while (0)
;
8895 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) == 0"
, "caja-file.c", 8895); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) == 0, (!(0))); } while (0)
;
8896 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(0))) == 0"
, "caja-file.c", 8896); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(
0))) == 0, (!(0))); } while (0)
;
8897
8898 caja_file_unref (file_1);
8899 caja_file_unref (file_2);
8900}
8901
8902#endif /* !CAJA_OMIT_SELF_CHECK */
diff --git a/2024-07-29-023715-6438-1/report-5dfaea.html b/2024-07-29-023715-6438-1/report-5dfaea.html new file mode 100644 index 000000000..64818b1ce --- /dev/null +++ b/2024-07-29-023715-6438-1/report-5dfaea.html @@ -0,0 +1,1264 @@ + + + +caja-notebook.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-notebook.c
Warning:line 395, column 5
Value stored to 'position' 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 caja-notebook.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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-notebook.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * Copyright © 2002 Christophe Fergeau
4 * Copyright © 2003, 2004 Marco Pesenti Gritti
5 * Copyright © 2003, 2004, 2005 Christian Persch
6 * (ephy-notebook.c)
7 *
8 * Copyright © 2008 Free Software Foundation, Inc.
9 * (caja-notebook.c)
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 *
25 */
26
27#include <config.h>
28
29#include <glib/gi18n.h>
30#include <gio/gio.h>
31#include <gtk/gtk.h>
32
33#include <libcaja-private/caja-dnd.h>
34
35#include "caja-notebook.h"
36#include "caja-navigation-window.h"
37#include "caja-window-manage-views.h"
38#include "caja-window-private.h"
39#include "caja-window-slot.h"
40#include "caja-navigation-window-pane.h"
41
42#define AFTER_ALL_TABS-1 -1
43
44static void caja_notebook_constructed (GObject *object);
45
46static int caja_notebook_insert_page (GtkNotebook *notebook,
47 GtkWidget *child,
48 GtkWidget *tab_label,
49 GtkWidget *menu_label,
50 int position);
51
52static void caja_notebook_remove (GtkContainer *container,
53 GtkWidget *tab_widget);
54
55static gboolean caja_notebook_scroll_event (GtkWidget *widget,
56 GdkEventScroll *event);
57
58enum
59{
60 TAB_CLOSE_REQUEST,
61 LAST_SIGNAL
62};
63
64static guint signals[LAST_SIGNAL] = { 0 };
65
66G_DEFINE_TYPE (CajaNotebook, caja_notebook, GTK_TYPE_NOTEBOOK)static void caja_notebook_init (CajaNotebook *self); static void
caja_notebook_class_init (CajaNotebookClass *klass); static GType
caja_notebook_get_type_once (void); static gpointer caja_notebook_parent_class
= ((void*)0); static gint CajaNotebook_private_offset; static
void caja_notebook_class_intern_init (gpointer klass) { caja_notebook_parent_class
= g_type_class_peek_parent (klass); if (CajaNotebook_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaNotebook_private_offset
); caja_notebook_class_init ((CajaNotebookClass*) klass); } __attribute__
((__unused__)) static inline gpointer caja_notebook_get_instance_private
(CajaNotebook *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (CajaNotebook_private_offset)))); } GType caja_notebook_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_notebook_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_notebook_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_notebook_get_type ()), g_intern_static_string ("CajaNotebook"
), sizeof (CajaNotebookClass), (GClassInitFunc)(void (*)(void
)) caja_notebook_class_intern_init, sizeof (CajaNotebook), (GInstanceInitFunc
)(void (*)(void)) caja_notebook_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
;
67
68static void
69caja_notebook_class_init (CajaNotebookClass *klass)
70{
71 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
72 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass)((((GtkContainerClass*) (void *) ((klass)))));
73 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass)((((GtkWidgetClass*) (void *) ((klass)))));
74 GtkNotebookClass *notebook_class = GTK_NOTEBOOK_CLASS (klass)((((GtkNotebookClass*) (void *) ((klass)))));
75
76 object_class->constructed = caja_notebook_constructed;
77
78 container_class->remove = caja_notebook_remove;
79
80 widget_class->scroll_event = caja_notebook_scroll_event;
81
82 notebook_class->insert_page = caja_notebook_insert_page;
83
84 signals[TAB_CLOSE_REQUEST] =
85 g_signal_new ("tab-close-request",
86 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
87 G_SIGNAL_RUN_LAST,
88 G_STRUCT_OFFSET (CajaNotebookClass, tab_close_request)((glong) __builtin_offsetof(CajaNotebookClass, tab_close_request
))
,
89 NULL((void*)0), NULL((void*)0),
90 g_cclosure_marshal_VOID__OBJECT,
91 G_TYPE_NONE((GType) ((1) << (2))),
92 1,
93 CAJA_TYPE_WINDOW_SLOT(caja_window_slot_get_type()));
94}
95
96static gint
97find_tab_num_at_pos (CajaNotebook *notebook, gint abs_x, gint abs_y)
98{
99 GtkPositionType tab_pos;
100 int page_num = 0;
101 GtkNotebook *nb = GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook)))));
102 GtkWidget *page;
103 GtkAllocation allocation;
104
105 tab_pos = gtk_notebook_get_tab_pos (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))));
106
107 while ((page = gtk_notebook_get_nth_page (nb, page_num)))
108 {
109 GtkWidget *tab;
110 gint max_x, max_y;
111 gint x_root, y_root;
112
113 tab = gtk_notebook_get_tab_label (nb, page);
114 g_return_val_if_fail (tab != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if (tab != ((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__)), "tab != NULL"); return
(-1); } } while (0)
;
115
116 if (!gtk_widget_get_mapped (GTK_WIDGET (tab)((((GtkWidget*) (void *) ((tab)))))))
117 {
118 page_num++;
119 continue;
120 }
121
122 gdk_window_get_origin (gtk_widget_get_window (tab),
123 &x_root, &y_root);
124 gtk_widget_get_allocation (tab, &allocation);
125
126 max_x = x_root + allocation.x + allocation.width;
127 max_y = y_root + allocation.y + allocation.height;
128
129 if (((tab_pos == GTK_POS_TOP)
130 || (tab_pos == GTK_POS_BOTTOM))
131 &&(abs_x<=max_x))
132 {
133 return page_num;
134 }
135 else if (((tab_pos == GTK_POS_LEFT)
136 || (tab_pos == GTK_POS_RIGHT))
137 && (abs_y<=max_y))
138 {
139 return page_num;
140 }
141
142 page_num++;
143 }
144 return AFTER_ALL_TABS-1;
145}
146
147static gboolean
148button_press_cb (CajaNotebook *notebook,
149 GdkEventButton *event,
150 gpointer data)
151{
152 int tab_clicked;
153
154 tab_clicked = find_tab_num_at_pos (notebook, event->x_root, event->y_root);
155
156 if (event->type == GDK_BUTTON_PRESS &&
157 (event->button == 3 || event->button == 2) &&
158 (event->state & gtk_accelerator_get_default_mod_mask ()) == 0)
159 {
160 if (tab_clicked == -1)
161 {
162 /* consume event, so that we don't pop up the context menu when
163 * the mouse if not over a tab label
164 */
165 return TRUE(!(0));
166 }
167
168 /* switch to the page the mouse is over, but don't consume the event */
169 gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))), tab_clicked);
170 }
171
172 return FALSE(0);
173}
174
175static void
176caja_notebook_init (CajaNotebook *notebook)
177{
178 GtkStyleContext *context;
179
180 context = gtk_widget_get_style_context (GTK_WIDGET (notebook)((((GtkWidget*) (void *) ((notebook))))));
181 gtk_style_context_add_class (context, "caja-notebook");
182
183 gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))), TRUE(!(0)));
184 gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))), FALSE(0));
185 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))), FALSE(0));
186
187 g_signal_connect (notebook, "button-press-event",g_signal_connect_data ((notebook), ("button-press-event"), ((
GCallback)button_press_cb), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
188 (GCallback)button_press_cb, NULL)g_signal_connect_data ((notebook), ("button-press-event"), ((
GCallback)button_press_cb), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
189}
190
191static void
192caja_notebook_constructed (GObject *object)
193{
194 GtkWidget *widget = GTK_WIDGET (object)((((GtkWidget*) (void *) ((object)))));
195
196 G_OBJECT_CLASS (caja_notebook_parent_class)((((GObjectClass*) (void *) ((caja_notebook_parent_class)))))->constructed (object);
197
198 /* Necessary for scroll events */
199 gtk_widget_add_events (widget, GDK_SCROLL_MASK);
200}
201
202
203void
204caja_notebook_sync_loading (CajaNotebook *notebook,
205 CajaWindowSlot *slot)
206{
207 GtkWidget *tab_label, *spinner, *icon;
208 gboolean active;
209
210 g_return_if_fail (CAJA_IS_NOTEBOOK (notebook))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_28
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((caja_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; }))))) _g_boolean_var_28
= 1; else _g_boolean_var_28 = 0; _g_boolean_var_28; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_NOTEBOOK (notebook)"); return; } } while
(0)
;
211 g_return_if_fail (CAJA_IS_WINDOW_SLOT (slot))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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_29
= 1; else _g_boolean_var_29 = 0; _g_boolean_var_29; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_WINDOW_SLOT (slot)"); return; } } while
(0)
;
212
213 tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))), slot->content_box);
214 g_return_if_fail (GTK_IS_WIDGET (tab_label))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tab_label)); GType __t = ((gtk_widget_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_30
= 1; else _g_boolean_var_30 = 0; _g_boolean_var_30; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "GTK_IS_WIDGET (tab_label)"); return; } } while
(0)
;
215
216 spinner = GTK_WIDGET (g_object_get_data (G_OBJECT (tab_label), "spinner"))((((GtkWidget*) (void *) ((g_object_get_data (((((GObject*) (
void *) ((tab_label))))), "spinner"))))))
;
217 icon = GTK_WIDGET (g_object_get_data (G_OBJECT (tab_label), "icon"))((((GtkWidget*) (void *) ((g_object_get_data (((((GObject*) (
void *) ((tab_label))))), "icon"))))))
;
218 g_return_if_fail (spinner != NULL && icon != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if (spinner != ((void*)0) && icon != ((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__)), "spinner != NULL && icon != NULL"); return
; } } while (0)
;
219
220 active = FALSE(0);
221 g_object_get (spinner, "active", &active, NULL((void*)0));
222 if (active == slot->allow_stop)
223 {
224 return;
225 }
226
227 if (slot->allow_stop)
228 {
229 gtk_widget_hide (icon);
230 gtk_widget_show (spinner);
231 gtk_spinner_start (GTK_SPINNER (spinner)((((GtkSpinner*) (void *) ((spinner))))));
232 }
233 else
234 {
235 gtk_spinner_stop (GTK_SPINNER (spinner)((((GtkSpinner*) (void *) ((spinner))))));
236 gtk_widget_hide (spinner);
237 gtk_widget_show (icon);
238 }
239}
240
241void
242caja_notebook_sync_tab_label (CajaNotebook *notebook,
243 CajaWindowSlot *slot)
244{
245 GtkWidget *hbox, *label;
246
247 g_return_if_fail (CAJA_IS_NOTEBOOK (notebook))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((caja_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; }))))) _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__)), "CAJA_IS_NOTEBOOK (notebook)"); return; } } while
(0)
;
248 g_return_if_fail (CAJA_IS_WINDOW_SLOT (slot))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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_33
= 1; else _g_boolean_var_33 = 0; _g_boolean_var_33; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_WINDOW_SLOT (slot)"); return; } } while
(0)
;
249 g_return_if_fail (GTK_IS_WIDGET (slot->content_box))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot->content_box)); GType __t = ((gtk_widget_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_34 = 1; else _g_boolean_var_34 = 0
; _g_boolean_var_34; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "GTK_IS_WIDGET (slot->content_box)"
); return; } } while (0)
;
250
251 hbox = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))), slot->content_box);
252 g_return_if_fail (GTK_IS_WIDGET (hbox))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((hbox)); GType __t = ((gtk_widget_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_35
= 1; else _g_boolean_var_35 = 0; _g_boolean_var_35; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "GTK_IS_WIDGET (hbox)"); return; } } while (0
)
;
253
254 label = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "label"))((((GtkWidget*) (void *) ((g_object_get_data (((((GObject*) (
void *) ((hbox))))), "label"))))))
;
255 g_return_if_fail (GTK_IS_WIDGET (label))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((gtk_widget_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_36
= 1; else _g_boolean_var_36 = 0; _g_boolean_var_36; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "GTK_IS_WIDGET (label)"); return; } } while (
0)
;
256
257 gtk_label_set_text (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), slot->title);
258
259 if (slot->location != NULL((void*)0))
260 {
261 char *location_name;
262
263 /* Set the tooltip on the label's parent (the tab label hbox),
264 * so it covers all of the tab label.
265 */
266 location_name = g_file_get_parse_name (slot->location);
267 gtk_widget_set_tooltip_text (gtk_widget_get_parent (label), location_name);
268 g_free (location_name);
269 }
270 else
271 {
272 gtk_widget_set_tooltip_text (gtk_widget_get_parent (label), NULL((void*)0));
273 }
274}
275
276static void
277close_button_clicked_cb (GtkWidget *widget,
278 CajaWindowSlot *slot)
279{
280 GtkWidget *notebook;
281
282 notebook = gtk_widget_get_ancestor (slot->content_box, CAJA_TYPE_NOTEBOOK(caja_notebook_get_type ()));
283 if (notebook != NULL((void*)0))
284 {
285 g_signal_emit (notebook, signals[TAB_CLOSE_REQUEST], 0, slot);
286 }
287}
288
289static GtkWidget *
290build_tab_label (CajaNotebook *nb, CajaWindowSlot *slot)
291{
292 CajaDragSlotProxyInfo *drag_info;
293 GtkWidget *hbox, *label, *close_button, *image, *spinner, *icon;
294
295 /* set hbox spacing and label padding (see below) so that there's an
296 * equal amount of space around the label */
297 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
298 gtk_widget_show (hbox);
299
300 /* setup load feedback */
301 spinner = gtk_spinner_new ();
302 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), spinner, FALSE(0), FALSE(0), 0);
303
304 /* setup site icon, empty by default */
305 icon = gtk_image_new ();
306 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), icon, FALSE(0), FALSE(0), 0);
307 /* don't show the icon */
308
309 /* setup label */
310 label = gtk_label_new (NULL((void*)0));
311 gtk_label_set_ellipsize (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), PANGO_ELLIPSIZE_END);
312 gtk_label_set_single_line_mode (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), TRUE(!(0)));
313 gtk_label_set_xalign (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), 0.0);
314 gtk_label_set_yalign (GTK_LABEL (label)((((GtkLabel*) (void *) ((label))))), 0.5);
315
316 gtk_widget_set_margin_start (label, 0);
317 gtk_widget_set_margin_end (label, 0);
318 gtk_widget_set_margin_top (label, 0);
319 gtk_widget_set_margin_bottom (label, 0);
320
321 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), label, TRUE(!(0)), TRUE(!(0)), 0);
322 gtk_widget_show (label);
323
324 /* setup close button */
325 close_button = gtk_button_new ();
326 gtk_button_set_relief (GTK_BUTTON (close_button)((((GtkButton*) (void *) ((close_button))))),
327 GTK_RELIEF_NONE);
328 /* don't allow focus on the close button */
329 gtk_widget_set_focus_on_click (close_button, FALSE(0));
330
331 gtk_widget_set_name (close_button, "caja-tab-close-button");
332
333 image = gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_MENU);
334 gtk_widget_set_tooltip_text (close_button, _("Close tab")dcgettext (((void*)0), "Close tab", 5));
335 g_signal_connect_object (close_button, "clicked",
336 G_CALLBACK (close_button_clicked_cb)((GCallback) (close_button_clicked_cb)), slot, 0);
337
338 gtk_container_add (GTK_CONTAINER (close_button)((((GtkContainer*) (void *) ((close_button))))), image);
339 gtk_widget_show (image);
340
341 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), close_button, FALSE(0), FALSE(0), 0);
342 gtk_widget_show (close_button);
343
344 drag_info = g_new0 (CajaDragSlotProxyInfo, 1)(CajaDragSlotProxyInfo *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (CajaDragSlotProxyInfo); 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; }))
;
345 drag_info->target_slot = slot;
346 g_object_set_data_full (G_OBJECT (hbox)((((GObject*) (void *) ((hbox))))), "proxy-drag-info",
347 drag_info, (GDestroyNotify) g_free);
348
349 caja_drag_slot_proxy_init (hbox, drag_info);
350
351 g_object_set_data (G_OBJECT (hbox)((((GObject*) (void *) ((hbox))))), "label", label);
352 g_object_set_data (G_OBJECT (hbox)((((GObject*) (void *) ((hbox))))), "spinner", spinner);
353 g_object_set_data (G_OBJECT (hbox)((((GObject*) (void *) ((hbox))))), "icon", icon);
354 g_object_set_data (G_OBJECT (hbox)((((GObject*) (void *) ((hbox))))), "close-button", close_button);
355
356 return hbox;
357}
358
359static int
360caja_notebook_insert_page (GtkNotebook *gnotebook,
361 GtkWidget *tab_widget,
362 GtkWidget *tab_label,
363 GtkWidget *menu_label,
364 int position)
365{
366 g_assert (GTK_IS_WIDGET (tab_widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tab_widget)); GType __t = ((gtk_widget_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_37
= 1; else _g_boolean_var_37 = 0; _g_boolean_var_37; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-notebook.c"
, 366, ((const char*) (__func__)), "GTK_IS_WIDGET (tab_widget)"
); } while (0)
;
367
368 position = GTK_NOTEBOOK_CLASS (caja_notebook_parent_class)((((GtkNotebookClass*) (void *) ((caja_notebook_parent_class)
))))
->insert_page (gnotebook,
369 tab_widget,
370 tab_label,
371 menu_label,
372 position);
373
374 gtk_notebook_set_show_tabs (gnotebook,
375 gtk_notebook_get_n_pages (gnotebook) > 1);
376 gtk_notebook_set_tab_reorderable (gnotebook, tab_widget, TRUE(!(0)));
377
378 return position;
379}
380
381int
382caja_notebook_add_tab (CajaNotebook *notebook,
383 CajaWindowSlot *slot,
384 int position,
385 gboolean jump_to)
386{
387 GtkNotebook *gnotebook = GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook)))));
388 GtkWidget *tab_label;
389
390 g_return_val_if_fail (CAJA_IS_NOTEBOOK (notebook), -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((caja_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; }))))) _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__)), "CAJA_IS_NOTEBOOK (notebook)"); return (-1); }
} while (0)
;
391 g_return_val_if_fail (CAJA_IS_WINDOW_SLOT (slot), -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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_39
= 1; else _g_boolean_var_39 = 0; _g_boolean_var_39; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_WINDOW_SLOT (slot)"); return (-1); }
} while (0)
;
392
393 tab_label = build_tab_label (notebook, slot);
394
395 position = gtk_notebook_insert_page (GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook))))),
Value stored to 'position' is never read
396 slot->content_box,
397 tab_label,
398 position);
399
400 gtk_container_child_set (GTK_CONTAINER (notebook)((((GtkContainer*) (void *) ((notebook))))),
401 slot->content_box,
402 "tab-expand", TRUE(!(0)),
403 NULL((void*)0));
404
405 caja_notebook_sync_tab_label (notebook, slot);
406 caja_notebook_sync_loading (notebook, slot);
407
408
409 /* FIXME gtk bug! */
410 /* FIXME: this should be fixed in gtk 2.12; check & remove this! */
411 /* The signal handler may have reordered the tabs */
412 position = gtk_notebook_page_num (gnotebook, slot->content_box);
413
414 if (jump_to)
415 {
416 gtk_notebook_set_current_page (gnotebook, position);
417
418 }
419
420 return position;
421}
422
423static void
424caja_notebook_remove (GtkContainer *container,
425 GtkWidget *tab_widget)
426{
427 GtkNotebook *gnotebook = GTK_NOTEBOOK (container)((((GtkNotebook*) (void *) ((container)))));
428 GTK_CONTAINER_CLASS (caja_notebook_parent_class)((((GtkContainerClass*) (void *) ((caja_notebook_parent_class
)))))
->remove (container, tab_widget);
429
430 gtk_notebook_set_show_tabs (gnotebook,
431 gtk_notebook_get_n_pages (gnotebook) > 1);
432
433}
434
435void
436caja_notebook_reorder_current_child_relative (CajaNotebook *notebook,
437 int offset)
438{
439 GtkNotebook *gnotebook;
440 GtkWidget *child;
441 int page;
442
443 g_return_if_fail (CAJA_IS_NOTEBOOK (notebook))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_40
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((caja_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; }))))) _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__)), "CAJA_IS_NOTEBOOK (notebook)"); return; } } while
(0)
;
444
445 if (!caja_notebook_can_reorder_current_child_relative (notebook, offset))
446 {
447 return;
448 }
449
450 gnotebook = GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook)))));
451
452 page = gtk_notebook_get_current_page (gnotebook);
453 child = gtk_notebook_get_nth_page (gnotebook, page);
454 gtk_notebook_reorder_child (gnotebook, child, page + offset);
455}
456
457void
458caja_notebook_set_current_page_relative (CajaNotebook *notebook,
459 int offset)
460{
461 GtkNotebook *gnotebook;
462 int page;
463
464 g_return_if_fail (CAJA_IS_NOTEBOOK (notebook))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_41
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((caja_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; }))))) _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__)), "CAJA_IS_NOTEBOOK (notebook)"); return; } } while
(0)
;
465
466 if (!caja_notebook_can_set_current_page_relative (notebook, offset))
467 {
468 return;
469 }
470
471 gnotebook = GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook)))));
472
473 page = gtk_notebook_get_current_page (gnotebook);
474 gtk_notebook_set_current_page (gnotebook, page + offset);
475
476}
477
478static gboolean
479caja_notebook_is_valid_relative_position (CajaNotebook *notebook,
480 int offset)
481{
482 GtkNotebook *gnotebook;
483 int page;
484 int n_pages;
485
486 gnotebook = GTK_NOTEBOOK (notebook)((((GtkNotebook*) (void *) ((notebook)))));
487
488 page = gtk_notebook_get_current_page (gnotebook);
489 n_pages = gtk_notebook_get_n_pages (gnotebook) - 1;
490 if (page < 0 ||
491 (offset < 0 && page < -offset) ||
492 (offset > 0 && page > n_pages - offset))
493 {
494 return FALSE(0);
495 }
496
497 return TRUE(!(0));
498}
499
500gboolean
501caja_notebook_can_reorder_current_child_relative (CajaNotebook *notebook,
502 int offset)
503{
504 g_return_val_if_fail (CAJA_IS_NOTEBOOK (notebook), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_42
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((caja_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; }))))) _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__)), "CAJA_IS_NOTEBOOK (notebook)"); return ((0));
} } while (0)
;
505
506 return caja_notebook_is_valid_relative_position (notebook, offset);
507}
508
509gboolean
510caja_notebook_can_set_current_page_relative (CajaNotebook *notebook,
511 int offset)
512{
513 g_return_val_if_fail (CAJA_IS_NOTEBOOK (notebook), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_43
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((caja_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; }))))) _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__)), "CAJA_IS_NOTEBOOK (notebook)"); return ((0));
} } while (0)
;
514
515 return caja_notebook_is_valid_relative_position (notebook, offset);
516}
517
518/* Tab scrolling was removed from GtkNotebook in gtk 3, so reimplement it here */
519static gboolean
520caja_notebook_scroll_event (GtkWidget *widget,
521 GdkEventScroll *event)
522{
523 GtkNotebook *notebook = GTK_NOTEBOOK (widget)((((GtkNotebook*) (void *) ((widget)))));
524 gboolean (* scroll_event) (GtkWidget *, GdkEventScroll *) =
525 GTK_WIDGET_CLASS (caja_notebook_parent_class)((((GtkWidgetClass*) (void *) ((caja_notebook_parent_class)))
))
->scroll_event;
526 GtkWidget *child, *event_widget, *action_widget;
527
528 if ((event->state & gtk_accelerator_get_default_mod_mask ()) != 0)
529 goto chain_up;
530
531 child = gtk_notebook_get_nth_page (notebook, gtk_notebook_get_current_page (notebook));
532 if (child == NULL((void*)0))
533 goto chain_up;
534
535 event_widget = gtk_get_event_widget ((GdkEvent *) event);
536
537 /* Ignore scroll events from the content of the page */
538 if (event_widget == NULL((void*)0) || event_widget == child || gtk_widget_is_ancestor (event_widget, child))
539 goto chain_up;
540
541 /* And also from the action widgets */
542 action_widget = gtk_notebook_get_action_widget (notebook, GTK_PACK_START);
543 if (event_widget == action_widget || (action_widget != NULL((void*)0) && gtk_widget_is_ancestor (event_widget, action_widget)))
544 goto chain_up;
545
546 action_widget = gtk_notebook_get_action_widget (notebook, GTK_PACK_END);
547 if (event_widget == action_widget || (action_widget != NULL((void*)0) && gtk_widget_is_ancestor (event_widget, action_widget)))
548 goto chain_up;
549
550 switch (event->direction) {
551 case GDK_SCROLL_RIGHT:
552 case GDK_SCROLL_DOWN:
553 gtk_notebook_next_page (notebook);
554 return TRUE(!(0));
555 case GDK_SCROLL_LEFT:
556 case GDK_SCROLL_UP:
557 gtk_notebook_prev_page (notebook);
558 return TRUE(!(0));
559 case GDK_SCROLL_SMOOTH:
560 switch (gtk_notebook_get_tab_pos (notebook)) {
561 case GTK_POS_LEFT:
562 case GTK_POS_RIGHT:
563 if (event->delta_y > 0)
564 gtk_notebook_next_page (notebook);
565 else if (event->delta_y < 0)
566 gtk_notebook_prev_page (notebook);
567 break;
568 case GTK_POS_TOP:
569 case GTK_POS_BOTTOM:
570 if (event->delta_x > 0)
571 gtk_notebook_next_page (notebook);
572 else if (event->delta_x < 0)
573 gtk_notebook_prev_page (notebook);
574 break;
575 }
576 return TRUE(!(0));
577 }
578
579chain_up:
580 if (scroll_event)
581 return scroll_event (widget, event);
582
583 return FALSE(0);
584}
diff --git a/2024-07-29-023715-6438-1/report-5f75fc.html b/2024-07-29-023715-6438-1/report-5f75fc.html new file mode 100644 index 000000000..61c97419d --- /dev/null +++ b/2024-07-29-023715-6438-1/report-5f75fc.html @@ -0,0 +1,6536 @@ + + + +fm-properties-window.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/file-manager/fm-properties-window.c
Warning:line 4490, column 2
Value stored to 'group_label' 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 fm-properties-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 -fdebug-compilation-dir=/rootdir/src/file-manager -fcoverage-compilation-dir=/rootdir/src/file-manager -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I ../../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D CAJA_DATADIR="/usr/local/share/caja" -D DATADIR="/usr/local/share" -D ICONDIR="/usr/local/share/icons" -D PIXMAPDIR="/usr/local/share/pixmaps" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c fm-properties-window.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* fm-properties-window.c - window that lets user modify file properties
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <string.h>
27#include <cairo.h>
28
29#include <gtk/gtk.h>
30#include <gdk/gdkkeysyms.h>
31#include <glib/gi18n.h>
32#include <sys/stat.h>
33
34#include <eel/eel-accessibility.h>
35#include <eel/eel-gdk-pixbuf-extensions.h>
36#include <eel/eel-glib-extensions.h>
37#include <eel/eel-mate-extensions.h>
38#include <eel/eel-gtk-extensions.h>
39#include <eel/eel-labeled-image.h>
40#include <eel/eel-stock-dialogs.h>
41#include <eel/eel-vfs-extensions.h>
42#include <eel/eel-wrap-table.h>
43
44#include <libcaja-extension/caja-property-page-provider.h>
45
46#include <libcaja-private/caja-mime-application-chooser.h>
47#include <libcaja-private/caja-entry.h>
48#include <libcaja-private/caja-extensions.h>
49#include <libcaja-private/caja-file-attributes.h>
50#include <libcaja-private/caja-file-operations.h>
51#include <libcaja-private/caja-desktop-icon-file.h>
52#include <libcaja-private/caja-global-preferences.h>
53#include <libcaja-private/caja-emblem-utils.h>
54#include <libcaja-private/caja-link.h>
55#include <libcaja-private/caja-metadata.h>
56#include <libcaja-private/caja-module.h>
57#include <libcaja-private/caja-mime-actions.h>
58
59#include "fm-properties-window.h"
60#include "fm-ditem-page.h"
61#include "fm-error-reporting.h"
62
63#if HAVE_SYS_VFS_H1
64#include <sys/vfs.h>
65#elif HAVE_SYS_MOUNT_H1
66#if HAVE_SYS_PARAM_H1
67#include <sys/param.h>
68#endif
69#include <sys/mount.h>
70#endif
71
72#define USED_FILL_R0.988235294 0.988235294
73#define USED_FILL_G0.91372549 0.91372549
74#define USED_FILL_B0.309803922 0.309803922
75
76#define FREE_FILL_R0.447058824 0.447058824
77#define FREE_FILL_G0.623529412 0.623529412
78#define FREE_FILL_B0.811764706 0.811764706
79
80#define PREVIEW_IMAGE_WIDTH96 96
81
82#define ROW_PAD6 6
83
84static GHashTable *windows;
85static GHashTable *pending_lists;
86
87struct _FMPropertiesWindowPrivate {
88 GList *original_files;
89 GList *target_files;
90
91 GtkNotebook *notebook;
92
93 GtkGrid *basic_grid;
94
95 GtkWidget *icon_button;
96 GtkWidget *icon_image;
97 GtkWidget *icon_chooser;
98
99 GtkLabel *name_label;
100 GtkWidget *name_field;
101 unsigned int name_row;
102 char *pending_name;
103
104 GtkLabel *directory_contents_title_field;
105 GtkLabel *directory_contents_value_field;
106 guint update_directory_contents_timeout_id;
107 guint update_files_timeout_id;
108
109 GList *emblem_buttons;
110 GHashTable *initial_emblems;
111
112 CajaFile *group_change_file;
113 char *group_change_group;
114 unsigned int group_change_timeout;
115 CajaFile *owner_change_file;
116 char *owner_change_owner;
117 unsigned int owner_change_timeout;
118
119 GList *permission_buttons;
120 GList *permission_combos;
121 GHashTable *initial_permissions;
122 gboolean has_recursive_apply;
123
124 GList *value_fields;
125
126 GList *mime_list;
127
128 gboolean deep_count_finished;
129
130 guint total_count;
131 goffset total_size;
132 goffset total_size_on_disk;
133
134 guint long_operation_underway;
135
136 GList *changed_files;
137
138 guint64 volume_capacity;
139 guint64 volume_free;
140
141 GdkRGBA used_color;
142 GdkRGBA free_color;
143 GdkRGBA used_stroke_color;
144 GdkRGBA free_stroke_color;
145};
146
147typedef enum {
148 PERMISSIONS_CHECKBOXES_READ,
149 PERMISSIONS_CHECKBOXES_WRITE,
150 PERMISSIONS_CHECKBOXES_EXECUTE
151} CheckboxType;
152
153enum {
154 TITLE_COLUMN,
155 VALUE_COLUMN,
156 COLUMN_COUNT
157};
158
159typedef struct {
160 GList *original_files;
161 GList *target_files;
162 GtkWidget *parent_widget;
163 char *pending_key;
164 GHashTable *pending_files;
165} StartupData;
166
167/* drag and drop definitions */
168
169enum {
170 TARGET_URI_LIST,
171 TARGET_MATE_URI_LIST,
172 TARGET_RESET_BACKGROUND
173};
174
175static const GtkTargetEntry target_table[] = {
176 { "text/uri-list", 0, TARGET_URI_LIST },
177 { "x-special/mate-icon-list", 0, TARGET_MATE_URI_LIST },
178 { "x-special/mate-reset-background", 0, TARGET_RESET_BACKGROUND }
179};
180
181#define DIRECTORY_CONTENTS_UPDATE_INTERVAL200 200 /* milliseconds */
182#define FILES_UPDATE_INTERVAL200 200 /* milliseconds */
183#define STANDARD_EMBLEM_HEIGHT52 52
184#define EMBLEM_LABEL_SPACING2 2
185
186/*
187 * A timeout before changes through the user/group combo box will be applied.
188 * When quickly changing owner/groups (i.e. by keyboard or scroll wheel),
189 * this ensures that the GUI doesn't end up unresponsive.
190 *
191 * Both combos react on changes by scheduling a new change and unscheduling
192 * or cancelling old pending changes.
193 */
194#define CHOWN_CHGRP_TIMEOUT300 300 /* milliseconds */
195
196static void directory_contents_value_field_update (FMPropertiesWindow *window);
197static void file_changed_callback (CajaFile *file,
198 gpointer user_data);
199static void permission_button_update (FMPropertiesWindow *window,
200 GtkToggleButton *button);
201static void permission_combo_update (FMPropertiesWindow *window,
202 GtkComboBox *combo);
203static void value_field_update (FMPropertiesWindow *window,
204 GtkLabel *field);
205static void properties_window_update (FMPropertiesWindow *window,
206 GList *files);
207static void is_directory_ready_callback (CajaFile *file,
208 gpointer data);
209static void cancel_group_change_callback (FMPropertiesWindow *window);
210static void cancel_owner_change_callback (FMPropertiesWindow *window);
211static void parent_widget_destroyed_callback (GtkWidget *widget,
212 gpointer callback_data);
213static void select_image_button_callback (GtkWidget *widget,
214 FMPropertiesWindow *properties_window);
215static void set_icon (const char *icon_path,
216 FMPropertiesWindow *properties_window);
217static void remove_pending (StartupData *data,
218 gboolean cancel_call_when_ready,
219 gboolean cancel_timed_wait,
220 gboolean cancel_destroy_handler);
221static void append_extension_pages (FMPropertiesWindow *window);
222
223static gboolean name_field_focus_out (CajaEntry *name_field,
224 GdkEventFocus *event,
225 gpointer callback_data);
226static void name_field_activate (CajaEntry *name_field,
227 gpointer callback_data);
228static GtkLabel *attach_ellipsizing_value_label (GtkGrid *grid,
229 GtkWidget *sibling,
230
231 const char *initial_text);
232
233static GtkWidget* create_pie_widget (FMPropertiesWindow *window);
234
235G_DEFINE_TYPE_WITH_PRIVATE (FMPropertiesWindow, fm_properties_window, GTK_TYPE_DIALOG)static void fm_properties_window_init (FMPropertiesWindow *self
); static void fm_properties_window_class_init (FMPropertiesWindowClass
*klass); static GType fm_properties_window_get_type_once (void
); static gpointer fm_properties_window_parent_class = ((void
*)0); static gint FMPropertiesWindow_private_offset; static void
fm_properties_window_class_intern_init (gpointer klass) { fm_properties_window_parent_class
= g_type_class_peek_parent (klass); if (FMPropertiesWindow_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &FMPropertiesWindow_private_offset
); fm_properties_window_class_init ((FMPropertiesWindowClass*
) klass); } __attribute__ ((__unused__)) static inline gpointer
fm_properties_window_get_instance_private (FMPropertiesWindow
*self) { return (((gpointer) ((guint8*) (self) + (glong) (FMPropertiesWindow_private_offset
)))); } GType fm_properties_window_get_type (void) { static GType
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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= fm_properties_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType fm_properties_window_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_dialog_get_type ()), g_intern_static_string ("FMPropertiesWindow"
), sizeof (FMPropertiesWindowClass), (GClassInitFunc)(void (*
)(void)) fm_properties_window_class_intern_init, sizeof (FMPropertiesWindow
), (GInstanceInitFunc)(void (*)(void)) fm_properties_window_init
, (GTypeFlags) 0); { {{ FMPropertiesWindow_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (FMPropertiesWindowPrivate)); };} }
return g_define_type_id; }
;
236
237static gboolean
238is_multi_file_window (FMPropertiesWindow *window)
239{
240 GList *l;
241 int count;
242
243 count = 0;
244
245 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
246 if (!caja_file_is_gone (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
247 count++;
248 if (count > 1) {
249 return TRUE(!(0));
250 }
251 }
252 }
253
254 return FALSE(0);
255}
256
257static int
258get_not_gone_original_file_count (FMPropertiesWindow *window)
259{
260 GList *l;
261 int count;
262
263 count = 0;
264
265 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
266 if (!caja_file_is_gone (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
267 count++;
268 }
269 }
270
271 return count;
272}
273
274static CajaFile *
275get_original_file (FMPropertiesWindow *window)
276{
277 g_return_val_if_fail (!is_multi_file_window (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if (!is_multi_file_window (window)) _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__)), "!is_multi_file_window (window)"); return (((void
*)0)); } } while (0)
;
278
279 if (window->details->original_files == NULL((void*)0)) {
280 return NULL((void*)0);
281 }
282
283 return CAJA_FILE (window->details->original_files->data)((((CajaFile*) (void *) ((window->details->original_files
->data)))))
;
284}
285
286static CajaFile *
287get_target_file_for_original_file (CajaFile *file)
288{
289 CajaFile *target_file;
290
291 target_file = NULL((void*)0);
292 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
293 CajaDesktopLink *link;
294
295 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
296
297 if (link != NULL((void*)0)) {
298 GFile *location;
299
300 /* map to linked URI for these types of links */
301 location = caja_desktop_link_get_activation_location (link);
302
303 if (location) {
304 target_file = caja_file_get (location);
305 g_object_unref (location);
306 }
307
308 g_object_unref (link);
309 }
310 } else {
311 char *uri_to_display;
312
313 uri_to_display = caja_file_get_activation_uri (file);
314
315 if (uri_to_display != NULL((void*)0)) {
316 target_file = caja_file_get_by_uri (uri_to_display);
317 g_free (uri_to_display);
318 }
319 }
320
321 if (target_file != NULL((void*)0)) {
322 return target_file;
323 }
324
325 /* Ref passed-in file here since we've decided to use it. */
326 caja_file_ref (file);
327 return file;
328}
329
330static CajaFile *
331get_target_file (FMPropertiesWindow *window)
332{
333 return CAJA_FILE (window->details->target_files->data)((((CajaFile*) (void *) ((window->details->target_files
->data)))))
;
334}
335
336static void
337add_prompt (GtkWidget *vbox, const char *prompt_text, gboolean pack_at_start)
338{
339 GtkWidget *prompt;
340
341 prompt = gtk_label_new (prompt_text);
342 gtk_label_set_justify (GTK_LABEL (prompt)((((GtkLabel*) (void *) ((prompt))))), GTK_JUSTIFY_LEFT);
343 gtk_label_set_line_wrap (GTK_LABEL (prompt)((((GtkLabel*) (void *) ((prompt))))), TRUE(!(0)));
344 gtk_widget_show (prompt);
345 if (pack_at_start) {
346 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), prompt, FALSE(0), FALSE(0), 0);
347 } else {
348 gtk_box_pack_end (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), prompt, FALSE(0), FALSE(0), 0);
349 }
350}
351
352static void
353add_prompt_and_separator (GtkWidget *vbox, const char *prompt_text)
354{
355 GtkWidget *separator_line;
356
357 add_prompt (vbox, prompt_text, FALSE(0));
358
359 separator_line = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
360
361 gtk_widget_show (separator_line);
362 gtk_box_pack_end (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), separator_line, TRUE(!(0)), TRUE(!(0)), 2*ROW_PAD6);
363}
364
365static void
366get_image_for_properties_window (FMPropertiesWindow *window,
367 char **icon_name,
368 GdkPixbuf **icon_pixbuf)
369{
370 CajaIconInfo *icon, *new_icon;
371 GList *l;
372 gint icon_scale;
373
374 icon = NULL((void*)0);
375 icon_scale = gtk_widget_get_scale_factor (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
);
376
377 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
378 CajaFile *file;
379
380 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
381
382 if (!icon) {
383 icon = caja_file_get_icon (file, CAJA_ICON_SIZE_STANDARD48, icon_scale,
384 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS |
385 CAJA_FILE_ICON_FLAGS_IGNORE_VISITING);
386 } else {
387 new_icon = caja_file_get_icon (file, CAJA_ICON_SIZE_STANDARD48, icon_scale,
388 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS |
389 CAJA_FILE_ICON_FLAGS_IGNORE_VISITING);
390 if (!new_icon || new_icon != icon) {
391 g_object_unref (icon);
392 g_object_unref (new_icon);
393 icon = NULL((void*)0);
394 break;
395 }
396 g_object_unref (new_icon);
397 }
398 }
399
400 if (!icon) {
401 icon = caja_icon_info_lookup_from_name ("text-x-generic",
402 CAJA_ICON_SIZE_STANDARD48,
403 icon_scale);
404 }
405
406 if (icon_name != NULL((void*)0)) {
407 *icon_name = g_strdup (caja_icon_info_get_used_name (icon))g_strdup_inline (caja_icon_info_get_used_name (icon));
408 }
409
410 if (icon_pixbuf != NULL((void*)0)) {
411 *icon_pixbuf = caja_icon_info_get_pixbuf_at_size (icon, CAJA_ICON_SIZE_STANDARD48);
412 }
413
414 g_object_unref (icon);
415}
416
417
418static void
419update_properties_window_icon (FMPropertiesWindow *window)
420{
421 GdkPixbuf *pixbuf;
422 cairo_surface_t *surface;
423 char *name;
424
425 get_image_for_properties_window (window, &name, &pixbuf);
426
427 if (name != NULL((void*)0)) {
428 gtk_window_set_icon_name (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), name);
429 } else {
430 gtk_window_set_icon (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), pixbuf);
431 }
432
433 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, gtk_widget_get_scale_factor (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))),
434 gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))));
435 gtk_image_set_from_surface (GTK_IMAGE (window->details->icon_image)((((GtkImage*) (void *) ((window->details->icon_image))
)))
, surface);
436
437 g_free (name);
438 g_object_unref (pixbuf);
439 cairo_surface_destroy (surface);
440}
441
442/* utility to test if a uri refers to a local image */
443static gboolean
444uri_is_local_image (const char *uri)
445{
446 GdkPixbuf *pixbuf;
447 char *image_path;
448
449 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
450 if (image_path == NULL((void*)0)) {
451 return FALSE(0);
452 }
453
454 pixbuf = gdk_pixbuf_new_from_file (image_path, NULL((void*)0));
455 g_free (image_path);
456
457 if (pixbuf == NULL((void*)0)) {
458 return FALSE(0);
459 }
460 g_object_unref (pixbuf);
461 return TRUE(!(0));
462}
463
464
465static void
466reset_icon (FMPropertiesWindow *properties_window)
467{
468 GList *l;
469
470 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
471 CajaFile *file;
472
473 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
474
475 caja_file_set_metadata (file,
476 CAJA_METADATA_KEY_ICON_SCALE"icon-scale",
477 NULL((void*)0), NULL((void*)0));
478 caja_file_set_metadata (file,
479 CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon",
480 NULL((void*)0), NULL((void*)0));
481 }
482}
483
484
485static void
486fm_properties_window_drag_data_received (GtkWidget *widget, GdkDragContext *context,
487 int x, int y,
488 GtkSelectionData *selection_data,
489 guint info, guint time)
490{
491 char **uris;
492 gboolean exactly_one;
493 GtkImage *image;
494 GtkWindow *window;
495
496 image = GTK_IMAGE (widget)((((GtkImage*) (void *) ((widget)))));
497 window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (image)))((((GtkWindow*) (void *) ((gtk_widget_get_toplevel (((((GtkWidget
*) (void *) ((image)))))))))))
;
498
499 if (info == TARGET_RESET_BACKGROUND) {
500 reset_icon (FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) ((window))))));
501
502 return;
503 }
504
505 uris = g_strsplit (gtk_selection_data_get_data (selection_data), "\r\n", 0);
506 exactly_one = uris[0] != NULL((void*)0) && (uris[1] == NULL((void*)0) || uris[1][0] == '\0');
507
508
509 if (!exactly_one) {
510 eel_show_error_dialog
511 (_("You cannot assign more than one custom icon at a time!")dcgettext (((void*)0), "You cannot assign more than one custom icon at a time!"
, 5)
,
512 _("Please drag just one image to set a custom icon.")dcgettext (((void*)0), "Please drag just one image to set a custom icon."
, 5)
,
513 window);
514 } else {
515 if (uri_is_local_image (uris[0])) {
516 set_icon (uris[0], FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) ((window))))));
517 } else {
518 GFile *f;
519
520 f = g_file_new_for_uri (uris[0]);
521 if (!g_file_is_native (f)) {
522 eel_show_error_dialog
523 (_("The file that you dropped is not local.")dcgettext (((void*)0), "The file that you dropped is not local."
, 5)
,
524 _("You can only use local images as custom icons.")dcgettext (((void*)0), "You can only use local images as custom icons."
, 5)
,
525 window);
526
527 } else {
528 eel_show_error_dialog
529 (_("The file that you dropped is not an image.")dcgettext (((void*)0), "The file that you dropped is not an image."
, 5)
,
530 _("You can only use local images as custom icons.")dcgettext (((void*)0), "You can only use local images as custom icons."
, 5)
,
531 window);
532 }
533 g_object_unref (f);
534 }
535 }
536 g_strfreev (uris);
537}
538
539static GtkWidget *
540create_image_widget (FMPropertiesWindow *window,
541 gboolean is_customizable)
542{
543 GtkWidget *button;
544 GtkWidget *image;
545
546 image = gtk_image_new ();
547 window->details->icon_image = image;
548
549 update_properties_window_icon (window);
550 gtk_widget_show (image);
551
552 button = NULL((void*)0);
553 if (is_customizable) {
554 button = gtk_button_new ();
555 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), image);
556
557 /* prepare the image to receive dropped objects to assign custom images */
558 gtk_drag_dest_set (GTK_WIDGET (image)((((GtkWidget*) (void *) ((image))))),
559 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
560 target_table, G_N_ELEMENTS (target_table)(sizeof (target_table) / sizeof ((target_table)[0])),
561 GDK_ACTION_COPY | GDK_ACTION_MOVE);
562
563 g_signal_connect (image, "drag_data_received",g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
564 G_CALLBACK (fm_properties_window_drag_data_received), NULL)g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
;
565 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
566 G_CALLBACK (select_image_button_callback), window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
567 }
568
569 window->details->icon_button = button;
570
571 return button != NULL((void*)0) ? button : image;
572}
573
574static void
575set_name_field (FMPropertiesWindow *window,
576 const gchar *original_name,
577 const gchar *name)
578{
579 gboolean new_widget;
580 gboolean use_label;
581
582 /* There are four cases here:
583 * 1) Changing the text of a label
584 * 2) Changing the text of an entry
585 * 3) Creating label (potentially replacing entry)
586 * 4) Creating entry (potentially replacing label)
587 */
588 use_label = is_multi_file_window (window) || !caja_file_can_rename (get_original_file (window));
589 new_widget = !window->details->name_field || (use_label ? CAJA_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (caja_entry_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; }))))
: GTK_IS_LABEL (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = ((gtk_label_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; }))))
);
590
591 if (new_widget) {
592 if (window->details->name_field) {
593 gtk_widget_destroy (window->details->name_field);
594 }
595
596 if (use_label) {
597 window->details->name_field = GTK_WIDGET((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
598 (attach_ellipsizing_value_label (window->details->basic_grid,((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
599 GTK_WIDGET (window->details->name_label),((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
600 name))((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
;
601
602 } else {
603 window->details->name_field = caja_entry_new ();
604 gtk_entry_set_text (GTK_ENTRY (window->details->name_field)((((GtkEntry*) (void *) ((window->details->name_field))
)))
, name);
605 gtk_widget_show (window->details->name_field);
606 gtk_grid_attach_next_to (window->details->basic_grid, window->details->name_field,
607 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
,
608 GTK_POS_RIGHT, 1, 1);
609
610 gtk_label_set_mnemonic_widget (GTK_LABEL (window->details->name_label)((((GtkLabel*) (void *) ((window->details->name_label))
)))
, window->details->name_field);
611
612 g_signal_connect_object (window->details->name_field, "focus_out_event",
613 G_CALLBACK (name_field_focus_out)((GCallback) (name_field_focus_out)), window, 0);
614 g_signal_connect_object (window->details->name_field, "activate",
615 G_CALLBACK (name_field_activate)((GCallback) (name_field_activate)), window, 0);
616 }
617
618 gtk_widget_show (window->details->name_field);
619 }
620 /* Only replace text if the file's name has changed. */
621 else if (original_name == NULL((void*)0) || strcmp (original_name, name) != 0) {
622
623 if (use_label) {
624 gtk_label_set_text (GTK_LABEL (window->details->name_field)((((GtkLabel*) (void *) ((window->details->name_field))
)))
, name);
625 } else {
626 /* Only reset the text if it's different from what is
627 * currently showing. This causes minimal ripples (e.g.
628 * selection change).
629 */
630 gchar *displayed_name = gtk_editable_get_chars (GTK_EDITABLE (window->details->name_field)((((GtkEditable*) (void *) ((window->details->name_field
)))))
, 0, -1);
631 if (strcmp (displayed_name, name) != 0) {
632 gtk_entry_set_text (GTK_ENTRY (window->details->name_field)((((GtkEntry*) (void *) ((window->details->name_field))
)))
, name);
633 }
634 g_free (displayed_name);
635 }
636 }
637}
638
639static void
640update_name_field (FMPropertiesWindow *window)
641{
642 CajaFile *file;
643
644 gtk_label_set_text_with_mnemonic (window->details->name_label,
645 ngettext ("_Name:", "_Names:",dcngettext (((void*)0), "_Name:", "_Names:", get_not_gone_original_file_count
(window), 5)
646 get_not_gone_original_file_count (window))dcngettext (((void*)0), "_Name:", "_Names:", get_not_gone_original_file_count
(window), 5)
);
647
648 if (is_multi_file_window (window)) {
649 /* Multifile property dialog, show all names */
650 GString *str;
651 char *name;
652 gboolean first;
653 GList *l;
654
655 str = g_string_new ("");
656
657 first = TRUE(!(0));
658
659 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
660 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
661
662 if (!caja_file_is_gone (file)) {
663 if (!first) {
664 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_193; if (__val != ((void
*)0)) _g_boolean_var_193 = 1; else _g_boolean_var_193 = 0; _g_boolean_var_193
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
665 }
666 first = FALSE(0);
667
668 name = caja_file_get_display_name (file);
669 g_string_append (str, name)(__builtin_constant_p (name) ? __extension__ ({ const char * const
__val = (name); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_194; if (__val != ((void
*)0)) _g_boolean_var_194 = 1; else _g_boolean_var_194 = 0; _g_boolean_var_194
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, name, (gssize) -1
))
;
670 g_free (name);
671 }
672 }
673 set_name_field (window, NULL((void*)0), str->str);
674 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
675 } else {
676 const char *original_name = NULL((void*)0);
677 char *current_name;
678
679 file = get_original_file (window);
680
681 if (file == NULL((void*)0) || caja_file_is_gone (file)) {
682 current_name = g_strdup ("")g_strdup_inline ("");
683 } else {
684 current_name = caja_file_get_display_name (file);
685 }
686
687 /* If the file name has changed since the original name was stored,
688 * update the text in the text field, possibly (deliberately) clobbering
689 * an edit in progress. If the name hasn't changed (but some other
690 * aspect of the file might have), then don't clobber changes.
691 */
692 if (window->details->name_field) {
693 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
, "original_name");
694 }
695
696 set_name_field (window, original_name, current_name);
697
698 if (original_name == NULL((void*)0) ||
699 g_strcmp0 (original_name, current_name) != 0) {
700 g_object_set_data_full (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
,
701 "original_name",
702 current_name,
703 g_free);
704 } else {
705 g_free (current_name);
706 }
707 }
708}
709
710static void
711name_field_restore_original_name (CajaEntry *name_field)
712{
713 const char *original_name;
714 char *displayed_name;
715
716 original_name = (const char *) g_object_get_data (G_OBJECT (name_field)((((GObject*) (void *) ((name_field))))),
717 "original_name");
718
719 if (!original_name) {
720 return;
721 }
722
723 displayed_name = gtk_editable_get_chars (GTK_EDITABLE (name_field)((((GtkEditable*) (void *) ((name_field))))), 0, -1);
724
725 if (strcmp (original_name, displayed_name) != 0) {
726 gtk_entry_set_text (GTK_ENTRY (name_field)((((GtkEntry*) (void *) ((name_field))))), original_name);
727 }
728 caja_entry_select_all (name_field);
729
730 g_free (displayed_name);
731}
732
733static void
734rename_callback (CajaFile *file, GFile *res_loc, GError *error, gpointer callback_data)
735{
736 FMPropertiesWindow *window;
737
738 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
739
740 /* Complain to user if rename failed. */
741 if (error != NULL((void*)0)) {
742 fm_report_error_renaming_file (file,
743 window->details->pending_name,
744 error,
745 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
746 if (window->details->name_field != NULL((void*)0)) {
747 name_field_restore_original_name (CAJA_ENTRY (window->details->name_field)((((CajaEntry*) (void *) ((window->details->name_field)
))))
);
748 }
749 }
750
751 g_object_unref (window);
752}
753
754static void
755set_pending_name (FMPropertiesWindow *window, const char *name)
756{
757 g_free (window->details->pending_name);
758 window->details->pending_name = g_strdup (name)g_strdup_inline (name);
759}
760
761static void
762name_field_done_editing (CajaEntry *name_field, FMPropertiesWindow *window)
763{
764 CajaFile *file;
765 char *new_name;
766
767 g_return_if_fail (CAJA_IS_ENTRY (name_field))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (caja_entry_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__)), "CAJA_IS_ENTRY (name_field)"); return; }
} while (0)
;
768
769 /* Don't apply if the dialog has more than one file */
770 if (is_multi_file_window (window)) {
771 return;
772 }
773
774 file = get_original_file (window);
775
776 /* This gets called when the window is closed, which might be
777 * caused by the file having been deleted.
778 */
779 if (file == NULL((void*)0) || caja_file_is_gone (file)) {
780 return;
781 }
782
783 new_name = gtk_editable_get_chars (GTK_EDITABLE (name_field)((((GtkEditable*) (void *) ((name_field))))), 0, -1);
784
785 /* Special case: silently revert text if new text is empty. */
786 if (strlen (new_name) == 0) {
787 name_field_restore_original_name (CAJA_ENTRY (name_field)((((CajaEntry*) (void *) ((name_field))))));
788 } else {
789 const char *original_name;
790
791 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
,
792 "original_name");
793 /* Don't rename if not changed since we read the display name.
794 This is needed so that we don't save the display name to the
795 file when nothing is changed */
796 if (strcmp (new_name, original_name) != 0) {
797 set_pending_name (window, new_name);
798 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
799 caja_file_rename (file, new_name,
800 rename_callback, window);
801 }
802 }
803
804 g_free (new_name);
805}
806
807static gboolean
808name_field_focus_out (CajaEntry *name_field,
809 GdkEventFocus *event,
810 gpointer callback_data)
811{
812 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_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_196 = 1; else _g_boolean_var_196 =
0; _g_boolean_var_196; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 812, ((const char*)
(__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"); } while
(0)
;
813
814 if (gtk_widget_get_sensitive (GTK_WIDGET (name_field)((((GtkWidget*) (void *) ((name_field))))))) {
815 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data))))));
816 }
817
818 return FALSE(0);
819}
820
821static void
822name_field_activate (CajaEntry *name_field, gpointer callback_data)
823{
824 g_assert (CAJA_IS_ENTRY (name_field))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (caja_entry_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_197
= 1; else _g_boolean_var_197 = 0; _g_boolean_var_197; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 824, ((const char*) (__func__)), "CAJA_IS_ENTRY (name_field)"
); } while (0)
;
825 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_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_198 = 1; else _g_boolean_var_198 =
0; _g_boolean_var_198; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 825, ((const char*)
(__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"); } while
(0)
;
826
827 /* Accept changes. */
828 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data))))));
829
830 caja_entry_select_all_at_idle (name_field);
831}
832
833static gboolean
834file_has_keyword (CajaFile *file, const char *keyword)
835{
836 GList *keywords, *word;
837
838 keywords = caja_file_get_keywords (file);
839 word = g_list_find_custom (keywords, keyword, (GCompareFunc) strcmp);
840 g_list_free_full (keywords, g_free);
841
842 return (word != NULL((void*)0));
843}
844
845static void
846get_initial_emblem_state (FMPropertiesWindow *window,
847 const char *name,
848 GList **on,
849 GList **off)
850{
851 GList *l;
852
853 *on = NULL((void*)0);
854 *off = NULL((void*)0);
855
856 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
857 GList *initial_emblems;
858
859 initial_emblems = g_hash_table_lookup (window->details->initial_emblems,
860 l->data);
861
862 if (g_list_find_custom (initial_emblems, name, (GCompareFunc) strcmp)) {
863 *on = g_list_prepend (*on, l->data);
864 } else {
865 *off = g_list_prepend (*off, l->data);
866 }
867 }
868}
869
870static void
871emblem_button_toggled (GtkToggleButton *button,
872 FMPropertiesWindow *window)
873{
874 GList *l;
875 GList *keywords;
876 GList *word;
877 char *name;
878 GList *files_on;
879 GList *files_off;
880
881 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name");
882
883 files_on = NULL((void*)0);
884 files_off = NULL((void*)0);
885 if (gtk_toggle_button_get_active (button)
886 && !gtk_toggle_button_get_inconsistent (button)) {
887 /* Go to the initial state unless the initial state was
888 consistent */
889 get_initial_emblem_state (window, name,
890 &files_on, &files_off);
891
892 if (!(files_on && files_off)) {
893 g_list_free (files_on);
894 g_list_free (files_off);
895 files_on = g_list_copy (window->details->original_files);
896 files_off = NULL((void*)0);
897 }
898 } else if (gtk_toggle_button_get_inconsistent (button)
899 && !gtk_toggle_button_get_active (button)) {
900 files_on = g_list_copy (window->details->original_files);
901 files_off = NULL((void*)0);
902 } else {
903 files_off = g_list_copy (window->details->original_files);
904 files_on = NULL((void*)0);
905 }
906
907 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
908 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
909 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
910
911 gtk_toggle_button_set_active (button, files_on != NULL((void*)0));
912 gtk_toggle_button_set_inconsistent (button, files_on && files_off);
913
914 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
915 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
916 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
917
918 for (l = files_on; l != NULL((void*)0); l = l->next) {
919 CajaFile *file;
920
921 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
922
923 keywords = caja_file_get_keywords (file);
924
925 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
926 if (!word) {
927 keywords = g_list_prepend (keywords, g_strdup (name)g_strdup_inline (name));
928 }
929 caja_file_set_keywords (file, keywords);
930 g_list_free_full (keywords, g_free);
931 }
932
933 for (l = files_off; l != NULL((void*)0); l = l->next) {
934 CajaFile *file;
935
936 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
937
938 keywords = caja_file_get_keywords (file);
939
940 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
941 if (word) {
942 keywords = g_list_remove_link (keywords, word);
943 g_list_free_full (word, g_free);
944 }
945 caja_file_set_keywords (file, keywords);
946 g_list_free_full (keywords, g_free);
947 }
948
949 g_list_free (files_on);
950 g_list_free (files_off);
951}
952
953static void
954emblem_button_update (FMPropertiesWindow *window,
955 GtkToggleButton *button)
956{
957 GList *l;
958 char *name;
959 gboolean all_set;
960 gboolean all_unset;
961
962 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name");
963
964 all_set = TRUE(!(0));
965 all_unset = TRUE(!(0));
966 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
967 gboolean has_keyword;
968 CajaFile *file;
969
970 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
971
972 has_keyword = file_has_keyword (file, name);
973
974 if (has_keyword) {
975 all_unset = FALSE(0);
976 } else {
977 all_set = FALSE(0);
978 }
979 }
980
981 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
982 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
983 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
984
985 gtk_toggle_button_set_active (button, !all_unset);
986 gtk_toggle_button_set_inconsistent (button, !all_unset && !all_set);
987
988 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
989 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
990 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
991
992}
993
994static void
995update_properties_window_title (FMPropertiesWindow *window)
996{
997 char *title;
998
999 g_return_if_fail (GTK_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((gtk_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_199
= 1; else _g_boolean_var_199 = 0; _g_boolean_var_199; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "GTK_IS_WINDOW (window)"); return; } } while
(0)
;
1000
1001 title = g_strdup_printf (_("Properties")dcgettext (((void*)0), "Properties", 5));
1002
1003 if (!is_multi_file_window (window)) {
1004 CajaFile *file;
1005
1006 file = get_original_file (window);
1007
1008 if (file != NULL((void*)0)) {
1009 char *name;
1010
1011 g_free (title);
1012 name = caja_file_get_display_name (file);
1013 title = g_strdup_printf (_("%s Properties")dcgettext (((void*)0), "%s Properties", 5), name);
1014 g_free (name);
1015 }
1016 }
1017
1018 gtk_window_set_title (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), title);
1019
1020 g_free (title);
1021}
1022
1023static void
1024clear_extension_pages (FMPropertiesWindow *window)
1025{
1026 int i;
1027 int num_pages;
1028 GtkWidget *page = NULL((void*)0);
1029
1030 num_pages = gtk_notebook_get_n_pages
1031 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
);
1032
1033 for (i = 0; i < num_pages; i++) {
1034 page = gtk_notebook_get_nth_page
1035 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
, i);
1036
1037 if (g_object_get_data (G_OBJECT (page)((((GObject*) (void *) ((page))))), "is-extension-page")) {
1038 gtk_notebook_remove_page
1039 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
, i);
1040 num_pages--;
1041 i--;
1042 }
1043 }
1044}
1045
1046static void
1047refresh_extension_pages (FMPropertiesWindow *window)
1048{
1049 clear_extension_pages (window);
1050 append_extension_pages (window);
1051}
1052
1053static void
1054remove_from_dialog (FMPropertiesWindow *window,
1055 CajaFile *file)
1056{
1057 int index;
1058 GList *original_link;
1059 GList *target_link;
1060 CajaFile *original_file;
1061 CajaFile *target_file;
1062
1063 index = g_list_index (window->details->target_files, file);
1064 if (index == -1) {
1065 index = g_list_index (window->details->original_files, file);
1066 g_return_if_fail (index != -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if (index != -1) _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__)), "index != -1"); return
; } } while (0)
;
1067 }
1068
1069 original_link = g_list_nth (window->details->original_files, index);
1070 target_link = g_list_nth (window->details->target_files, index);
1071
1072 g_return_if_fail (original_link && target_link)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if (original_link && target_link) _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__)), "original_link && target_link");
return; } } while (0)
;
1073
1074 original_file = CAJA_FILE (original_link->data)((((CajaFile*) (void *) ((original_link->data)))));
1075 target_file = CAJA_FILE (target_link->data)((((CajaFile*) (void *) ((target_link->data)))));
1076
1077 window->details->original_files = g_list_remove_link (window->details->original_files, original_link);
1078 g_list_free (original_link);
1079
1080 window->details->target_files = g_list_remove_link (window->details->target_files, target_link);
1081 g_list_free (target_link);
1082
1083 g_hash_table_remove (window->details->initial_emblems, original_file);
1084 g_hash_table_remove (window->details->initial_permissions, target_file);
1085
1086 g_signal_handlers_disconnect_by_func (original_file,g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1087 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1088 window)g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1089 g_signal_handlers_disconnect_by_func (target_file,g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1090 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1091 window)g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1092
1093 caja_file_monitor_remove (original_file, &window->details->original_files);
1094 caja_file_monitor_remove (target_file, &window->details->target_files);
1095
1096 caja_file_unref (original_file);
1097 caja_file_unref (target_file);
1098
1099}
1100
1101static gboolean
1102mime_list_equal (GList *a, GList *b)
1103{
1104 while (a && b) {
1105 if (strcmp (a->data, b->data)) {
1106 return FALSE(0);
1107 }
1108 a = a->next;
1109 b = b->next;
1110 }
1111
1112 return (a == b);
1113}
1114
1115static GList *
1116get_mime_list (FMPropertiesWindow *window)
1117{
1118 GList *ret;
1119 GList *l;
1120
1121 ret = NULL((void*)0);
1122 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
1123 ret = g_list_append (ret, caja_file_get_mime_type (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))))));
1124 }
1125 ret = g_list_reverse (ret);
1126 return ret;
1127}
1128
1129static void
1130properties_window_update (FMPropertiesWindow *window,
1131 GList *files)
1132{
1133 GList *l;
1134 GList *mime_list;
1135 GList *tmp;
1136 CajaFile *changed_file = NULL((void*)0);
1137 gboolean dirty_original = FALSE(0);
1138 gboolean dirty_target = FALSE(0);
1139
1140 if (files == NULL((void*)0)) {
1141 dirty_original = TRUE(!(0));
1142 dirty_target = TRUE(!(0));
1143 }
1144
1145 for (tmp = files; tmp != NULL((void*)0); tmp = tmp->next) {
1146 changed_file = CAJA_FILE (tmp->data)((((CajaFile*) (void *) ((tmp->data)))));
1147
1148 if (changed_file && caja_file_is_gone (changed_file)) {
1149 /* Remove the file from the property dialog */
1150 remove_from_dialog (window, changed_file);
1151 changed_file = NULL((void*)0);
1152
1153 if (window->details->original_files == NULL((void*)0)) {
1154 return;
1155 }
1156 }
1157 if (changed_file == NULL((void*)0) ||
1158 g_list_find (window->details->original_files, changed_file)) {
1159 dirty_original = TRUE(!(0));
1160 }
1161 if (changed_file == NULL((void*)0) ||
1162 g_list_find (window->details->target_files, changed_file)) {
1163 dirty_target = TRUE(!(0));
1164 }
1165
1166 }
1167
1168 if (dirty_original) {
1169 update_properties_window_title (window);
1170 update_properties_window_icon (window);
1171 update_name_field (window);
1172
1173 for (l = window->details->emblem_buttons; l != NULL((void*)0); l = l->next) {
1174 emblem_button_update (window, GTK_TOGGLE_BUTTON (l->data)((((GtkToggleButton*) (void *) ((l->data))))));
1175 }
1176
1177 /* If any of the value fields start to depend on the original
1178 * value, value_field_updates should be added here */
1179 }
1180
1181 if (dirty_target) {
1182 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
1183 permission_button_update (window, GTK_TOGGLE_BUTTON (l->data)((((GtkToggleButton*) (void *) ((l->data))))));
1184 }
1185
1186 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
1187 permission_combo_update (window, GTK_COMBO_BOX (l->data)((((GtkComboBox*) (void *) ((l->data))))));
1188 }
1189
1190 for (l = window->details->value_fields; l != NULL((void*)0); l = l->next) {
1191 value_field_update (window, GTK_LABEL (l->data)((((GtkLabel*) (void *) ((l->data))))));
1192 }
1193 }
1194
1195 mime_list = get_mime_list (window);
1196
1197 if (!window->details->mime_list) {
1198 window->details->mime_list = mime_list;
1199 } else {
1200 if (!mime_list_equal (window->details->mime_list, mime_list)) {
1201 refresh_extension_pages (window);
1202 }
1203
1204 g_list_free_full (window->details->mime_list, g_free);
1205 window->details->mime_list = mime_list;
1206 }
1207}
1208
1209static gboolean
1210update_files_callback (gpointer data)
1211{
1212 FMPropertiesWindow *window;
1213
1214 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
1215
1216 window->details->update_files_timeout_id = 0;
1217
1218 properties_window_update (window, window->details->changed_files);
1219
1220 if (window->details->original_files == NULL((void*)0)) {
1221 /* Close the window if no files are left */
1222 gtk_widget_destroy (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
1223 } else {
1224 caja_file_list_free (window->details->changed_files);
1225 window->details->changed_files = NULL((void*)0);
1226 }
1227
1228 return FALSE(0);
1229 }
1230
1231static void
1232schedule_files_update (FMPropertiesWindow *window)
1233 {
1234 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_202 = 1; else _g_boolean_var_202 = 0; _g_boolean_var_202
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1234, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1235
1236 if (window->details->update_files_timeout_id == 0) {
1237 window->details->update_files_timeout_id
1238 = g_timeout_add (FILES_UPDATE_INTERVAL200,
1239 update_files_callback,
1240 window);
1241 }
1242 }
1243
1244static gboolean
1245file_list_attributes_identical (GList *file_list, const char *attribute_name)
1246{
1247 gboolean identical;
1248 char *first_attr;
1249 GList *l;
1250
1251 first_attr = NULL((void*)0);
1252 identical = TRUE(!(0));
1253
1254 for (l = file_list; l != NULL((void*)0); l = l->next) {
1255 CajaFile *file;
1256
1257 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1258
1259 if (caja_file_is_gone (file)) {
1260 continue;
1261 }
1262
1263 if (first_attr == NULL((void*)0)) {
1264 first_attr = caja_file_get_string_attribute_with_default (file, attribute_name);
1265 } else {
1266 char *attr;
1267 attr = caja_file_get_string_attribute_with_default (file, attribute_name);
1268 if (strcmp (attr, first_attr)) {
1269 identical = FALSE(0);
1270 g_free (attr);
1271 break;
1272 }
1273 g_free (attr);
1274 }
1275 }
1276
1277 g_free (first_attr);
1278 return identical;
1279}
1280
1281static char *
1282file_list_get_string_attribute (GList *file_list,
1283 const char *attribute_name,
1284 const char *inconsistent_value)
1285{
1286 if (file_list_attributes_identical (file_list, attribute_name)) {
1287 GList *l;
1288
1289 for (l = file_list; l != NULL((void*)0); l = l->next) {
1290 CajaFile *file;
1291
1292 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1293 if (!caja_file_is_gone (file)) {
1294 return caja_file_get_string_attribute_with_default
1295 (file,
1296 attribute_name);
1297 }
1298 }
1299 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
1300 } else {
1301 return g_strdup (inconsistent_value)g_strdup_inline (inconsistent_value);
1302 }
1303}
1304
1305
1306static gboolean
1307file_list_all_directories (GList *file_list)
1308{
1309 GList *l;
1310 for (l = file_list; l != NULL((void*)0); l = l->next) {
1311 if (!caja_file_is_directory (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
1312 return FALSE(0);
1313 }
1314 }
1315 return TRUE(!(0));
1316}
1317
1318static void
1319value_field_update_internal (GtkLabel *label,
1320 GList *file_list)
1321{
1322 const char *attribute_name;
1323 char *attribute_value;
1324 char *inconsistent_string;
1325
1326 g_assert (GTK_IS_LABEL (label))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((gtk_label_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1326, ((const char*) (__func__)), "GTK_IS_LABEL (label)"); }
while (0)
;
1327
1328 attribute_name = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) ((label))))), "file_attribute");
1329 inconsistent_string = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) ((label))))), "inconsistent_string");
1330 attribute_value = file_list_get_string_attribute (file_list,
1331 attribute_name,
1332 inconsistent_string);
1333 if (!strcmp (attribute_name, "type") && strcmp (attribute_value, inconsistent_string)) {
1334 char *mime_type;
1335
1336 mime_type = file_list_get_string_attribute (file_list,
1337 "mime_type",
1338 inconsistent_string);
1339 if (strcmp (mime_type, inconsistent_string)) {
1340 char *tmp;
1341
1342 tmp = attribute_value;
1343 attribute_value = g_strdup_printf (C_("MIME type description (MIME type)", "%s (%s)")g_dpgettext (((void*)0), "MIME type description (MIME type)" "\004"
"%s (%s)", strlen ("MIME type description (MIME type)") + 1)
, attribute_value, mime_type);
1344 g_free (tmp);
1345 }
1346 g_free (mime_type);
1347 }
1348
1349 gtk_label_set_text (label, attribute_value);
1350 g_free (attribute_value);
1351}
1352
1353static void
1354value_field_update (FMPropertiesWindow *window, GtkLabel *label)
1355{
1356 gboolean use_original;
1357
1358 use_original = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), "show_original"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
label))))), "show_original")))
;
1359
1360 value_field_update_internal (label,
1361 (use_original ?
1362 window->details->original_files :
1363 window->details->target_files));
1364}
1365
1366static GtkLabel *
1367attach_label (GtkGrid *grid,
1368 GtkWidget *sibling,
1369 const char *initial_text,
1370 gboolean ellipsize_text,
1371 gboolean selectable,
1372 gboolean mnemonic)
1373{
1374 GtkWidget *label_field;
1375
1376 if (ellipsize_text) {
1377 label_field = gtk_label_new (initial_text);
1378 gtk_label_set_ellipsize (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))),
1379 PANGO_ELLIPSIZE_END);
1380 } else if (mnemonic) {
1381 label_field = gtk_label_new_with_mnemonic (initial_text);
1382 } else {
1383 label_field = gtk_label_new (initial_text);
1384 }
1385
1386 if (selectable) {
1387 gtk_label_set_selectable (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), TRUE(!(0)));
1388 }
1389
1390 gtk_label_set_xalign (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), 0);
1391 gtk_widget_show (label_field);
1392 if (ellipsize_text) {
1393 gtk_widget_set_hexpand (label_field, TRUE(!(0)));
1394 gtk_label_set_max_width_chars (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), 24);
1395 }
1396
1397 if (sibling != NULL((void*)0)) {
1398 gtk_grid_attach_next_to (grid, label_field, sibling,
1399 GTK_POS_RIGHT, 1, 1);
1400 } else {
1401 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), label_field);
1402 }
1403
1404 return GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field)))));
1405}
1406
1407static GtkLabel *
1408attach_value_label (GtkGrid *grid,
1409 GtkWidget *sibling,
1410 const char *initial_text)
1411{
1412 return attach_label (grid, sibling, initial_text, FALSE(0), TRUE(!(0)), FALSE(0));
1413}
1414
1415static GtkLabel *
1416attach_ellipsizing_value_label (GtkGrid *grid,
1417 GtkWidget *sibling,
1418 const char *initial_text)
1419{
1420 return attach_label (grid, sibling, initial_text, TRUE(!(0)), TRUE(!(0)), FALSE(0));
1421}
1422
1423static GtkWidget*
1424attach_value_field_internal (FMPropertiesWindow *window,
1425 GtkGrid *grid,
1426 GtkWidget *sibling,
1427 const char *file_attribute_name,
1428 const char *inconsistent_string,
1429 gboolean show_original,
1430 gboolean ellipsize_text)
1431{
1432 GtkLabel *value_field;
1433
1434 if (ellipsize_text) {
1435 value_field = attach_ellipsizing_value_label (grid, sibling, "");
1436 } else {
1437 value_field = attach_value_label (grid, sibling, "");
1438 }
1439
1440 /* Stash a copy of the file attribute name in this field for the callback's sake. */
1441 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "file_attribute",
1442 g_strdup (file_attribute_name)g_strdup_inline (file_attribute_name), g_free);
1443
1444 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "inconsistent_string",
1445 g_strdup (inconsistent_string)g_strdup_inline (inconsistent_string), g_free);
1446
1447 g_object_set_data (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "show_original", GINT_TO_POINTER (show_original)((gpointer) (glong) (show_original)));
1448
1449 window->details->value_fields = g_list_prepend (window->details->value_fields,
1450 value_field);
1451 return GTK_WIDGET(value_field)((((GtkWidget*) (void *) ((value_field)))));
1452}
1453
1454static GtkWidget*
1455attach_value_field (FMPropertiesWindow *window,
1456 GtkGrid *grid,
1457 GtkWidget *sibling,
1458 const char *file_attribute_name,
1459 const char *inconsistent_string,
1460 gboolean show_original)
1461{
1462 return attach_value_field_internal (window,
1463 grid, sibling,
1464 file_attribute_name,
1465 inconsistent_string,
1466 show_original,
1467 FALSE(0));
1468}
1469
1470static GtkWidget*
1471attach_ellipsizing_value_field (FMPropertiesWindow *window,
1472 GtkGrid *grid,
1473 GtkWidget *sibling,
1474 const char *file_attribute_name,
1475 const char *inconsistent_string,
1476 gboolean show_original)
1477{
1478 return attach_value_field_internal (window,
1479 grid, sibling,
1480 file_attribute_name,
1481 inconsistent_string,
1482 show_original,
1483 TRUE(!(0)));
1484}
1485
1486static void
1487group_change_callback (CajaFile *file,
1488 GFile *res_loc,
1489 GError *error,
1490 FMPropertiesWindow *window)
1491{
1492 char *group;
1493
1494 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_204 = 1; else _g_boolean_var_204 = 0; _g_boolean_var_204
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1494, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1495 g_assert (window->details->group_change_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if (window->details->group_change_file == file) _g_boolean_var_205
= 1; else _g_boolean_var_205 = 0; _g_boolean_var_205; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1495, ((const char*) (__func__)), "window->details->group_change_file == file"
); } while (0)
;
1496
1497 group = window->details->group_change_group;
1498 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (group != ((void*)0)) _g_boolean_var_206 = 1; else _g_boolean_var_206
= 0; _g_boolean_var_206; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1498, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1499
1500 /* Report the error if it's an error. */
1501 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1502 fm_report_error_setting_group (file, error, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1503
1504 caja_file_unref (file);
1505 g_free (group);
1506
1507 window->details->group_change_file = NULL((void*)0);
1508 window->details->group_change_group = NULL((void*)0);
1509 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1510}
1511
1512static void
1513cancel_group_change_callback (FMPropertiesWindow *window)
1514{
1515 CajaFile *file;
1516 char *group;
1517
1518 file = window->details->group_change_file;
1519 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_207
= 1; else _g_boolean_var_207 = 0; _g_boolean_var_207; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1519, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1520
1521 group = window->details->group_change_group;
1522 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (group != ((void*)0)) _g_boolean_var_208 = 1; else _g_boolean_var_208
= 0; _g_boolean_var_208; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1522, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1523
1524 caja_file_cancel (file, (CajaFileOperationCallback) group_change_callback, window);
1525
1526 g_free (group);
1527 caja_file_unref (file);
1528
1529 window->details->group_change_file = NULL((void*)0);
1530 window->details->group_change_group = NULL((void*)0);
1531 g_object_unref (window);
1532}
1533
1534static gboolean
1535schedule_group_change_timeout (FMPropertiesWindow *window)
1536{
1537 CajaFile *file;
1538 char *group;
1539
1540 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_209 = 1; else _g_boolean_var_209 = 0; _g_boolean_var_209
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1540, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1541
1542 file = window->details->group_change_file;
1543 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_210
= 1; else _g_boolean_var_210 = 0; _g_boolean_var_210; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1543, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1544
1545 group = window->details->group_change_group;
1546 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (group != ((void*)0)) _g_boolean_var_211 = 1; else _g_boolean_var_211
= 0; _g_boolean_var_211; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1546, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1547
1548 eel_timed_wait_start
1549 ((EelCancelCallback) cancel_group_change_callback,
1550 window,
1551 _("Cancel Group Change?")dcgettext (((void*)0), "Cancel Group Change?", 5),
1552 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1553
1554 caja_file_set_group
1555 (file, group,
1556 (CajaFileOperationCallback) group_change_callback, window);
1557
1558 window->details->group_change_timeout = 0;
1559 return FALSE(0);
1560}
1561
1562static void
1563schedule_group_change (FMPropertiesWindow *window,
1564 CajaFile *file,
1565 const char *group)
1566{
1567 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_212 = 1; else _g_boolean_var_212 = 0; _g_boolean_var_212
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1567, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1568 g_assert (window->details->group_change_group == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if (window->details->group_change_group == ((void*)0)
) _g_boolean_var_213 = 1; else _g_boolean_var_213 = 0; _g_boolean_var_213
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1568, ((const char*) (__func__)), "window->details->group_change_group == NULL"
); } while (0)
;
1569 g_assert (window->details->group_change_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if (window->details->group_change_file == ((void*)0))
_g_boolean_var_214 = 1; else _g_boolean_var_214 = 0; _g_boolean_var_214
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1569, ((const char*) (__func__)), "window->details->group_change_file == NULL"
); } while (0)
;
1570 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_215
= 1; else _g_boolean_var_215 = 0; _g_boolean_var_215; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1570, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1571
1572 window->details->group_change_file = caja_file_ref (file);
1573 window->details->group_change_group = g_strdup (group)g_strdup_inline (group);
1574 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) ((window))))))) (g_object_ref
) (((((GObject*) (void *) ((window)))))))
;
1575 window->details->group_change_timeout =
1576 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1577 (GSourceFunc) schedule_group_change_timeout,
1578 window);
1579}
1580
1581static void
1582unschedule_or_cancel_group_change (FMPropertiesWindow *window)
1583{
1584 CajaFile *file;
1585 char *group;
1586
1587 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_216 = 1; else _g_boolean_var_216 = 0; _g_boolean_var_216
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1587, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1588
1589 file = window->details->group_change_file;
1590 group = window->details->group_change_group;
1591
1592 g_assert ((file == NULL && group == NULL) ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if ((file == ((void*)0) && group == ((void*)0)) || (
file != ((void*)0) && group != ((void*)0))) _g_boolean_var_217
= 1; else _g_boolean_var_217 = 0; _g_boolean_var_217; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1593, ((const char*) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
1593 (file != NULL && group != NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if ((file == ((void*)0) && group == ((void*)0)) || (
file != ((void*)0) && group != ((void*)0))) _g_boolean_var_217
= 1; else _g_boolean_var_217 = 0; _g_boolean_var_217; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1593, ((const char*) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
;
1594
1595 if (file != NULL((void*)0)) {
1596 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_218
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_218
= 1; else _g_boolean_var_218 = 0; _g_boolean_var_218; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1596, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1597
1598 if (window->details->group_change_timeout == 0) {
1599 caja_file_cancel (file,
1600 (CajaFileOperationCallback) group_change_callback, window);
1601 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1602 }
1603
1604 caja_file_unref (file);
1605 g_free (group);
1606
1607 window->details->group_change_file = NULL((void*)0);
1608 window->details->group_change_group = NULL((void*)0);
1609 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1610 }
1611
1612 if (window->details->group_change_timeout > 0) {
1613 g_assert (file != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_219
; if (file != ((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), "fm-properties-window.c", 1613, ((const char*
) (__func__)), "file != NULL"); } while (0)
;
1614 g_source_remove (window->details->group_change_timeout);
1615 window->details->group_change_timeout = 0;
1616 }
1617}
1618
1619static void
1620changed_group_callback (GtkComboBox *combo_box, CajaFile *file)
1621{
1622 char *group;
1623 char *cur_group;
1624
1625 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_220
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_220
= 1; else _g_boolean_var_220 = 0; _g_boolean_var_220; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1625, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1626 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_221
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_221
= 1; else _g_boolean_var_221 = 0; _g_boolean_var_221; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1626, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1627
1628 group = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))));
1629 cur_group = caja_file_get_group_name (file);
1630
1631 if (group != NULL((void*)0) && strcmp (group, cur_group) != 0) {
1632 FMPropertiesWindow *window;
1633
1634 /* Try to change file group. If this fails, complain to user. */
1635 window = FM_PROPERTIES_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (combo_box), GTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) ((gtk_widget_get_ancestor (
((((GtkWidget*) (void *) ((combo_box))))), (gtk_window_get_type
())))))))
;
1636
1637 unschedule_or_cancel_group_change (window);
1638 schedule_group_change (window, file, group);
1639 }
1640 g_free (group);
1641 g_free (cur_group);
1642}
1643
1644/* checks whether the given column at the first level
1645 * of model has the specified entries in the given order. */
1646static gboolean
1647tree_model_entries_equal (GtkTreeModel *model,
1648 unsigned int column,
1649 GList *entries)
1650{
1651 GtkTreeIter iter;
1652 gboolean empty_model;
1653
1654 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_222
= 1; else _g_boolean_var_222 = 0; _g_boolean_var_222; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1654, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1655 g_assert (gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_223
; if (gtk_tree_model_get_column_type (model, column) == ((GType
) ((16) << (2)))) _g_boolean_var_223 = 1; else _g_boolean_var_223
= 0; _g_boolean_var_223; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1655, ((const char*
) (__func__)), "gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1656
1657 empty_model = !gtk_tree_model_get_iter_first (model, &iter);
1658
1659 if (!empty_model && entries != NULL((void*)0)) {
1660 GList *l;
1661
1662 l = entries;
1663
1664 do {
1665 char *val;
1666
1667 gtk_tree_model_get (model, &iter,
1668 column, &val,
1669 -1);
1670 if ((val == NULL((void*)0) && l->data != NULL((void*)0)) ||
1671 (val != NULL((void*)0) && l->data == NULL((void*)0)) ||
1672 (val != NULL((void*)0) && strcmp (val, l->data))) {
1673 g_free (val);
1674 return FALSE(0);
1675 }
1676
1677 g_free (val);
1678 l = l->next;
1679 } while (gtk_tree_model_iter_next (model, &iter));
1680
1681 return l == NULL((void*)0);
1682 } else {
1683 return (empty_model && entries == NULL((void*)0)) ||
1684 (!empty_model && entries != NULL((void*)0));
1685 }
1686}
1687
1688static char *
1689combo_box_get_active_entry (GtkComboBox *combo_box,
1690 unsigned int column)
1691{
1692 GtkTreeIter iter;
1693 char *val;
1694
1695 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_224
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_224
= 1; else _g_boolean_var_224 = 0; _g_boolean_var_224; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1695, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1696
1697 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box))))), &iter)) {
1698 GtkTreeModel *model;
1699
1700 model = gtk_combo_box_get_model (combo_box);
1701 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_225
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_225
= 1; else _g_boolean_var_225 = 0; _g_boolean_var_225; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1701, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1702
1703 gtk_tree_model_get (model, &iter,
1704 column, &val,
1705 -1);
1706 return val;
1707 }
1708
1709 return NULL((void*)0);
1710}
1711
1712/* returns the index of the given entry in the the given column
1713 * at the first level of model. Returns -1 if entry can't be found
1714 * or entry is NULL.
1715 * */
1716static int
1717tree_model_get_entry_index (GtkTreeModel *model,
1718 unsigned int column,
1719 const char *entry)
1720{
1721 GtkTreeIter iter;
1722 gboolean empty_model;
1723
1724 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_226
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1724, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1725 g_assert (gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if (gtk_tree_model_get_column_type (model, column) == ((GType
) ((16) << (2)))) _g_boolean_var_227 = 1; else _g_boolean_var_227
= 0; _g_boolean_var_227; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1725, ((const char*
) (__func__)), "gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1726
1727 empty_model = !gtk_tree_model_get_iter_first (model, &iter);
1728 if (!empty_model && entry != NULL((void*)0)) {
1729 int index;
1730
1731 index = 0;
1732
1733 do {
1734 char *val;
1735
1736 gtk_tree_model_get (model, &iter,
1737 column, &val,
1738 -1);
1739 if (val != NULL((void*)0) && !strcmp (val, entry)) {
1740 g_free (val);
1741 return index;
1742 }
1743
1744 g_free (val);
1745 index++;
1746 } while (gtk_tree_model_iter_next (model, &iter));
1747 }
1748
1749 return -1;
1750}
1751
1752
1753static void
1754synch_groups_combo_box (GtkComboBox *combo_box, CajaFile *file)
1755{
1756 GList *groups;
1757 GList *node;
1758 GtkTreeModel *model;
1759 GtkListStore *store;
1760 char *current_group_name;
1761 int current_group_index;
1762
1763 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_228
= 1; else _g_boolean_var_228 = 0; _g_boolean_var_228; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1763, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1764 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_229
= 1; else _g_boolean_var_229 = 0; _g_boolean_var_229; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1764, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1765
1766 if (caja_file_is_gone (file)) {
1767 return;
1768 }
1769
1770 groups = caja_file_get_settable_group_names (file);
1771
1772 model = gtk_combo_box_get_model (combo_box);
1773 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
1774 g_assert (GTK_IS_LIST_STORE (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_230
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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_230
= 1; else _g_boolean_var_230 = 0; _g_boolean_var_230; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1774, ((const char*) (__func__)), "GTK_IS_LIST_STORE (model)"
); } while (0)
;
1775
1776 if (!tree_model_entries_equal (model, 0, groups)) {
1777 int group_index;
1778
1779 /* Clear the contents of ComboBox in a wacky way because there
1780 * is no function to clear all items and also no function to obtain
1781 * the number of items in a combobox.
1782 */
1783 gtk_list_store_clear (store);
1784
1785 for (node = groups, group_index = 0; node != NULL((void*)0); node = node->next, ++group_index) {
1786 const char *group_name;
1787
1788 group_name = (const char *)node->data;
1789 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), group_name);
1790 }
1791 }
1792
1793 current_group_name = caja_file_get_group_name (file);
1794 current_group_index = tree_model_get_entry_index (model, 0, current_group_name);
1795
1796 /* If current group wasn't in list, we prepend it (with a separator).
1797 * This can happen if the current group is an id with no matching
1798 * group in the groups file.
1799 */
1800 if (current_group_index < 0 && current_group_name != NULL((void*)0)) {
1801 if (groups != NULL((void*)0)) {
1802 /* add separator */
1803 gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), "-");
1804 }
1805
1806 gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), current_group_name);
1807 current_group_index = 0;
1808 }
1809 gtk_combo_box_set_active (combo_box, current_group_index);
1810
1811 g_free (current_group_name);
1812 g_list_free_full (groups, g_free);
1813}
1814
1815static gboolean
1816combo_box_row_separator_func (GtkTreeModel *model,
1817 GtkTreeIter *iter,
1818 gpointer data)
1819{
1820 gchar *text;
1821 gboolean ret;
1822
1823 gtk_tree_model_get (model, iter, 0, &text, -1);
1824
1825 if (text == NULL((void*)0)) {
1826 return FALSE(0);
1827 }
1828
1829 if (strcmp (text, "-") == 0) {
1830 ret = TRUE(!(0));
1831 } else {
1832 ret = FALSE(0);
1833 }
1834
1835 g_free (text);
1836 return ret;
1837}
1838
1839static GtkComboBox *
1840attach_combo_box (GtkGrid *grid,
1841 GtkWidget *sibling,
1842 gboolean two_columns)
1843{
1844 GtkWidget *combo_box;
1845
1846 if (!two_columns) {
1847 combo_box = gtk_combo_box_text_new ();
1848 } else {
1849 GtkTreeModel *model;
1850 GtkCellRenderer *renderer;
1851
1852 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING))((((GtkTreeModel*) (void *) ((gtk_list_store_new (2, ((GType)
((16) << (2))), ((GType) ((16) << (2)))))))))
;
1853 combo_box = gtk_combo_box_new_with_model (model);
1854 g_object_unref (G_OBJECT (model)((((GObject*) (void *) ((model))))));
1855
1856 renderer = gtk_cell_renderer_text_new ();
1857 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box)((((GtkCellLayout*) (void *) ((combo_box))))), renderer, TRUE(!(0)));
1858 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo_box)((((GtkCellLayout*) (void *) ((combo_box))))), renderer,
1859 "text", 0);
1860
1861 }
1862
1863 gtk_widget_set_halign (combo_box, GTK_ALIGN_START);
1864
1865 gtk_widget_show (combo_box);
1866
1867 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box))))),
1868 combo_box_row_separator_func,
1869 NULL((void*)0),
1870 NULL((void*)0));
1871
1872 gtk_grid_attach_next_to (grid, combo_box, sibling,
1873 GTK_POS_RIGHT, 1, 1);
1874
1875 return GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box)))));
1876}
1877
1878static GtkComboBox*
1879attach_group_combo_box (GtkGrid *grid,
1880 GtkWidget *sibling,
1881 CajaFile *file)
1882{
1883 GtkComboBox *combo_box;
1884
1885 combo_box = attach_combo_box (grid, sibling, FALSE(0));
1886
1887 synch_groups_combo_box (combo_box, file);
1888
1889 /* Connect to signal to update menu when file changes. */
1890 g_signal_connect_object (file, "changed",
1891 G_CALLBACK (synch_groups_combo_box)((GCallback) (synch_groups_combo_box)),
1892 combo_box, G_CONNECT_SWAPPED);
1893 g_signal_connect_data (combo_box, "changed",
1894 G_CALLBACK (changed_group_callback)((GCallback) (changed_group_callback)),
1895 caja_file_ref (file),
1896 (GClosureNotify)caja_file_unref, 0);
1897
1898 return combo_box;
1899}
1900
1901static void
1902owner_change_callback (CajaFile *file,
1903 GFile *result_location,
1904 GError *error,
1905 FMPropertiesWindow *window)
1906{
1907 char *owner;
1908
1909 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_231 = 1; else _g_boolean_var_231 = 0; _g_boolean_var_231
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1909, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1910 g_assert (window->details->owner_change_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_232
; if (window->details->owner_change_file == file) _g_boolean_var_232
= 1; else _g_boolean_var_232 = 0; _g_boolean_var_232; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1910, ((const char*) (__func__)), "window->details->owner_change_file == file"
); } while (0)
;
1911
1912 owner = window->details->owner_change_owner;
1913 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_233
; if (owner != ((void*)0)) _g_boolean_var_233 = 1; else _g_boolean_var_233
= 0; _g_boolean_var_233; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1913, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1914
1915 /* Report the error if it's an error. */
1916 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
1917 fm_report_error_setting_owner (file, error, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1918
1919 caja_file_unref (file);
1920 g_free (owner);
1921
1922 window->details->owner_change_file = NULL((void*)0);
1923 window->details->owner_change_owner = NULL((void*)0);
1924 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1925}
1926
1927static void
1928cancel_owner_change_callback (FMPropertiesWindow *window)
1929{
1930 CajaFile *file;
1931 char *owner;
1932
1933 file = window->details->owner_change_file;
1934 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_234
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_234
= 1; else _g_boolean_var_234 = 0; _g_boolean_var_234; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1934, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1935
1936 owner = window->details->owner_change_owner;
1937 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_235
; if (owner != ((void*)0)) _g_boolean_var_235 = 1; else _g_boolean_var_235
= 0; _g_boolean_var_235; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1937, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1938
1939 caja_file_cancel (file, (CajaFileOperationCallback) owner_change_callback, window);
1940
1941 caja_file_unref (file);
1942 g_free (owner);
1943
1944 window->details->owner_change_file = NULL((void*)0);
1945 window->details->owner_change_owner = NULL((void*)0);
1946 g_object_unref (window);
1947}
1948
1949static gboolean
1950schedule_owner_change_timeout (FMPropertiesWindow *window)
1951{
1952 CajaFile *file;
1953 char *owner;
1954
1955 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_236
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_236 = 1; else _g_boolean_var_236 = 0; _g_boolean_var_236
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1955, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1956
1957 file = window->details->owner_change_file;
1958 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_237
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_237
= 1; else _g_boolean_var_237 = 0; _g_boolean_var_237; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1958, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1959
1960 owner = window->details->owner_change_owner;
1961 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_238
; if (owner != ((void*)0)) _g_boolean_var_238 = 1; else _g_boolean_var_238
= 0; _g_boolean_var_238; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1961, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1962
1963 eel_timed_wait_start
1964 ((EelCancelCallback) cancel_owner_change_callback,
1965 window,
1966 _("Cancel Owner Change?")dcgettext (((void*)0), "Cancel Owner Change?", 5),
1967 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1968
1969 caja_file_set_owner
1970 (file, owner,
1971 (CajaFileOperationCallback) owner_change_callback, window);
1972
1973 window->details->owner_change_timeout = 0;
1974 return FALSE(0);
1975}
1976
1977static void
1978schedule_owner_change (FMPropertiesWindow *window,
1979 CajaFile *file,
1980 const char *owner)
1981{
1982 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_239
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_239 = 1; else _g_boolean_var_239 = 0; _g_boolean_var_239
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1982, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1983 g_assert (window->details->owner_change_owner == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_240
; if (window->details->owner_change_owner == ((void*)0)
) _g_boolean_var_240 = 1; else _g_boolean_var_240 = 0; _g_boolean_var_240
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1983, ((const char*) (__func__)), "window->details->owner_change_owner == NULL"
); } while (0)
;
1984 g_assert (window->details->owner_change_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_241
; if (window->details->owner_change_file == ((void*)0))
_g_boolean_var_241 = 1; else _g_boolean_var_241 = 0; _g_boolean_var_241
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1984, ((const char*) (__func__)), "window->details->owner_change_file == NULL"
); } while (0)
;
1985 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_242
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_242
= 1; else _g_boolean_var_242 = 0; _g_boolean_var_242; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1985, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1986
1987 window->details->owner_change_file = caja_file_ref (file);
1988 window->details->owner_change_owner = g_strdup (owner)g_strdup_inline (owner);
1989 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) ((window))))))) (g_object_ref
) (((((GObject*) (void *) ((window)))))))
;
1990 window->details->owner_change_timeout =
1991 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1992 (GSourceFunc) schedule_owner_change_timeout,
1993 window);
1994}
1995
1996static void
1997unschedule_or_cancel_owner_change (FMPropertiesWindow *window)
1998{
1999 CajaFile *file;
2000 char *owner;
2001
2002 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_243
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_243 = 1; else _g_boolean_var_243 = 0; _g_boolean_var_243
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2002, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2003
2004 file = window->details->owner_change_file;
2005 owner = window->details->owner_change_owner;
2006
2007 g_assert ((file == NULL && owner == NULL) ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if ((file == ((void*)0) && owner == ((void*)0)) || (
file != ((void*)0) && owner != ((void*)0))) _g_boolean_var_244
= 1; else _g_boolean_var_244 = 0; _g_boolean_var_244; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2008, ((const char*) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
2008 (file != NULL && owner != NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if ((file == ((void*)0) && owner == ((void*)0)) || (
file != ((void*)0) && owner != ((void*)0))) _g_boolean_var_244
= 1; else _g_boolean_var_244 = 0; _g_boolean_var_244; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2008, ((const char*) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
;
2009
2010 if (file != NULL((void*)0)) {
2011 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_245
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_245
= 1; else _g_boolean_var_245 = 0; _g_boolean_var_245; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2011, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2012
2013 if (window->details->owner_change_timeout == 0) {
2014 caja_file_cancel (file,
2015 (CajaFileOperationCallback) owner_change_callback, window);
2016 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
2017 }
2018
2019 caja_file_unref (file);
2020 g_free (owner);
2021
2022 window->details->owner_change_file = NULL((void*)0);
2023 window->details->owner_change_owner = NULL((void*)0);
2024 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
2025 }
2026
2027 if (window->details->owner_change_timeout > 0) {
2028 g_assert (file != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_246
; if (file != ((void*)0)) _g_boolean_var_246 = 1; else _g_boolean_var_246
= 0; _g_boolean_var_246; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2028, ((const char*
) (__func__)), "file != NULL"); } while (0)
;
2029 g_source_remove (window->details->owner_change_timeout);
2030 window->details->owner_change_timeout = 0;
2031 }
2032}
2033
2034static void
2035changed_owner_callback (GtkComboBox *combo_box, CajaFile* file)
2036{
2037 char *owner_text;
2038 char **name_array;
2039 char *new_owner;
2040 char *cur_owner;
2041
2042 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_247
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2042, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2043 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_248
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_248
= 1; else _g_boolean_var_248 = 0; _g_boolean_var_248; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2043, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2044
2045 owner_text = combo_box_get_active_entry (combo_box, 0);
2046 if (! owner_text)
2047 return;
2048 name_array = g_strsplit (owner_text, " - ", 2);
2049 new_owner = name_array[0];
2050 g_free (owner_text);
2051 cur_owner = caja_file_get_owner_name (file);
2052
2053 if (strcmp (new_owner, cur_owner) != 0) {
2054 FMPropertiesWindow *window;
2055
2056 /* Try to change file owner. If this fails, complain to user. */
2057 window = FM_PROPERTIES_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (combo_box), GTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) ((gtk_widget_get_ancestor (
((((GtkWidget*) (void *) ((combo_box))))), (gtk_window_get_type
())))))))
;
2058
2059 unschedule_or_cancel_owner_change (window);
2060 schedule_owner_change (window, file, new_owner);
2061 }
2062 g_strfreev (name_array);
2063 g_free (cur_owner);
2064}
2065
2066static void
2067synch_user_menu (GtkComboBox *combo_box, CajaFile *file)
2068{
2069 GList *users;
2070 GList *node;
2071 GtkTreeModel *model;
2072 GtkListStore *store;
2073 GtkTreeIter iter;
2074 char *user_name;
2075 char *owner_name;
2076 int owner_index;
2077 char **name_array;
2078
2079 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_249
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_249
= 1; else _g_boolean_var_249 = 0; _g_boolean_var_249; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2079, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2080 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_250
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_250
= 1; else _g_boolean_var_250 = 0; _g_boolean_var_250; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2080, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2081
2082 if (caja_file_is_gone (file)) {
2083 return;
2084 }
2085
2086 users = caja_get_user_names ();
2087
2088 model = gtk_combo_box_get_model (combo_box);
2089 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
2090 g_assert (GTK_IS_LIST_STORE (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_251
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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_251
= 1; else _g_boolean_var_251 = 0; _g_boolean_var_251; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2090, ((const char*) (__func__)), "GTK_IS_LIST_STORE (model)"
); } while (0)
;
2091
2092 if (!tree_model_entries_equal (model, 1, users)) {
2093 int user_index;
2094
2095 /* Clear the contents of ComboBox in a wacky way because there
2096 * is no function to clear all items and also no function to obtain
2097 * the number of items in a combobox.
2098 */
2099 gtk_list_store_clear (store);
2100
2101 for (node = users, user_index = 0; node != NULL((void*)0); node = node->next, ++user_index) {
2102 char *combo_text;
2103
2104 user_name = (char *)node->data;
2105
2106 name_array = g_strsplit (user_name, "\n", 2);
2107 if (name_array[1] != NULL((void*)0)) {
2108 combo_text = g_strdup_printf ("%s - %s", name_array[0], name_array[1]);
2109 } else {
2110 combo_text = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2111 }
2112
2113 gtk_list_store_append (store, &iter);
2114 gtk_list_store_set (store, &iter,
2115 0, combo_text,
2116 1, user_name,
2117 -1);
2118
2119 g_strfreev (name_array);
2120 g_free (combo_text);
2121 }
2122 }
2123
2124 owner_name = caja_file_get_string_attribute (file, "owner");
2125 owner_index = tree_model_get_entry_index (model, 0, owner_name);
2126
2127 /* If owner wasn't in list, we prepend it (with a separator).
2128 * This can happen if the owner is an id with no matching
2129 * identifier in the passwords file.
2130 */
2131 if (owner_index < 0 && owner_name != NULL((void*)0)) {
2132 if (users != NULL((void*)0)) {
2133 /* add separator */
2134 gtk_list_store_prepend (store, &iter);
2135 gtk_list_store_set (store, &iter,
2136 0, "-",
2137 1, NULL((void*)0),
2138 -1);
2139 }
2140
2141 name_array = g_strsplit (owner_name, " - ", 2);
2142 if (name_array[1] != NULL((void*)0)) {
2143 user_name = g_strdup_printf ("%s\n%s", name_array[0], name_array[1]);
2144 } else {
2145 user_name = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2146 }
2147 owner_index = 0;
2148
2149 gtk_list_store_prepend (store, &iter);
2150 gtk_list_store_set (store, &iter,
2151 0, owner_name,
2152 1, user_name,
2153 -1);
2154
2155 g_free (user_name);
2156 g_strfreev (name_array);
2157 }
2158
2159 gtk_combo_box_set_active (combo_box, owner_index);
2160
2161 g_free (owner_name);
2162 g_list_free_full (users, g_free);
2163}
2164
2165static GtkComboBox*
2166attach_owner_combo_box (GtkGrid *grid,
2167 GtkWidget *sibling,
2168 CajaFile *file)
2169{
2170 GtkComboBox *combo_box;
2171
2172 combo_box = attach_combo_box (grid, sibling, TRUE(!(0)));
2173
2174 synch_user_menu (combo_box, file);
2175
2176 /* Connect to signal to update menu when file changes. */
2177 g_signal_connect_object (file, "changed",
2178 G_CALLBACK (synch_user_menu)((GCallback) (synch_user_menu)),
2179 combo_box, G_CONNECT_SWAPPED);
2180 g_signal_connect_data (combo_box, "changed",
2181 G_CALLBACK (changed_owner_callback)((GCallback) (changed_owner_callback)),
2182 caja_file_ref (file),
2183 (GClosureNotify)caja_file_unref, 0);
2184
2185 return combo_box;
2186}
2187
2188static gboolean
2189file_has_prefix (CajaFile *file,
2190 GList *prefix_candidates)
2191{
2192 GList *p;
2193 GFile *location, *candidate_location;
2194
2195 location = caja_file_get_location (file);
2196
2197 for (p = prefix_candidates; p != NULL((void*)0); p = p->next) {
2198 if (file == p->data) {
2199 continue;
2200 }
2201
2202 candidate_location = caja_file_get_location (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
2203 if (g_file_has_prefix (location, candidate_location)) {
2204 g_object_unref (location);
2205 g_object_unref (candidate_location);
2206 return TRUE(!(0));
2207 }
2208 g_object_unref (candidate_location);
2209 }
2210
2211 g_object_unref (location);
2212
2213 return FALSE(0);
2214}
2215
2216static void
2217directory_contents_value_field_update (FMPropertiesWindow *window)
2218{
2219 CajaRequestStatus file_status, status;
2220 char *text, *temp;
2221 guint directory_count;
2222 guint file_count;
2223 guint total_count;
2224 guint unreadable_directory_count;
2225 goffset total_size;
2226 goffset total_size_on_disk;
2227 gboolean used_two_lines;
2228 GList *l;
2229 guint file_unreadable;
2230 goffset file_size;
2231 goffset file_size_on_disk;
2232 CajaFile *file = NULL((void*)0);
2233
2234 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_252
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_252 = 1; else _g_boolean_var_252 = 0; _g_boolean_var_252
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2234, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2235
2236 status = CAJA_REQUEST_DONE;
2237 file_status = CAJA_REQUEST_NOT_STARTED;
2238 total_count = window->details->total_count;
2239 total_size = window->details->total_size;
2240 total_size_on_disk = window->details->total_size_on_disk;
2241 unreadable_directory_count = FALSE(0);
2242
2243 for (l = window->details->target_files; l; l = l->next) {
2244 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
2245
2246 if (file_has_prefix (file, window->details->target_files)) {
2247 /* don't count nested files twice */
2248 continue;
2249 }
2250
2251 if (caja_file_is_directory (file)) {
2252 file_status = caja_file_get_deep_counts (file,
2253 &directory_count,
2254 &file_count,
2255 &file_unreadable,
2256 &file_size,
2257 &file_size_on_disk,
2258 TRUE(!(0)));
2259 total_count += (file_count + directory_count);
2260 total_size += file_size;
2261 total_size_on_disk += file_size_on_disk;
2262
2263 if (file_unreadable) {
2264 unreadable_directory_count = TRUE(!(0));
2265 }
2266
2267 if (file_status != CAJA_REQUEST_DONE) {
2268 status = file_status;
2269 }
2270 } else {
2271 ++total_count;
2272 total_size += caja_file_get_size (file);
2273 total_size_on_disk += caja_file_get_size_on_disk (file);
2274 }
2275 }
2276
2277 /* If we've already displayed the total once, don't do another visible
2278 * count-up if the deep_count happens to get invalidated.
2279 * But still display the new total, since it might have changed.
2280 */
2281 if (window->details->deep_count_finished &&
2282 status != CAJA_REQUEST_DONE) {
2283 return;
2284 }
2285
2286 text = NULL((void*)0);
2287 used_two_lines = FALSE(0);
2288
2289 if (total_count == 0) {
2290 switch (status) {
2291 case CAJA_REQUEST_DONE:
2292 if (unreadable_directory_count == 0) {
2293 text = g_strdup (_("nothing"))g_strdup_inline (dcgettext (((void*)0), "nothing", 5));
2294 } else {
2295 text = g_strdup (_("unreadable"))g_strdup_inline (dcgettext (((void*)0), "unreadable", 5));
2296 }
2297
2298 break;
2299 default:
2300 text = g_strdup ("...")g_strdup_inline ("...");
2301 }
2302 } else {
2303 char *size_str;
2304 char *size_on_disk_str;
2305
2306 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
2307 size_str = g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
2308 size_on_disk_str = g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
2309 } else {
2310 size_str = g_format_size (total_size);
2311 size_on_disk_str = g_format_size (total_size_on_disk);
2312 }
2313
2314 text = g_strdup_printf (ngettext("%'d item, with size %s (%s on disk)",dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
2315 "%'d items, totalling %s (%s on disk)",dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
2316 total_count)dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
,
2317 total_count, size_str, size_on_disk_str);
2318 g_free (size_str);
2319 g_free (size_on_disk_str);
2320
2321 if (unreadable_directory_count != 0) {
2322 temp = text;
2323 text = g_strconcat (temp, "\n",
2324 _("(some contents unreadable)")dcgettext (((void*)0), "(some contents unreadable)", 5),
2325 NULL((void*)0));
2326 g_free (temp);
2327 used_two_lines = TRUE(!(0));
2328 }
2329 }
2330
2331 gtk_label_set_text (window->details->directory_contents_value_field,
2332 text);
2333 g_free (text);
2334
2335 /* Also set the title field here, with a trailing carriage return &
2336 * space if the value field has two lines. This is a hack to get the
2337 * "Contents:" title to line up with the first line of the
2338 * 2-line value. Maybe there's a better way to do this, but I
2339 * couldn't think of one.
2340 */
2341 text = g_strdup (_("Contents:"))g_strdup_inline (dcgettext (((void*)0), "Contents:", 5));
2342 if (used_two_lines) {
2343 temp = text;
2344 text = g_strconcat (temp, "\n ", NULL((void*)0));
2345 g_free (temp);
2346 }
2347 gtk_label_set_text (window->details->directory_contents_title_field,
2348 text);
2349 g_free (text);
2350
2351 if (status == CAJA_REQUEST_DONE) {
2352 window->details->deep_count_finished = TRUE(!(0));
2353 }
2354}
2355
2356static gboolean
2357update_directory_contents_callback (gpointer data)
2358{
2359 FMPropertiesWindow *window;
2360
2361 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2362
2363 window->details->update_directory_contents_timeout_id = 0;
2364 directory_contents_value_field_update (window);
2365
2366 return FALSE(0);
2367}
2368
2369static void
2370schedule_directory_contents_update (FMPropertiesWindow *window)
2371{
2372 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_253
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_253 = 1; else _g_boolean_var_253 = 0; _g_boolean_var_253
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2372, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2373
2374 if (window->details->update_directory_contents_timeout_id == 0) {
2375 window->details->update_directory_contents_timeout_id
2376 = g_timeout_add (DIRECTORY_CONTENTS_UPDATE_INTERVAL200,
2377 update_directory_contents_callback,
2378 window);
2379 }
2380}
2381
2382static GtkLabel *
2383attach_directory_contents_value_field (FMPropertiesWindow *window,
2384 GtkGrid *grid,
2385 GtkWidget *sibling)
2386{
2387 GtkLabel *value_field;
2388 GList *l;
2389 CajaFile *file = NULL((void*)0);
2390
2391 value_field = attach_value_label (grid, sibling, "");
2392
2393 g_assert (window->details->directory_contents_value_field == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_254
; if (window->details->directory_contents_value_field ==
((void*)0)) _g_boolean_var_254 = 1; else _g_boolean_var_254 =
0; _g_boolean_var_254; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2393, ((const char*
) (__func__)), "window->details->directory_contents_value_field == NULL"
); } while (0)
;
2394 window->details->directory_contents_value_field = value_field;
2395
2396 gtk_label_set_line_wrap (value_field, TRUE(!(0)));
2397
2398 /* Fill in the initial value. */
2399 directory_contents_value_field_update (window);
2400
2401 for (l = window->details->target_files; l; l = l->next) {
2402 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
2403 caja_file_recompute_deep_counts (file);
2404
2405 g_signal_connect_object (file,
2406 "updated_deep_count_in_progress",
2407 G_CALLBACK (schedule_directory_contents_update)((GCallback) (schedule_directory_contents_update)),
2408 window, G_CONNECT_SWAPPED);
2409 }
2410
2411 return value_field;
2412}
2413
2414static GtkLabel *
2415attach_title_field (GtkGrid *grid,
2416 const char *title)
2417{
2418 return attach_label (grid, NULL((void*)0), title, FALSE(0), FALSE(0), TRUE(!(0)));
2419}
2420
2421
2422
2423#define INCONSISTENT_STATE_STRING"\xE2\x80\x92" \
2424 "\xE2\x80\x92"
2425
2426static void
2427append_title_value_pair (FMPropertiesWindow *window,
2428 GtkGrid *grid,
2429 const char *title,
2430 const char *file_attribute_name,
2431 const char *inconsistent_state,
2432 gboolean show_original)
2433{
2434 GtkLabel *title_label;
2435 GtkWidget *value;
2436
2437 title_label = attach_title_field (grid, title);
2438 value = attach_value_field (window, grid, GTK_WIDGET (title_label)((((GtkWidget*) (void *) ((title_label))))),
2439 file_attribute_name,
2440 inconsistent_state,
2441 show_original);
2442 gtk_label_set_mnemonic_widget (title_label, value);
2443}
2444
2445static void
2446append_title_and_ellipsizing_value (FMPropertiesWindow *window,
2447 GtkGrid *grid,
2448 const char *title,
2449 const char *file_attribute_name,
2450 const char *inconsistent_state,
2451 gboolean show_original)
2452{
2453 GtkLabel *title_label;
2454 GtkWidget *value;
2455
2456 title_label = attach_title_field (grid, title);
2457 value = attach_ellipsizing_value_field (window, grid,
2458 GTK_WIDGET (title_label)((((GtkWidget*) (void *) ((title_label))))),
2459 file_attribute_name,
2460 inconsistent_state,
2461 show_original);
2462 gtk_label_set_mnemonic_widget (title_label, value);
2463}
2464
2465static void
2466append_directory_contents_fields (FMPropertiesWindow *window,
2467 GtkGrid *grid)
2468{
2469 GtkLabel *title_field, *value_field;
2470 title_field = attach_title_field (grid, "");
2471 window->details->directory_contents_title_field = title_field;
2472 gtk_label_set_line_wrap (title_field, TRUE(!(0)));
2473
2474 value_field = attach_directory_contents_value_field
2475 (window, grid, GTK_WIDGET (title_field)((((GtkWidget*) (void *) ((title_field))))));
2476
2477 gtk_label_set_mnemonic_widget (title_field, GTK_WIDGET(value_field)((((GtkWidget*) (void *) ((value_field))))));
2478}
2479
2480static GtkWidget *
2481create_page_with_hbox (GtkNotebook *notebook,
2482 const char *title)
2483{
2484 GtkWidget *hbox;
2485
2486 g_assert (GTK_IS_NOTEBOOK (notebook))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_255
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((gtk_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; }))))) _g_boolean_var_255
= 1; else _g_boolean_var_255 = 0; _g_boolean_var_255; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2486, ((const char*) (__func__)), "GTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2487 g_assert (title != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_256
; if (title != ((void*)0)) _g_boolean_var_256 = 1; else _g_boolean_var_256
= 0; _g_boolean_var_256; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2487, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2488
2489 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2490 gtk_widget_show (hbox);
2491 gtk_container_set_border_width (GTK_CONTAINER (hbox)((((GtkContainer*) (void *) ((hbox))))), 12);
2492 gtk_box_set_spacing (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), 12);
2493 gtk_notebook_append_page (notebook, hbox, gtk_label_new (title));
2494
2495 return hbox;
2496}
2497
2498static GtkWidget *
2499create_page_with_vbox (GtkNotebook *notebook,
2500 const char *title)
2501{
2502 GtkWidget *vbox;
2503
2504 g_assert (GTK_IS_NOTEBOOK (notebook))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_257
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((gtk_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; }))))) _g_boolean_var_257
= 1; else _g_boolean_var_257 = 0; _g_boolean_var_257; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2504, ((const char*) (__func__)), "GTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2505 g_assert (title != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_258
; if (title != ((void*)0)) _g_boolean_var_258 = 1; else _g_boolean_var_258
= 0; _g_boolean_var_258; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2505, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2506
2507 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2508 gtk_widget_show (vbox);
2509
2510 gtk_container_set_border_width (GTK_CONTAINER (vbox)((((GtkContainer*) (void *) ((vbox))))), 12);
2511 gtk_notebook_append_page (notebook, vbox, gtk_label_new (title));
2512
2513 return vbox;
2514}
2515
2516static GtkWidget *
2517append_blank_row (GtkGrid *grid)
2518{
2519 return GTK_WIDGET (attach_title_field (grid, ""))((((GtkWidget*) (void *) ((attach_title_field (grid, ""))))));
2520}
2521
2522static void
2523append_blank_slim_row (GtkGrid *grid)
2524{
2525 GtkWidget *w;
2526 PangoAttribute *attribute;
2527 PangoAttrList *attr_list;
2528
2529 attr_list = pango_attr_list_new ();
2530 attribute = pango_attr_scale_new (0.30);
2531 pango_attr_list_insert (attr_list, attribute);
2532
2533 w = gtk_label_new (NULL((void*)0));
2534 gtk_label_set_attributes (GTK_LABEL (w)((((GtkLabel*) (void *) ((w))))), attr_list);
2535 gtk_widget_show (w);
2536
2537 pango_attr_list_unref (attr_list);
2538
2539 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), w);
2540}
2541
2542static GtkWidget *
2543create_grid_with_standard_properties (void)
2544{
2545 GtkWidget *grid;
2546
2547 grid = gtk_grid_new ();
2548 gtk_container_set_border_width (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), 6);
2549 gtk_grid_set_row_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), ROW_PAD6);
2550 gtk_grid_set_column_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), 12);
2551 gtk_orientable_set_orientation (GTK_ORIENTABLE (grid)((((GtkOrientable*) (void *) ((grid))))), GTK_ORIENTATION_VERTICAL);
2552 gtk_widget_show (grid);
2553
2554 return grid;
2555}
2556
2557static gboolean
2558is_merged_trash_directory (CajaFile *file)
2559{
2560 char *file_uri;
2561 gboolean result;
2562
2563 file_uri = caja_file_get_uri (file);
2564 result = strcmp (file_uri, "trash:///") == 0;
2565 g_free (file_uri);
2566
2567 return result;
2568}
2569
2570static gboolean
2571is_computer_directory (CajaFile *file)
2572{
2573 char *file_uri;
2574 gboolean result;
2575
2576 file_uri = caja_file_get_uri (file);
2577 result = strcmp (file_uri, "computer:///") == 0;
2578 g_free (file_uri);
2579
2580 return result;
2581}
2582
2583static gboolean
2584is_network_directory (CajaFile *file)
2585{
2586 char *file_uri;
2587 gboolean result;
2588
2589 file_uri = caja_file_get_uri (file);
2590 result = strcmp (file_uri, "network:///") == 0;
2591 g_free (file_uri);
2592
2593 return result;
2594}
2595
2596static gboolean
2597is_burn_directory (CajaFile *file)
2598{
2599 char *file_uri;
2600 gboolean result;
2601
2602 file_uri = caja_file_get_uri (file);
2603 result = strcmp (file_uri, "burn:///") == 0;
2604 g_free (file_uri);
2605
2606 return result;
2607}
2608
2609static gboolean
2610should_show_custom_icon_buttons (FMPropertiesWindow *window)
2611{
2612 if (is_multi_file_window (window)) {
2613 return FALSE(0);
2614 }
2615
2616 return TRUE(!(0));
2617}
2618
2619static gboolean
2620should_show_file_type (FMPropertiesWindow *window)
2621{
2622 if (!is_multi_file_window (window)
2623 && (is_merged_trash_directory (get_target_file (window)) ||
2624 is_computer_directory (get_target_file (window)) ||
2625 is_network_directory (get_target_file (window)) ||
2626 is_burn_directory (get_target_file (window)))) {
2627 return FALSE(0);
2628 }
2629
2630
2631 return TRUE(!(0));
2632}
2633
2634static gboolean
2635should_show_location_info (FMPropertiesWindow *window)
2636{
2637 if (!is_multi_file_window (window)
2638 && (is_merged_trash_directory (get_target_file (window)) ||
2639 is_computer_directory (get_target_file (window)) ||
2640 is_network_directory (get_target_file (window)) ||
2641 is_burn_directory (get_target_file (window)))) {
2642 return FALSE(0);
2643 }
2644
2645 return TRUE(!(0));
2646}
2647
2648static gboolean
2649should_show_accessed_date (FMPropertiesWindow *window)
2650{
2651 /* Accessed date for directory seems useless. If we some
2652 * day decide that it is useful, we should separately
2653 * consider whether it's useful for "trash:".
2654 */
2655 if (file_list_all_directories (window->details->target_files)
2656 || is_multi_file_window (window))
2657 {
2658 return FALSE(0);
2659 }
2660
2661 return TRUE(!(0));
2662}
2663
2664static gboolean
2665should_show_modified_date (FMPropertiesWindow *window)
2666{
2667 CajaFile *file;
2668
2669 if (is_multi_file_window (window))
2670 return FALSE(0);
2671
2672 file = get_original_file (window);
2673 if ((file != NULL((void*)0)) && caja_file_can_unmount (file))
2674 return FALSE(0);
2675
2676 return TRUE(!(0));
2677}
2678
2679static gboolean
2680should_show_link_target (FMPropertiesWindow *window)
2681{
2682 if (!is_multi_file_window (window)
2683 && caja_file_is_symbolic_link (get_target_file (window))) {
2684 return TRUE(!(0));
2685 }
2686
2687 return FALSE(0);
2688}
2689
2690static gboolean
2691should_show_free_space (FMPropertiesWindow *window)
2692{
2693
2694 if (!is_multi_file_window (window)
2695 && (is_merged_trash_directory (get_target_file (window)) ||
2696 is_computer_directory (get_target_file (window)) ||
2697 is_network_directory (get_target_file (window)) ||
2698 is_burn_directory (get_target_file (window)))) {
2699 return FALSE(0);
2700 }
2701
2702 if (file_list_all_directories (window->details->target_files)) {
2703 return TRUE(!(0));
2704 }
2705
2706 return FALSE(0);
2707}
2708
2709static gboolean
2710should_show_volume_usage (FMPropertiesWindow *window)
2711{
2712 CajaFile *file;
2713 gboolean success = FALSE(0);
2714
2715 if (is_multi_file_window (window)) {
2716 return FALSE(0);
2717 }
2718
2719 file = get_original_file (window);
2720
2721 if (file == NULL((void*)0)) {
2722 return FALSE(0);
2723 }
2724
2725 if (caja_file_can_unmount (file)) {
2726 return TRUE(!(0));
2727 }
2728
2729#ifdef TODO_GIO
2730 /* Look at is_mountpoint for activation uri */
2731#endif
2732 return success;
2733}
2734
2735static void
2736paint_used_legend (GtkWidget *widget,
2737 cairo_t *cr,
2738 gpointer data)
2739{
2740 FMPropertiesWindow *window;
2741 gint width, height;
2742 GtkAllocation allocation;
2743
2744 gtk_widget_get_allocation (widget, &allocation);
2745
2746 width = allocation.width;
2747 height = allocation.height;
2748
2749 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2750
2751 cairo_rectangle (cr,
2752 2,
2753 2,
2754 width - 4,
2755 height - 4);
2756
2757 gdk_cairo_set_source_rgba (cr, &window->details->used_color);
2758 cairo_fill_preserve (cr);
2759
2760 gdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2761 cairo_stroke (cr);
2762}
2763
2764static void
2765paint_free_legend (GtkWidget *widget,
2766 cairo_t *cr, gpointer data)
2767{
2768 FMPropertiesWindow *window;
2769 gint width, height;
2770 GtkAllocation allocation;
2771
2772 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2773 gtk_widget_get_allocation (widget, &allocation);
2774
2775 width = allocation.width;
2776 height = allocation.height;
2777
2778 cairo_rectangle (cr,
2779 2,
2780 2,
2781 width - 4,
2782 height - 4);
2783
2784 gdk_cairo_set_source_rgba (cr, &window->details->free_color);
2785 cairo_fill_preserve(cr);
2786
2787 gdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2788 cairo_stroke (cr);
2789}
2790
2791static void
2792paint_pie_chart (GtkWidget *widget,
2793 cairo_t *cr,
2794 gpointer data)
2795{
2796
2797 FMPropertiesWindow *window;
2798 gint width, height;
2799 double free, used;
2800 double angle1, angle2, split, xc, yc, radius;
2801 GtkAllocation allocation;
2802
2803 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2804 gtk_widget_get_allocation (widget, &allocation);
2805
2806 width = allocation.width;
2807 height = allocation.height;
2808
2809
2810 free = (double)window->details->volume_free / (double)window->details->volume_capacity;
2811 used = 1.0 - free;
2812
2813 angle1 = free * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2814 angle2 = used * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2815 split = (2 * G_PI3.1415926535897932384626433832795028841971693993751 - angle1) * .5;
2816 xc = width / 2;
2817 yc = height / 2;
2818
2819 if (width < height) {
2820 radius = width / 2 - 8;
2821 } else {
2822 radius = height / 2 - 8;
2823 }
2824
2825 if (angle1 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle1 != 0) {
2826 angle1 = angle1 + split;
2827 }
2828
2829 if (angle2 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle2 != 0) {
2830 angle2 = angle2 - split;
2831 }
2832
2833 if (used > 0) {
2834 if (free != 0) {
2835 cairo_move_to (cr,xc,yc);
2836 }
2837
2838 cairo_arc (cr, xc, yc, radius, angle1, angle2);
2839
2840 if (free != 0) {
2841 cairo_line_to (cr,xc,yc);
2842 }
2843
2844 gdk_cairo_set_source_rgba (cr, &window->details->used_color);
2845 cairo_fill_preserve (cr);
2846
2847 gdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2848
2849 cairo_stroke (cr);
2850 }
2851
2852 if (free > 0) {
2853 if (used != 0) {
2854 cairo_move_to (cr,xc,yc);
2855 }
2856
2857 cairo_arc_negative (cr, xc, yc, radius, angle1, angle2);
2858
2859 if (used != 0) {
2860 cairo_line_to (cr,xc,yc);
2861 }
2862
2863
2864 gdk_cairo_set_source_rgba (cr, &window->details->free_color);
2865 cairo_fill_preserve(cr);
2866
2867 gdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2868
2869 cairo_stroke (cr);
2870 }
2871}
2872
2873
2874/* Copied from gtk/gtkstyle.c */
2875
2876static void
2877rgb_to_hls (gdouble *r,
2878 gdouble *g,
2879 gdouble *b)
2880{
2881 gdouble min;
2882 gdouble max;
2883 gdouble red;
2884 gdouble green;
2885 gdouble blue;
2886 gdouble h, l, s;
2887 gdouble delta;
2888
2889 red = *r;
2890 green = *g;
2891 blue = *b;
2892
2893 if (red > green)
2894 {
2895 if (red > blue)
2896 max = red;
2897 else
2898 max = blue;
2899
2900 if (green < blue)
2901 min = green;
2902 else
2903 min = blue;
2904 }
2905 else
2906 {
2907 if (green > blue)
2908 max = green;
2909 else
2910 max = blue;
2911
2912 if (red < blue)
2913 min = red;
2914 else
2915 min = blue;
2916 }
2917
2918 l = (max + min) / 2;
2919 s = 0;
2920 h = 0;
2921
2922 if (max != min)
2923 {
2924 if (l <= 0.5)
2925 s = (max - min) / (max + min);
2926 else
2927 s = (max - min) / (2 - max - min);
2928
2929 delta = max -min;
2930 if (red == max)
2931 h = (green - blue) / delta;
2932 else if (green == max)
2933 h = 2 + (blue - red) / delta;
2934 else if (blue == max)
2935 h = 4 + (red - green) / delta;
2936
2937 h *= 60;
2938 if (h < 0.0)
2939 h += 360;
2940 }
2941
2942 *r = h;
2943 *g = l;
2944 *b = s;
2945}
2946
2947static void
2948hls_to_rgb (gdouble *h,
2949 gdouble *l,
2950 gdouble *s)
2951{
2952 gdouble hue;
2953 gdouble lightness;
2954 gdouble saturation;
2955 gdouble m1, m2;
2956 gdouble r, g, b;
2957
2958 lightness = *l;
2959 saturation = *s;
2960
2961 if (lightness <= 0.5)
2962 m2 = lightness * (1 + saturation);
2963 else
2964 m2 = lightness + saturation - lightness * saturation;
2965 m1 = 2 * lightness - m2;
2966
2967 if (saturation == 0)
2968 {
2969 *h = lightness;
2970 *l = lightness;
2971 *s = lightness;
2972 }
2973 else
2974 {
2975 hue = *h + 120;
2976 while (hue > 360)
2977 hue -= 360;
2978 while (hue < 0)
2979 hue += 360;
2980
2981 if (hue < 60)
2982 r = m1 + (m2 - m1) * hue / 60;
2983 else if (hue < 180)
2984 r = m2;
2985 else if (hue < 240)
2986 r = m1 + (m2 - m1) * (240 - hue) / 60;
2987 else
2988 r = m1;
2989
2990 hue = *h;
2991 while (hue > 360)
2992 hue -= 360;
2993 while (hue < 0)
2994 hue += 360;
2995
2996 if (hue < 60)
2997 g = m1 + (m2 - m1) * hue / 60;
2998 else if (hue < 180)
2999 g = m2;
3000 else if (hue < 240)
3001 g = m1 + (m2 - m1) * (240 - hue) / 60;
3002 else
3003 g = m1;
3004
3005 hue = *h - 120;
3006 while (hue > 360)
3007 hue -= 360;
3008 while (hue < 0)
3009 hue += 360;
3010
3011 if (hue < 60)
3012 b = m1 + (m2 - m1) * hue / 60;
3013 else if (hue < 180)
3014 b = m2;
3015 else if (hue < 240)
3016 b = m1 + (m2 - m1) * (240 - hue) / 60;
3017 else
3018 b = m1;
3019
3020 *h = r;
3021 *l = g;
3022 *s = b;
3023 }
3024}
3025static void
3026_pie_style_shade (GdkRGBA *a,
3027 GdkRGBA *b,
3028 gdouble k)
3029{
3030 gdouble red;
3031 gdouble green;
3032 gdouble blue;
3033
3034 red = a->red;
3035 green = a->green;
3036 blue = a->blue;
3037
3038 rgb_to_hls (&red, &green, &blue);
3039
3040 green *= k;
3041 if (green > 1.0)
3042 green = 1.0;
3043 else if (green < 0.0)
3044 green = 0.0;
3045
3046 blue *= k;
3047 if (blue > 1.0)
3048 blue = 1.0;
3049 else if (blue < 0.0)
3050 blue = 0.0;
3051
3052 hls_to_rgb (&red, &green, &blue);
3053
3054 b->red = red;
3055 b->green = green;
3056 b->blue = blue;
3057 b->alpha = a->alpha;
3058}
3059
3060
3061static GtkWidget*
3062create_pie_widget (FMPropertiesWindow *window)
3063{
3064 CajaFile *file;
3065 GtkGrid *grid;
3066 GtkStyleContext *style;
3067
3068 GtkWidget *pie_canvas;
3069 GtkWidget *used_canvas;
3070 GtkWidget *used_label;
3071 GtkWidget *free_canvas;
3072 GtkWidget *free_label;
3073 GtkWidget *capacity_label;
3074 GtkWidget *fstype_label;
3075 gchar *capacity;
3076 gchar *used;
3077 gchar *free;
3078 gchar *uri;
3079 gchar *concat;
3080 GFile *location;
3081 GFileInfo *info;
3082
3083 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
3084 capacity = g_format_size_full(window->details->volume_capacity, G_FORMAT_SIZE_IEC_UNITS);
3085 free = g_format_size_full(window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3086 used = g_format_size_full(window->details->volume_capacity - window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3087 }
3088 else {
3089 capacity = g_format_size(window->details->volume_capacity);
3090 free = g_format_size(window->details->volume_free);
3091 used = g_format_size(window->details->volume_capacity - window->details->volume_free);
3092 }
3093
3094 file = get_original_file (window);
3095
3096 uri = caja_file_get_activation_uri (file);
3097
3098 grid = GTK_GRID (gtk_grid_new ())((((GtkGrid*) (void *) ((gtk_grid_new ())))));
3099 gtk_container_set_border_width (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), 5);
3100 gtk_grid_set_column_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), 5);
3101 style = gtk_widget_get_style_context (GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid))))));
3102
3103 if (!gtk_style_context_lookup_color (style, "chart_rgba_1", &window->details->used_color)) {
3104
3105 window->details->used_color.red = USED_FILL_R0.988235294;
3106 window->details->used_color.green = USED_FILL_G0.91372549;
3107 window->details->used_color.blue = USED_FILL_B0.309803922;
3108 window->details->used_color.alpha = 1;
3109
3110 }
3111
3112
3113 if (!gtk_style_context_lookup_color (style, "chart_rgba_2", &window->details->free_color)) {
3114 window->details->free_color.red = FREE_FILL_R0.447058824;
3115 window->details->free_color.green = FREE_FILL_G0.623529412;
3116 window->details->free_color.blue = FREE_FILL_B0.811764706;
3117 window->details->free_color.alpha = 1;
3118
3119 }
3120
3121 _pie_style_shade (&window->details->used_color, &window->details->used_stroke_color, 0.7);
3122 _pie_style_shade (&window->details->free_color, &window->details->free_stroke_color, 0.7);
3123
3124 pie_canvas = gtk_drawing_area_new ();
3125 gtk_widget_set_size_request (pie_canvas, 200, 200);
3126
3127 used_canvas = gtk_drawing_area_new ();
3128
3129 gtk_widget_set_valign (used_canvas, GTK_ALIGN_CENTER);
3130 gtk_widget_set_halign (used_canvas, GTK_ALIGN_CENTER);
3131
3132 gtk_widget_set_size_request (used_canvas, 20, 20);
3133 /* Translators: "used" refers to the capacity of the filesystem */
3134 concat = g_strconcat (used, " ", _("used")dcgettext (((void*)0), "used", 5), NULL((void*)0));
3135 used_label = gtk_label_new (concat);
3136 g_free (concat);
3137
3138 free_canvas = gtk_drawing_area_new ();
3139
3140 gtk_widget_set_valign (free_canvas, GTK_ALIGN_CENTER);
3141 gtk_widget_set_halign (free_canvas, GTK_ALIGN_CENTER);
3142
3143 gtk_widget_set_size_request (free_canvas, 20, 20);
3144 /* Translators: "free" refers to the capacity of the filesystem */
3145 concat = g_strconcat (free, " ", _("free")dcgettext (((void*)0), "free", 5), NULL((void*)0));
3146 free_label = gtk_label_new (concat);
3147 g_free (concat);
3148
3149 concat = g_strconcat (_("Total capacity:")dcgettext (((void*)0), "Total capacity:", 5), " ", capacity, NULL((void*)0));
3150 capacity_label = gtk_label_new (concat);
3151 g_free (concat);
3152 fstype_label = gtk_label_new (NULL((void*)0));
3153
3154 location = g_file_new_for_uri (uri);
3155 info = g_file_query_filesystem_info (location, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3156 NULL((void*)0), NULL((void*)0));
3157 if (info) {
3158 const char *fs_type;
3159
3160 fs_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type");
3161
3162 if (fs_type != NULL((void*)0)) {
3163 concat = g_strconcat (_("Filesystem type:")dcgettext (((void*)0), "Filesystem type:", 5), " ", fs_type, NULL((void*)0));
3164 gtk_label_set_text (GTK_LABEL (fstype_label)((((GtkLabel*) (void *) ((fstype_label))))), concat);
3165 g_free (concat);
3166 }
3167
3168 g_object_unref (info);
3169 }
3170 g_object_unref (location);
3171
3172 g_free (uri);
3173 g_free (capacity);
3174 g_free (used);
3175 g_free (free);
3176
3177 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), pie_canvas,
3178 "height", 4,
3179 NULL((void*)0));
3180 gtk_grid_attach_next_to (grid, used_canvas, pie_canvas,
3181 GTK_POS_RIGHT, 1, 1);
3182 gtk_grid_attach_next_to (grid, used_label, used_canvas,
3183 GTK_POS_RIGHT, 1, 1);
3184
3185 gtk_grid_attach_next_to (grid, free_canvas, used_canvas,
3186 GTK_POS_BOTTOM, 1, 1);
3187 gtk_grid_attach_next_to (grid, free_label, free_canvas,
3188 GTK_POS_RIGHT, 1, 1);
3189
3190 gtk_grid_attach_next_to (grid, capacity_label, free_canvas,
3191 GTK_POS_BOTTOM, 2, 1);
3192 gtk_grid_attach_next_to (grid, fstype_label, capacity_label,
3193 GTK_POS_BOTTOM, 2, 1);
3194
3195 g_signal_connect (pie_canvas, "draw",g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
3196 G_CALLBACK (paint_pie_chart), window)g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
;
3197 g_signal_connect (used_canvas, "draw",g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
3198 G_CALLBACK (paint_used_legend), window)g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3199 g_signal_connect (free_canvas, "draw",g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
3200 G_CALLBACK (paint_free_legend), window)g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3201
3202 return GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid)))));
3203
3204}
3205
3206static GtkWidget*
3207create_volume_usage_widget (FMPropertiesWindow *window)
3208{
3209 GtkWidget *piewidget;
3210 gchar *uri;
3211 CajaFile *file;
3212 GFile *location;
3213 GFileInfo *info;
3214
3215 file = get_original_file (window);
3216
3217 uri = caja_file_get_activation_uri (file);
3218
3219 location = g_file_new_for_uri (uri);
3220 info = g_file_query_filesystem_info (location, "filesystem::*", NULL((void*)0), NULL((void*)0));
3221
3222 if (info) {
3223 window->details->volume_capacity = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE"filesystem::size");
3224 window->details->volume_free = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
3225
3226 g_object_unref (info);
3227 } else {
3228 window->details->volume_capacity = 0;
3229 window->details->volume_free = 0;
3230 }
3231
3232 g_object_unref (location);
3233
3234 piewidget = create_pie_widget (window);
3235
3236 gtk_widget_show_all (piewidget);
3237
3238 return piewidget;
3239}
3240
3241static void
3242create_basic_page (FMPropertiesWindow *window)
3243{
3244 GtkGrid *grid;
3245 GtkWidget *icon_pixmap_widget;
3246 GtkWidget *hbox, *vbox;
3247
3248 hbox = create_page_with_hbox (window->details->notebook, _("Basic")dcgettext (((void*)0), "Basic", 5));
3249
3250 /* Icon pixmap */
3251
3252 icon_pixmap_widget = create_image_widget (
3253 window, should_show_custom_icon_buttons (window));
3254
3255 gtk_widget_set_halign (icon_pixmap_widget, GTK_ALIGN_END);
3256 gtk_widget_set_valign (icon_pixmap_widget, GTK_ALIGN_START);
3257 gtk_widget_show (icon_pixmap_widget);
3258
3259 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), icon_pixmap_widget, FALSE(0), FALSE(0), 0);
3260
3261 window->details->icon_chooser = NULL((void*)0);
3262
3263 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3264
3265 gtk_widget_show (vbox);
3266 gtk_container_add (GTK_CONTAINER (hbox)((((GtkContainer*) (void *) ((hbox))))), vbox);
3267
3268 grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
3269 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid))))), FALSE(0), FALSE(0), 0);
3270 window->details->basic_grid = grid;
3271
3272 /* Name label. The text will be determined in update_name_field */
3273 window->details->name_label = attach_title_field (grid, NULL((void*)0));
3274
3275 /* Name field */
3276 window->details->name_field = NULL((void*)0);
3277 update_name_field (window);
3278
3279 /* Start with name field selected, if it's an entry. */
3280 if (CAJA_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (caja_entry_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; }))))
) {
3281 caja_entry_select_all (CAJA_ENTRY (window->details->name_field)((((CajaEntry*) (void *) ((window->details->name_field)
))))
);
3282 gtk_widget_grab_focus (GTK_WIDGET (window->details->name_field)((((GtkWidget*) (void *) ((window->details->name_field)
))))
);
3283 }
3284
3285 if (fm_ditem_page_should_show (window->details->target_files)) {
3286 GtkSizeGroup *label_size_group;
3287 GtkWidget *box;
3288
3289 label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3290 gtk_size_group_add_widget (label_size_group,
3291 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
);
3292 box = fm_ditem_page_make_box (label_size_group,
3293 window->details->target_files);
3294
3295 gtk_grid_attach_next_to (window->details->basic_grid, box,
3296 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
,
3297 GTK_POS_BOTTOM, 2, 1);
3298 }
3299
3300 if (should_show_file_type (window)) {
3301 append_title_value_pair (window,
3302 grid, _("Type:")dcgettext (((void*)0), "Type:", 5),
3303 "type",
3304 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3305 FALSE(0));
3306 }
3307
3308 if (should_show_link_target (window)) {
3309 append_title_and_ellipsizing_value (window, grid,
3310 _("Link target:")dcgettext (((void*)0), "Link target:", 5),
3311 "link_target",
3312 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3313 FALSE(0));
3314 }
3315
3316 if (is_multi_file_window (window) ||
3317 caja_file_is_directory (get_target_file (window))) {
3318 append_directory_contents_fields (window, grid);
3319 } else {
3320 append_title_value_pair (window, grid, _("Size:")dcgettext (((void*)0), "Size:", 5),
3321 "size_detail",
3322 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3323 FALSE(0));
3324 append_title_value_pair (window, grid, _("Size on Disk:")dcgettext (((void*)0), "Size on Disk:", 5),
3325 "size_on_disk_detail",
3326 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3327 FALSE(0));
3328 }
3329
3330 append_blank_row (grid);
3331
3332 if (should_show_location_info (window)) {
3333 append_title_and_ellipsizing_value (window, grid, _("Location:")dcgettext (((void*)0), "Location:", 5),
3334 "where",
3335 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3336 TRUE(!(0)));
3337
3338 append_title_and_ellipsizing_value (window, grid,
3339 _("Volume:")dcgettext (((void*)0), "Volume:", 5),
3340 "volume",
3341 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3342 FALSE(0));
3343 }
3344
3345 if (should_show_accessed_date (window)
3346 || should_show_modified_date (window))
3347 {
3348 append_blank_row (grid);
3349 }
3350
3351 if (should_show_accessed_date (window))
3352 {
3353 append_title_value_pair (window, grid, _("Accessed:")dcgettext (((void*)0), "Accessed:", 5),
3354 "date_accessed",
3355 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3356 FALSE(0));
3357 }
3358
3359 if (should_show_modified_date (window))
3360 {
3361 append_title_value_pair (window, grid, _("Modified:")dcgettext (((void*)0), "Modified:", 5),
3362 "date_modified",
3363 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3364 FALSE(0));
3365 append_title_value_pair (window, grid, _("Created:")dcgettext (((void*)0), "Created:", 5),
3366 "date_created",
3367 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3368 FALSE(0));
3369 }
3370
3371 if (should_show_free_space (window)) {
3372 append_blank_row (grid);
3373
3374 append_title_value_pair (window, grid, _("Free space:")dcgettext (((void*)0), "Free space:", 5),
3375 "free_space",
3376 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3377 FALSE(0));
3378 }
3379
3380 if (should_show_volume_usage (window)) {
3381 GtkWidget *volume_usage;
3382
3383 volume_usage = create_volume_usage_widget (window);
3384 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), volume_usage,
3385 "width", 2,
3386 NULL((void*)0));
3387 }
3388}
3389
3390static GHashTable *
3391get_initial_emblems (GList *files)
3392{
3393 GHashTable *ret;
3394 GList *l;
3395
3396 ret = g_hash_table_new_full (g_direct_hash,
3397 g_direct_equal,
3398 NULL((void*)0),
3399 (GDestroyNotify) eel_g_list_free_deep);
3400
3401 for (l = files; l != NULL((void*)0); l = l->next) {
3402 CajaFile *file;
3403 GList *keywords;
3404
3405 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3406
3407 keywords = caja_file_get_keywords (file);
3408 g_hash_table_insert (ret, file, keywords);
3409 }
3410
3411 return ret;
3412}
3413
3414static gboolean
3415files_has_directory (FMPropertiesWindow *window)
3416{
3417 GList *l;
3418
3419 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3420 CajaFile *file;
3421 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3422 if (caja_file_is_directory (file)) {
3423 return TRUE(!(0));
3424 }
3425
3426 }
3427
3428 return FALSE(0);
3429}
3430
3431static gboolean
3432files_has_changable_permissions_directory (FMPropertiesWindow *window)
3433{
3434 GList *l;
3435
3436 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3437 CajaFile *file;
3438 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3439 if (caja_file_is_directory (file) &&
3440 caja_file_can_get_permissions (file) &&
3441 caja_file_can_set_permissions (file)) {
3442 return TRUE(!(0));
3443 }
3444
3445 }
3446
3447 return FALSE(0);
3448}
3449
3450
3451static gboolean
3452files_has_file (FMPropertiesWindow *window)
3453{
3454 GList *l;
3455
3456 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3457 CajaFile *file;
3458 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3459 if (!caja_file_is_directory (file)) {
3460 return TRUE(!(0));
3461 }
3462
3463 }
3464
3465 return FALSE(0);
3466}
3467
3468
3469static void
3470create_emblems_page (FMPropertiesWindow *window)
3471{
3472 GtkWidget *emblems_table, *button, *scroller;
3473 GdkPixbuf *pixbuf;
3474 char *label;
3475 GList *icons, *l;
3476 CajaIconInfo *info;
3477 gint scale;
3478
3479 /* The emblems wrapped table */
3480 scroller = eel_scrolled_wrap_table_new (TRUE(!(0)), GTK_SHADOW_NONE, &emblems_table);
3481
3482 gtk_container_set_border_width (GTK_CONTAINER (emblems_table)((((GtkContainer*) (void *) ((emblems_table))))), 12);
3483
3484 /* stop GTK 3.22 builds from ballooning the properties dialog to full screen height */
3485 gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (scroller)((((GtkScrolledWindow*) (void *) ((scroller))))), 300);
3486
3487 gtk_widget_show (scroller);
3488
3489 gtk_notebook_append_page (window->details->notebook,
3490 scroller, gtk_label_new (_("Emblems")dcgettext (((void*)0), "Emblems", 5)));
3491
3492 icons = caja_emblem_list_available ();
3493 scale = gtk_widget_get_scale_factor (scroller);
3494
3495 window->details->initial_emblems = get_initial_emblems (window->details->original_files);
3496
3497 l = icons;
3498 while (l != NULL((void*)0)) {
3499 char *emblem_name;
3500
3501 emblem_name = l->data;
3502 l = l->next;
3503
3504 if (!caja_emblem_should_show_in_list (emblem_name)) {
3505 continue;
3506 }
3507
3508 info = caja_icon_info_lookup_from_name (emblem_name, CAJA_ICON_SIZE_SMALL32, scale);
3509 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (info, CAJA_ICON_SIZE_SMALL32);
3510
3511 if (pixbuf == NULL((void*)0)) {
3512 continue;
3513 }
3514
3515 label = g_strdup (caja_icon_info_get_display_name (info))g_strdup_inline (caja_icon_info_get_display_name (info));
3516 g_object_unref (info);
3517
3518 if (label == NULL((void*)0)) {
3519 label = caja_emblem_get_keyword_from_icon_name (emblem_name);
3520 }
3521
3522 button = eel_labeled_image_check_button_new (label, pixbuf);
3523 eel_labeled_image_set_fixed_image_height (EEL_LABELED_IMAGE (gtk_bin_get_child (GTK_BIN (button)))((((EelLabeledImage*) (void *) ((gtk_bin_get_child (((((GtkBin
*) (void *) ((button)))))))))))
, STANDARD_EMBLEM_HEIGHT52 * scale);
3524 eel_labeled_image_set_spacing (EEL_LABELED_IMAGE (gtk_bin_get_child (GTK_BIN (button)))((((EelLabeledImage*) (void *) ((gtk_bin_get_child (((((GtkBin
*) (void *) ((button)))))))))))
, EMBLEM_LABEL_SPACING2 * scale);
3525
3526 g_free (label);
3527 g_object_unref (pixbuf);
3528
3529 /* Attach parameters and signal handler. */
3530 g_object_set_data_full (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name",
3531 caja_emblem_get_keyword_from_icon_name (emblem_name), g_free);
3532
3533 window->details->emblem_buttons =
3534 g_list_append (window->details->emblem_buttons,
3535 button);
3536
3537 g_signal_connect_object (button, "toggled",
3538 G_CALLBACK (emblem_button_toggled)((GCallback) (emblem_button_toggled)),
3539 G_OBJECT (window)((((GObject*) (void *) ((window))))),
3540 0);
3541
3542 gtk_container_add (GTK_CONTAINER (emblems_table)((((GtkContainer*) (void *) ((emblems_table))))), button);
3543 }
3544 g_list_free_full (icons, g_free);
3545 gtk_widget_show_all (emblems_table);
3546}
3547
3548static void
3549start_long_operation (FMPropertiesWindow *window)
3550{
3551 if (window->details->long_operation_underway == 0) {
3552 /* start long operation */
3553 GdkDisplay *display;
3554 GdkCursor * cursor;
3555
3556 display = gtk_widget_get_display (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
3557 cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
3558 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))), cursor);
3559 g_object_unref (cursor);
3560 }
3561 window->details->long_operation_underway ++;
3562}
3563
3564static void
3565end_long_operation (FMPropertiesWindow *window)
3566{
3567 if (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))) != NULL((void*)0) &&
3568 window->details->long_operation_underway == 1) {
3569 /* finished !! */
3570 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))), NULL((void*)0));
3571 }
3572 window->details->long_operation_underway--;
3573}
3574
3575static void
3576permission_change_callback (CajaFile *file,
3577 GFile *res_loc,
3578 GError *error,
3579 gpointer callback_data)
3580{
3581 FMPropertiesWindow *window;
3582 g_assert (callback_data != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_259
; if (callback_data != ((void*)0)) _g_boolean_var_259 = 1; else
_g_boolean_var_259 = 0; _g_boolean_var_259; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 3582, ((const char*
) (__func__)), "callback_data != NULL"); } while (0)
;
3583
3584 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
3585 end_long_operation (window);
3586
3587 /* Report the error if it's an error. */
3588 fm_report_error_setting_permissions (file, error, NULL((void*)0));
3589
3590 g_object_unref (window);
3591}
3592
3593static void
3594update_permissions (FMPropertiesWindow *window,
3595 guint32 vfs_new_perm,
3596 guint32 vfs_mask,
3597 gboolean is_folder,
3598 gboolean apply_to_both_folder_and_dir,
3599 gboolean use_original)
3600{
3601 GList *l;
3602
3603 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3604 CajaFile *file;
3605 guint32 permissions;
3606
3607 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3608
3609 if (!caja_file_can_get_permissions (file)) {
3610 continue;
3611 }
3612
3613 if (!apply_to_both_folder_and_dir &&
3614 ((caja_file_is_directory (file) && !is_folder) ||
3615 (!caja_file_is_directory (file) && is_folder))) {
3616 continue;
3617 }
3618
3619 permissions = caja_file_get_permissions (file);
3620 if (use_original) {
3621 gpointer ptr;
3622 if (g_hash_table_lookup_extended (window->details->initial_permissions,
3623 file, NULL((void*)0), &ptr)) {
3624 permissions = (permissions & ~vfs_mask) | (GPOINTER_TO_INT (ptr)((gint) (glong) (ptr)) & vfs_mask);
3625 }
3626 } else {
3627 permissions = (permissions & ~vfs_mask) | vfs_new_perm;
3628 }
3629
3630 start_long_operation (window);
3631 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
3632 caja_file_set_permissions
3633 (file, permissions,
3634 permission_change_callback,
3635 window);
3636 }
3637}
3638
3639static gboolean
3640initial_permission_state_consistent (FMPropertiesWindow *window,
3641 guint32 mask,
3642 gboolean is_folder,
3643 gboolean both_folder_and_dir)
3644{
3645 GList *l;
3646 gboolean first;
3647 guint32 first_permissions;
3648
3649 first = TRUE(!(0));
3650 first_permissions = 0;
3651 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3652 CajaFile *file;
3653 guint32 permissions;
3654
3655 file = l->data;
3656
3657 if (!both_folder_and_dir &&
3658 ((caja_file_is_directory (file) && !is_folder) ||
3659 (!caja_file_is_directory (file) && is_folder))) {
3660 continue;
3661 }
3662
3663 permissions = GPOINTER_TO_INT (g_hash_table_lookup (window->details->initial_permissions,((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
3664 file))((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
;
3665
3666 if (first) {
3667 if ((permissions & mask) != mask &&
3668 (permissions & mask) != 0) {
3669 /* Not fully on or off -> inconsistent */
3670 return FALSE(0);
3671 }
3672
3673 first_permissions = permissions;
3674 first = FALSE(0);
3675
3676 } else if ((permissions & mask) != (first_permissions & mask)) {
3677 /* Not same permissions as first -> inconsistent */
3678 return FALSE(0);
3679 }
3680 }
3681 return TRUE(!(0));
3682}
3683
3684static void
3685permission_button_toggled (GtkToggleButton *button,
3686 FMPropertiesWindow *window)
3687{
3688 gboolean is_folder, is_special;
3689 guint32 permission_mask;
3690 gboolean inconsistent;
3691 gboolean on;
3692
3693 permission_mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
3694 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
3695 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
3696 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
3697 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
3698 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
3699
3700 if (gtk_toggle_button_get_active (button)
3701 && !gtk_toggle_button_get_inconsistent (button)) {
3702 /* Go to the initial state unless the initial state was
3703 consistent, or we support recursive apply */
3704 inconsistent = TRUE(!(0));
3705 on = TRUE(!(0));
3706
3707 if (!window->details->has_recursive_apply &&
3708 initial_permission_state_consistent (window, permission_mask, is_folder, is_special)) {
3709 inconsistent = FALSE(0);
3710 on = TRUE(!(0));
3711 }
3712 } else if (gtk_toggle_button_get_inconsistent (button)
3713 && !gtk_toggle_button_get_active (button)) {
3714 inconsistent = FALSE(0);
3715 on = TRUE(!(0));
3716 } else {
3717 inconsistent = FALSE(0);
3718 on = FALSE(0);
3719 }
3720
3721 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3722 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3723 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3724
3725 gtk_toggle_button_set_active (button, on);
3726 gtk_toggle_button_set_inconsistent (button, inconsistent);
3727
3728 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3729 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3730 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3731
3732 update_permissions (window,
3733 on?permission_mask:0,
3734 permission_mask,
3735 is_folder,
3736 is_special,
3737 inconsistent);
3738}
3739
3740static void
3741permission_button_update (FMPropertiesWindow *window,
3742 GtkToggleButton *button)
3743{
3744 GList *l;
3745 gboolean all_set;
3746 gboolean all_unset;
3747 gboolean all_cannot_set;
3748 gboolean is_folder, is_special;
3749 gboolean no_match;
3750 gboolean sensitive;
3751 guint32 button_permission;
3752
3753 if (gtk_toggle_button_get_inconsistent (button) &&
3754 window->details->has_recursive_apply) {
3755 /* Never change from an inconsistent state if we have dirs, even
3756 * if the current state is now consistent, because its a useful
3757 * state for recursive apply.
3758 */
3759 return;
3760 }
3761
3762 button_permission = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
3763 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
3764 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
3765 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
3766 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
3767 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
3768
3769 all_set = TRUE(!(0));
3770 all_unset = TRUE(!(0));
3771 all_cannot_set = TRUE(!(0));
3772 no_match = TRUE(!(0));
3773 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3774 CajaFile *file;
3775 guint32 file_permissions;
3776
3777 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3778
3779 if (!caja_file_can_get_permissions (file)) {
3780 continue;
3781 }
3782
3783 if (!is_special &&
3784 ((caja_file_is_directory (file) && !is_folder) ||
3785 (!caja_file_is_directory (file) && is_folder))) {
3786 continue;
3787 }
3788
3789 no_match = FALSE(0);
3790
3791 file_permissions = caja_file_get_permissions (file);
3792
3793 if ((file_permissions & button_permission) == button_permission) {
3794 all_unset = FALSE(0);
3795 } else if ((file_permissions & button_permission) == 0) {
3796 all_set = FALSE(0);
3797 } else {
3798 all_unset = FALSE(0);
3799 all_set = FALSE(0);
3800 }
3801
3802 if (caja_file_can_set_permissions (file)) {
3803 all_cannot_set = FALSE(0);
3804 }
3805 }
3806
3807 sensitive = !all_cannot_set;
3808 if (!is_folder) {
3809 /* Don't insitive files when we have recursive apply */
3810 sensitive |= window->details->has_recursive_apply;
3811 }
3812
3813
3814 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3815 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3816 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3817
3818 gtk_toggle_button_set_active (button, !all_unset);
3819 /* if actually inconsistent, or default value for file buttons
3820 if no files are selected. (useful for recursive apply) */
3821 gtk_toggle_button_set_inconsistent (button,
3822 (!all_unset && !all_set) ||
3823 (!is_folder && no_match));
3824 gtk_widget_set_sensitive (GTK_WIDGET (button)((((GtkWidget*) (void *) ((button))))), sensitive);
3825
3826 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3827 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3828 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3829}
3830
3831static void
3832set_up_permissions_checkbox (FMPropertiesWindow *window,
3833 GtkWidget *check_button,
3834 guint32 permission,
3835 gboolean is_folder)
3836{
3837 /* Load up the check_button with data we'll need when updating its state. */
3838 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "permission",
3839 GINT_TO_POINTER (permission)((gpointer) (glong) (permission)));
3840 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "properties_window",
3841 window);
3842 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "is-folder",
3843 GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
3844
3845 window->details->permission_buttons =
3846 g_list_prepend (window->details->permission_buttons,
3847 check_button);
3848
3849 g_signal_connect_object (check_button, "toggled",
3850 G_CALLBACK (permission_button_toggled)((GCallback) (permission_button_toggled)),
3851 window,
3852 0);
3853}
3854
3855static GtkWidget *
3856add_permissions_checkbox_with_label (FMPropertiesWindow *window,
3857 GtkGrid *grid,
3858 GtkWidget *sibling,
3859 const char *label,
3860 guint32 permission_to_check,
3861 GtkLabel *label_for,
3862 gboolean is_folder)
3863{
3864 GtkWidget *check_button;
3865 gboolean a11y_enabled;
3866
3867 check_button = gtk_check_button_new_with_mnemonic (label);
3868 gtk_widget_show (check_button);
3869 if (sibling) {
3870 gtk_grid_attach_next_to (grid, check_button, sibling,
3871 GTK_POS_RIGHT, 1, 1);
3872 } else {
3873 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), check_button);
3874 }
3875
3876 set_up_permissions_checkbox (window,
3877 check_button,
3878 permission_to_check,
3879 is_folder);
3880
3881 a11y_enabled = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (check_button))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(gtk_widget_get_accessible (check_button))); GType __t = ((gtk_accessible_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; }))))
;
3882 if (a11y_enabled && label_for != NULL((void*)0)) {
3883 eel_accessibility_set_up_label_widget_relation (GTK_WIDGET (label_for)((((GtkWidget*) (void *) ((label_for))))),
3884 check_button);
3885 }
3886
3887 return check_button;
3888}
3889
3890static GtkWidget *
3891add_permissions_checkbox (FMPropertiesWindow *window,
3892 GtkGrid *grid,
3893 GtkWidget *sibling,
3894 CheckboxType type,
3895 guint32 permission_to_check,
3896 GtkLabel *label_for,
3897 gboolean is_folder)
3898{
3899 const gchar *label;
3900
3901 if (type == PERMISSIONS_CHECKBOXES_READ) {
3902 label = _("_Read")dcgettext (((void*)0), "_Read", 5);
3903 } else if (type == PERMISSIONS_CHECKBOXES_WRITE) {
3904 label = _("_Write")dcgettext (((void*)0), "_Write", 5);
3905 } else {
3906 label = _("E_xecute")dcgettext (((void*)0), "E_xecute", 5);
3907 }
3908
3909 return add_permissions_checkbox_with_label (window, grid,
3910 sibling,
3911 label,
3912 permission_to_check,
3913 label_for,
3914 is_folder);
3915}
3916
3917enum {
3918 UNIX_PERM_SUID = S_ISUID04000,
3919 UNIX_PERM_SGID = S_ISGID02000,
3920 UNIX_PERM_STICKY = 01000, /* S_ISVTX not defined on all systems */
3921 UNIX_PERM_USER_READ = S_IRUSR0400,
3922 UNIX_PERM_USER_WRITE = S_IWUSR0200,
3923 UNIX_PERM_USER_EXEC = S_IXUSR0100,
3924 UNIX_PERM_USER_ALL = S_IRUSR0400 | S_IWUSR0200 | S_IXUSR0100,
3925 UNIX_PERM_GROUP_READ = S_IRGRP(0400 >> 3),
3926 UNIX_PERM_GROUP_WRITE = S_IWGRP(0200 >> 3),
3927 UNIX_PERM_GROUP_EXEC = S_IXGRP(0100 >> 3),
3928 UNIX_PERM_GROUP_ALL = S_IRGRP(0400 >> 3) | S_IWGRP(0200 >> 3) | S_IXGRP(0100 >> 3),
3929 UNIX_PERM_OTHER_READ = S_IROTH((0400 >> 3) >> 3),
3930 UNIX_PERM_OTHER_WRITE = S_IWOTH((0200 >> 3) >> 3),
3931 UNIX_PERM_OTHER_EXEC = S_IXOTH((0100 >> 3) >> 3),
3932 UNIX_PERM_OTHER_ALL = S_IROTH((0400 >> 3) >> 3) | S_IWOTH((0200 >> 3) >> 3) | S_IXOTH((0100 >> 3) >> 3)
3933};
3934
3935typedef enum {
3936 PERMISSION_READ = (1<<0),
3937 PERMISSION_WRITE = (1<<1),
3938 PERMISSION_EXEC = (1<<2)
3939} PermissionValue;
3940
3941typedef enum {
3942 PERMISSION_USER,
3943 PERMISSION_GROUP,
3944 PERMISSION_OTHER
3945} PermissionType;
3946
3947static guint32 vfs_perms[3][3] = {
3948 {UNIX_PERM_USER_READ, UNIX_PERM_USER_WRITE, UNIX_PERM_USER_EXEC},
3949 {UNIX_PERM_GROUP_READ, UNIX_PERM_GROUP_WRITE, UNIX_PERM_GROUP_EXEC},
3950 {UNIX_PERM_OTHER_READ, UNIX_PERM_OTHER_WRITE, UNIX_PERM_OTHER_EXEC},
3951};
3952
3953static guint32
3954permission_to_vfs (PermissionType type, PermissionValue perm)
3955{
3956 guint32 vfs_perm;
3957 g_assert (type >= 0 && type < 3)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_260
; if (type >= 0 && type < 3) _g_boolean_var_260
= 1; else _g_boolean_var_260 = 0; _g_boolean_var_260; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 3957, ((const char*) (__func__)), "type >= 0 && type < 3"
); } while (0)
;
3958
3959 vfs_perm = 0;
3960 if (perm & PERMISSION_READ) {
3961 vfs_perm |= vfs_perms[type][0];
3962 }
3963 if (perm & PERMISSION_WRITE) {
3964 vfs_perm |= vfs_perms[type][1];
3965 }
3966 if (perm & PERMISSION_EXEC) {
3967 vfs_perm |= vfs_perms[type][2];
3968 }
3969
3970 return vfs_perm;
3971}
3972
3973
3974static PermissionValue
3975permission_from_vfs (PermissionType type, guint32 vfs_perm)
3976{
3977 PermissionValue perm;
3978 g_assert (type >= 0 && type < 3)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_261
; if (type >= 0 && type < 3) _g_boolean_var_261
= 1; else _g_boolean_var_261 = 0; _g_boolean_var_261; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 3978, ((const char*) (__func__)), "type >= 0 && type < 3"
); } while (0)
;
3979
3980 perm = 0;
3981 if (vfs_perm & vfs_perms[type][0]) {
3982 perm |= PERMISSION_READ;
3983 }
3984 if (vfs_perm & vfs_perms[type][1]) {
3985 perm |= PERMISSION_WRITE;
3986 }
3987 if (vfs_perm & vfs_perms[type][2]) {
3988 perm |= PERMISSION_EXEC;
3989 }
3990
3991 return perm;
3992}
3993
3994static void
3995permission_combo_changed (GtkWidget *combo, FMPropertiesWindow *window)
3996{
3997 GtkTreeIter iter;
3998 GtkTreeModel *model;
3999 gboolean is_folder, use_original;
4000 PermissionType type;
4001 int new_perm, mask;
4002 guint32 vfs_new_perm, vfs_mask;
4003
4004 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4005 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4006
4007 if (is_folder) {
4008 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4009 } else {
4010 mask = PERMISSION_READ|PERMISSION_WRITE;
4011 }
4012
4013 vfs_mask = permission_to_vfs (type, mask);
4014
4015 model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))));
4016
4017 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4018 return;
4019 }
4020 gtk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
4021 vfs_new_perm = permission_to_vfs (type, new_perm);
4022
4023 update_permissions (window, vfs_new_perm, vfs_mask,
4024 is_folder, FALSE(0), use_original);
4025}
4026
4027static void
4028permission_combo_add_multiple_choice (GtkComboBox *combo, GtkTreeIter *iter)
4029{
4030 GtkTreeModel *model;
4031 GtkListStore *store;
4032 gboolean found;
4033
4034 model = gtk_combo_box_get_model (combo);
4035 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
4036
4037 found = FALSE(0);
4038 gtk_tree_model_get_iter_first (model, iter);
4039 do {
4040 gboolean multi;
4041 gtk_tree_model_get (model, iter, 2, &multi, -1);
4042
4043 if (multi) {
4044 found = TRUE(!(0));
4045 break;
4046 }
4047 } while (gtk_tree_model_iter_next (model, iter));
4048
4049 if (!found) {
4050 gtk_list_store_append (store, iter);
4051 gtk_list_store_set (store, iter, 0, "---", 1, 0, 2, TRUE(!(0)), -1);
4052 }
4053}
4054
4055static void
4056permission_combo_update (FMPropertiesWindow *window,
4057 GtkComboBox *combo)
4058{
4059 PermissionType type;
4060 PermissionValue perm, all_dir_perm, all_file_perm, all_perm;
4061 gboolean is_folder, no_files, no_dirs, all_file_same, all_dir_same, all_same;
4062 gboolean all_dir_cannot_set, all_file_cannot_set, sensitive;
4063 GtkTreeIter iter;
4064 int mask;
4065 GtkTreeModel *model;
4066 GtkListStore *store;
4067 GList *l;
4068 gboolean is_multi;
4069
4070 model = gtk_combo_box_get_model (combo);
4071
4072 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4073 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4074
4075 is_multi = FALSE(0);
4076 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4077 gtk_tree_model_get (model, &iter, 2, &is_multi, -1);
4078 }
4079
4080 if (is_multi && window->details->has_recursive_apply) {
4081 /* Never change from an inconsistent state if we have dirs, even
4082 * if the current state is now consistent, because its a useful
4083 * state for recursive apply.
4084 */
4085 return;
4086 }
4087
4088 no_files = TRUE(!(0));
4089 no_dirs = TRUE(!(0));
4090 all_dir_same = TRUE(!(0));
4091 all_file_same = TRUE(!(0));
4092 all_dir_perm = 0;
4093 all_file_perm = 0;
4094 all_dir_cannot_set = TRUE(!(0));
4095 all_file_cannot_set = TRUE(!(0));
4096
4097 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4098 CajaFile *file;
4099 guint32 file_permissions;
4100
4101 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4102
4103 if (!caja_file_can_get_permissions (file)) {
4104 continue;
4105 }
4106
4107 if (caja_file_is_directory (file)) {
4108 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4109 } else {
4110 mask = PERMISSION_READ|PERMISSION_WRITE;
4111 }
4112
4113 file_permissions = caja_file_get_permissions (file);
4114
4115 perm = permission_from_vfs (type, file_permissions) & mask;
4116
4117 if (caja_file_is_directory (file)) {
4118 if (no_dirs) {
4119 all_dir_perm = perm;
4120 no_dirs = FALSE(0);
4121 } else if (perm != all_dir_perm) {
4122 all_dir_same = FALSE(0);
4123 }
4124
4125 if (caja_file_can_set_permissions (file)) {
4126 all_dir_cannot_set = FALSE(0);
4127 }
4128 } else {
4129 if (no_files) {
4130 all_file_perm = perm;
4131 no_files = FALSE(0);
4132 } else if (perm != all_file_perm) {
4133 all_file_same = FALSE(0);
4134 }
4135
4136 if (caja_file_can_set_permissions (file)) {
4137 all_file_cannot_set = FALSE(0);
4138 }
4139 }
4140 }
4141
4142 if (is_folder) {
4143 all_same = all_dir_same;
4144 all_perm = all_dir_perm;
4145 } else {
4146 all_same = all_file_same && !no_files;
4147 all_perm = all_file_perm;
4148 }
4149
4150 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
4151 if (all_same) {
4152 gboolean found;
4153
4154 found = FALSE(0);
4155 gtk_tree_model_get_iter_first (model, &iter);
4156 do {
4157 int current_perm;
4158 gtk_tree_model_get (model, &iter, 1, &current_perm, -1);
4159
4160 if (current_perm == all_perm) {
4161 found = TRUE(!(0));
4162 break;
4163 }
4164 } while (gtk_tree_model_iter_next (model, &iter));
4165
4166 if (!found) {
4167 GString *str;
4168 str = g_string_new ("");
4169
4170 if (!(all_perm & PERMISSION_READ)) {
4171 /* Translators: this gets concatenated to "no read",
4172 * "no access", etc. (see following strings)
4173 */
4174 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_262; if (__val != ((void
*)0)) _g_boolean_var_262 = 1; else _g_boolean_var_262 = 0; _g_boolean_var_262
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4175 }
4176 if (is_folder) {
4177 g_string_append (str, _("list"))(__builtin_constant_p (dcgettext (((void*)0), "list", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "list"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_263; if (__val != ((void
*)0)) _g_boolean_var_263 = 1; else _g_boolean_var_263 = 0; _g_boolean_var_263
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "list", 5), (gssize) -1))
;
4178 } else {
4179 g_string_append (str, _("read"))(__builtin_constant_p (dcgettext (((void*)0), "read", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "read"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_264; if (__val != ((void
*)0)) _g_boolean_var_264 = 1; else _g_boolean_var_264 = 0; _g_boolean_var_264
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "read", 5), (gssize) -1))
;
4180 }
4181
4182 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_265; if (__val != ((void
*)0)) _g_boolean_var_265 = 1; else _g_boolean_var_265 = 0; _g_boolean_var_265
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
4183
4184 if (!(all_perm & PERMISSION_WRITE)) {
4185 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_266; if (__val != ((void
*)0)) _g_boolean_var_266 = 1; else _g_boolean_var_266 = 0; _g_boolean_var_266
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4186 }
4187 if (is_folder) {
4188 g_string_append (str, _("create/delete"))(__builtin_constant_p (dcgettext (((void*)0), "create/delete"
, 5)) ? __extension__ ({ const char * const __val = (dcgettext
(((void*)0), "create/delete", 5)); g_string_append_len_inline
(str, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (__val != ((void*)0)) _g_boolean_var_267 = 1; else _g_boolean_var_267
= 0; _g_boolean_var_267; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, dcgettext (((void*)0), "create/delete", 5), (gssize) -
1))
;
4189 } else {
4190 g_string_append (str, _("write"))(__builtin_constant_p (dcgettext (((void*)0), "write", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "write"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_268; if (__val != ((void
*)0)) _g_boolean_var_268 = 1; else _g_boolean_var_268 = 0; _g_boolean_var_268
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "write", 5), (gssize) -1))
;
4191 }
4192
4193 if (is_folder) {
4194 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_269; if (__val != ((void
*)0)) _g_boolean_var_269 = 1; else _g_boolean_var_269 = 0; _g_boolean_var_269
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
4195
4196 if (!(all_perm & PERMISSION_EXEC)) {
4197 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_270; if (__val != ((void
*)0)) _g_boolean_var_270 = 1; else _g_boolean_var_270 = 0; _g_boolean_var_270
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4198 }
4199 g_string_append (str, _("access"))(__builtin_constant_p (dcgettext (((void*)0), "access", 5)) ?
__extension__ ({ const char * const __val = (dcgettext (((void
*)0), "access", 5)); g_string_append_len_inline (str, __val, (
__builtin_expect (__extension__ ({ int _g_boolean_var_271; if
(__val != ((void*)0)) _g_boolean_var_271 = 1; else _g_boolean_var_271
= 0; _g_boolean_var_271; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, dcgettext (((void*)0), "access", 5), (gssize) -1))
;
4200 }
4201
4202 gtk_list_store_append (store, &iter);
4203 gtk_list_store_set (store, &iter,
4204 0, str->str,
4205 1, all_perm, -1);
4206
4207 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
4208 }
4209 } else {
4210 permission_combo_add_multiple_choice (combo, &iter);
4211 }
4212
4213 g_signal_handlers_block_by_func (G_OBJECT (combo),g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4214 G_CALLBACK (permission_combo_changed),g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4215 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4216
4217 gtk_combo_box_set_active_iter (combo, &iter);
4218
4219 /* Also enable if no files found (for recursive
4220 file changes when only selecting folders) */
4221 if (is_folder) {
4222 sensitive = !all_dir_cannot_set;
4223 } else {
4224 sensitive = !all_file_cannot_set ||
4225 window->details->has_recursive_apply;
4226 }
4227 gtk_widget_set_sensitive (GTK_WIDGET (combo)((((GtkWidget*) (void *) ((combo))))), sensitive);
4228
4229 g_signal_handlers_unblock_by_func (G_OBJECT (combo),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4230 G_CALLBACK (permission_combo_changed),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4231 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4232
4233}
4234
4235static void
4236add_permissions_combo_box (FMPropertiesWindow *window, GtkGrid *grid,
4237 PermissionType type, gboolean is_folder,
4238 gboolean short_label)
4239{
4240 GtkWidget *combo;
4241 GtkLabel *label;
4242 GtkListStore *store;
4243 GtkCellRenderer *cell;
4244 GtkTreeIter iter;
4245
4246 if (short_label) {
4247 label = attach_title_field (grid, _("Access:")dcgettext (((void*)0), "Access:", 5));
4248 } else if (is_folder) {
4249 label = attach_title_field (grid, _("Folder access:")dcgettext (((void*)0), "Folder access:", 5));
4250 } else {
4251 label = attach_title_field (grid, _("File access:")dcgettext (((void*)0), "File access:", 5));
4252 }
4253
4254 store = gtk_list_store_new (3, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_INT((GType) ((6) << (2))), G_TYPE_BOOLEAN((GType) ((5) << (2))));
4255 combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))));
4256
4257 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) ((combo))))), "is-folder", GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
4258 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) ((combo))))), "permission-type", GINT_TO_POINTER (type)((gpointer) (glong) (type)));
4259
4260 if (is_folder) {
4261 if (type != PERMISSION_USER) {
4262 gtk_list_store_append (store, &iter);
4263 /* Translators: this is referred to the permissions
4264 * the user has in a directory.
4265 */
4266 gtk_list_store_set (store, &iter, 0, _("None")dcgettext (((void*)0), "None", 5), 1, 0, -1);
4267 }
4268 gtk_list_store_append (store, &iter);
4269 gtk_list_store_set (store, &iter, 0, _("List files only")dcgettext (((void*)0), "List files only", 5), 1, PERMISSION_READ, -1);
4270 gtk_list_store_append (store, &iter);
4271 gtk_list_store_set (store, &iter, 0, _("Access files")dcgettext (((void*)0), "Access files", 5), 1, PERMISSION_READ|PERMISSION_EXEC, -1);
4272 gtk_list_store_append (store, &iter);
4273 gtk_list_store_set (store, &iter, 0, _("Create and delete files")dcgettext (((void*)0), "Create and delete files", 5), 1, PERMISSION_READ|PERMISSION_EXEC|PERMISSION_WRITE, -1);
4274 } else {
4275 if (type != PERMISSION_USER) {
4276 gtk_list_store_append (store, &iter);
4277 gtk_list_store_set (store, &iter, 0, _("None")dcgettext (((void*)0), "None", 5), 1, 0, -1);
4278 }
4279 gtk_list_store_append (store, &iter);
4280 gtk_list_store_set (store, &iter, 0, _("Read-only")dcgettext (((void*)0), "Read-only", 5), 1, PERMISSION_READ, -1);
4281 gtk_list_store_append (store, &iter);
4282 gtk_list_store_set (store, &iter, 0, _("Read and write")dcgettext (((void*)0), "Read and write", 5), 1, PERMISSION_READ|PERMISSION_WRITE, -1);
4283 }
4284 if (window->details->has_recursive_apply) {
4285 permission_combo_add_multiple_choice (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
4286 }
4287
4288 g_object_unref (store);
4289
4290 window->details->permission_combos =
4291 g_list_prepend (window->details->permission_combos,
4292 combo);
4293
4294 g_signal_connect (combo, "changed", G_CALLBACK (permission_combo_changed), window)g_signal_connect_data ((combo), ("changed"), (((GCallback) (permission_combo_changed
))), (window), ((void*)0), (GConnectFlags) 0)
;
4295
4296 cell = gtk_cell_renderer_text_new ();
4297 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
4298 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell,
4299 "text", 0,
4300 NULL((void*)0));
4301
4302 gtk_label_set_mnemonic_widget (label, combo);
4303 gtk_widget_show (combo);
4304
4305 gtk_grid_attach_next_to (grid, combo, GTK_WIDGET (label)((((GtkWidget*) (void *) ((label))))),
4306 GTK_POS_RIGHT, 1, 1);
4307}
4308
4309
4310static GtkWidget *
4311append_special_execution_checkbox (FMPropertiesWindow *window,
4312 GtkGrid *grid,
4313 GtkWidget *sibling,
4314 const char *label_text,
4315 guint32 permission_to_check)
4316{
4317 GtkWidget *check_button;
4318
4319 check_button = gtk_check_button_new_with_mnemonic (label_text);
4320 gtk_widget_show (check_button);
4321
4322 if (sibling != NULL((void*)0)) {
4323 gtk_grid_attach_next_to (grid, check_button, sibling,
4324 GTK_POS_RIGHT, 1, 1);
4325 } else {
4326 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), check_button,
4327 "left-attach", 1,
4328 NULL((void*)0));
4329 }
4330
4331 set_up_permissions_checkbox (window,
4332 check_button,
4333 permission_to_check,
4334 FALSE(0));
4335 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "is-special",
4336 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4337
4338 return check_button;
4339}
4340
4341static void
4342append_special_execution_flags (FMPropertiesWindow *window, GtkGrid *grid)
4343{
4344 GtkWidget *title;
4345
4346 append_blank_slim_row (grid);
4347 title = GTK_WIDGET (attach_title_field (grid, _("Special flags:")))((((GtkWidget*) (void *) ((attach_title_field (grid, dcgettext
(((void*)0), "Special flags:", 5)))))))
;
4348
4349 append_special_execution_checkbox (window, grid, title, _("Set _user ID")dcgettext (((void*)0), "Set _user ID", 5), UNIX_PERM_SUID);
4350 append_special_execution_checkbox (window, grid, NULL((void*)0), _("Set gro_up ID")dcgettext (((void*)0), "Set gro_up ID", 5), UNIX_PERM_SGID);
4351 append_special_execution_checkbox (window, grid, NULL((void*)0), _("_Sticky")dcgettext (((void*)0), "_Sticky", 5), UNIX_PERM_STICKY);
4352}
4353
4354static gboolean
4355all_can_get_permissions (GList *file_list)
4356{
4357 GList *l;
4358 for (l = file_list; l != NULL((void*)0); l = l->next) {
4359 CajaFile *file;
4360
4361 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4362
4363 if (!caja_file_can_get_permissions (file)) {
4364 return FALSE(0);
4365 }
4366 }
4367
4368 return TRUE(!(0));
4369}
4370
4371static gboolean
4372all_can_set_permissions (GList *file_list)
4373{
4374 GList *l;
4375 for (l = file_list; l != NULL((void*)0); l = l->next) {
4376 CajaFile *file;
4377
4378 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4379
4380 if (!caja_file_can_set_permissions (file)) {
4381 return FALSE(0);
4382 }
4383 }
4384
4385 return TRUE(!(0));
4386}
4387
4388static GHashTable *
4389get_initial_permissions (GList *file_list)
4390{
4391 GHashTable *ret;
4392 GList *l;
4393
4394 ret = g_hash_table_new (g_direct_hash,
4395 g_direct_equal);
4396
4397 for (l = file_list; l != NULL((void*)0); l = l->next) {
4398 guint32 permissions;
4399 CajaFile *file;
4400
4401 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4402
4403 permissions = caja_file_get_permissions (file);
4404 g_hash_table_insert (ret, file,
4405 GINT_TO_POINTER (permissions)((gpointer) (glong) (permissions)));
4406 }
4407
4408 return ret;
4409}
4410
4411static void
4412create_simple_permissions (FMPropertiesWindow *window, GtkGrid *page_grid)
4413{
4414 gboolean has_file, has_directory;
4415 GtkLabel *group_label;
4416 GtkLabel *owner_label;
4417 GtkLabel *execute_label;
4418 GtkWidget *value;
4419
4420 has_file = files_has_file (window);
4421 has_directory = files_has_directory (window);
4422
4423 if (!is_multi_file_window (window) && caja_file_can_set_owner (get_target_file (window))) {
4424 GtkComboBox *owner_combo_box;
4425
4426 owner_label = attach_title_field (page_grid, _("_Owner:")dcgettext (((void*)0), "_Owner:", 5));
4427 /* Combo box in this case. */
4428 owner_combo_box = attach_owner_combo_box (page_grid,
4429 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4430 get_target_file (window));
4431 gtk_label_set_mnemonic_widget (owner_label,
4432 GTK_WIDGET (owner_combo_box)((((GtkWidget*) (void *) ((owner_combo_box))))));
4433 } else {
4434 owner_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4435 /* Static text in this case. */
4436 value = attach_value_field (window,
4437 page_grid, GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4438 "owner",
4439 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4440 FALSE(0));
4441 gtk_label_set_mnemonic_widget (owner_label, value);
4442 }
4443
4444 if (has_directory) {
4445 add_permissions_combo_box (window, page_grid,
4446 PERMISSION_USER, TRUE(!(0)), FALSE(0));
4447 }
4448 if (has_file || window->details->has_recursive_apply) {
4449 add_permissions_combo_box (window, page_grid,
4450 PERMISSION_USER, FALSE(0), !has_directory);
4451 }
4452
4453 append_blank_slim_row (page_grid);
4454
4455 if (!is_multi_file_window (window) && caja_file_can_set_group (get_target_file (window))) {
4456 GtkComboBox *group_combo_box;
4457
4458 group_label = attach_title_field (page_grid, _("_Group:")dcgettext (((void*)0), "_Group:", 5));
4459
4460 /* Combo box in this case. */
4461 group_combo_box = attach_group_combo_box (page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4462 get_target_file (window));
4463 gtk_label_set_mnemonic_widget (group_label,
4464 GTK_WIDGET (group_combo_box)((((GtkWidget*) (void *) ((group_combo_box))))));
4465 } else {
4466 group_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4467
4468 /* Static text in this case. */
4469 value = attach_value_field (window, page_grid,
4470 GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4471 "group",
4472 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4473 FALSE(0));
4474 gtk_label_set_mnemonic_widget (group_label, value);
4475 }
4476
4477 if (has_directory) {
4478 add_permissions_combo_box (window, page_grid,
4479 PERMISSION_GROUP, TRUE(!(0)),
4480 FALSE(0));
4481 }
4482 if (has_file || window->details->has_recursive_apply) {
4483 add_permissions_combo_box (window, page_grid,
4484 PERMISSION_GROUP, FALSE(0),
4485 !has_directory);
4486 }
4487
4488 append_blank_slim_row (page_grid);
4489
4490 group_label = attach_title_field (page_grid, _("Others")dcgettext (((void*)0), "Others", 5));
Value stored to 'group_label' is never read
4491
4492 if (has_directory) {
4493 add_permissions_combo_box (window, page_grid,
4494 PERMISSION_OTHER, TRUE(!(0)),
4495 FALSE(0));
4496 }
4497 if (has_file || window->details->has_recursive_apply) {
4498 add_permissions_combo_box (window, page_grid,
4499 PERMISSION_OTHER, FALSE(0),
4500 !has_directory);
4501 }
4502
4503 append_blank_slim_row (page_grid);
4504
4505 execute_label = attach_title_field (page_grid, _("Execute:")dcgettext (((void*)0), "Execute:", 5));
4506 add_permissions_checkbox_with_label (window, page_grid,
4507 GTK_WIDGET (execute_label)((((GtkWidget*) (void *) ((execute_label))))),
4508 _("Allow _executing file as program")dcgettext (((void*)0), "Allow _executing file as program", 5),
4509 UNIX_PERM_USER_EXEC|UNIX_PERM_GROUP_EXEC|UNIX_PERM_OTHER_EXEC,
4510 execute_label, FALSE(0));
4511}
4512
4513static void
4514create_permission_checkboxes (FMPropertiesWindow *window,
4515 GtkGrid *page_grid,
4516 gboolean is_folder)
4517{
4518 GtkLabel *owner_perm_label;
4519 GtkLabel *group_perm_label;
4520 GtkLabel *other_perm_label;
4521 GtkGrid *check_button_grid;
4522 GtkWidget *w;
4523
4524 owner_perm_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4525 group_perm_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4526 other_perm_label = attach_title_field (page_grid, _("Others:")dcgettext (((void*)0), "Others:", 5));
4527
4528 check_button_grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
4529 gtk_widget_show (GTK_WIDGET (check_button_grid)((((GtkWidget*) (void *) ((check_button_grid))))));
4530
4531 gtk_grid_attach_next_to (page_grid, GTK_WIDGET (check_button_grid)((((GtkWidget*) (void *) ((check_button_grid))))),
4532 GTK_WIDGET (owner_perm_label)((((GtkWidget*) (void *) ((owner_perm_label))))),
4533 GTK_POS_RIGHT, 1, 3);
4534
4535 w = add_permissions_checkbox (window,
4536 check_button_grid,
4537 NULL((void*)0),
4538 PERMISSIONS_CHECKBOXES_READ,
4539 UNIX_PERM_USER_READ,
4540 owner_perm_label,
4541 is_folder);
4542
4543 w = add_permissions_checkbox (window,
4544 check_button_grid,
4545 w,
4546 PERMISSIONS_CHECKBOXES_WRITE,
4547 UNIX_PERM_USER_WRITE,
4548 owner_perm_label,
4549 is_folder);
4550
4551 w = add_permissions_checkbox (window,
4552 check_button_grid,
4553 w,
4554 PERMISSIONS_CHECKBOXES_EXECUTE,
4555 UNIX_PERM_USER_EXEC,
4556 owner_perm_label,
4557 is_folder);
4558
4559 w = add_permissions_checkbox (window,
4560 check_button_grid,
4561 NULL((void*)0),
4562 PERMISSIONS_CHECKBOXES_READ,
4563 UNIX_PERM_GROUP_READ,
4564 group_perm_label,
4565 is_folder);
4566
4567 w = add_permissions_checkbox (window,
4568 check_button_grid,
4569 w,
4570 PERMISSIONS_CHECKBOXES_WRITE,
4571 UNIX_PERM_GROUP_WRITE,
4572 group_perm_label,
4573 is_folder);
4574
4575 w = add_permissions_checkbox (window,
4576 check_button_grid,
4577 w,
4578 PERMISSIONS_CHECKBOXES_EXECUTE,
4579 UNIX_PERM_GROUP_EXEC,
4580 group_perm_label,
4581 is_folder);
4582
4583 w = add_permissions_checkbox (window,
4584 check_button_grid,
4585 NULL((void*)0),
4586 PERMISSIONS_CHECKBOXES_READ,
4587 UNIX_PERM_OTHER_READ,
4588 other_perm_label,
4589 is_folder);
4590
4591 w = add_permissions_checkbox (window,
4592 check_button_grid,
4593 w,
4594 PERMISSIONS_CHECKBOXES_WRITE,
4595 UNIX_PERM_OTHER_WRITE,
4596 other_perm_label,
4597 is_folder);
4598
4599 add_permissions_checkbox (window,
4600 check_button_grid,
4601 w,
4602 PERMISSIONS_CHECKBOXES_EXECUTE,
4603 UNIX_PERM_OTHER_EXEC,
4604 other_perm_label,
4605 is_folder);
4606}
4607
4608static void
4609create_advanced_permissions (FMPropertiesWindow *window, GtkGrid *page_grid)
4610{
4611 GtkLabel *group_label;
4612 GtkLabel *owner_label;
4613 gboolean has_directory, has_file;
4614
4615 if (!is_multi_file_window (window) && caja_file_can_set_owner (get_target_file (window))) {
4616 GtkComboBox *owner_combo_box;
4617
4618 owner_label = attach_title_field (page_grid, _("_Owner:")dcgettext (((void*)0), "_Owner:", 5));
4619 /* Combo box in this case. */
4620 owner_combo_box = attach_owner_combo_box (page_grid,
4621 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4622 get_target_file (window));
4623 gtk_label_set_mnemonic_widget (owner_label,
4624 GTK_WIDGET (owner_combo_box)((((GtkWidget*) (void *) ((owner_combo_box))))));
4625 } else {
4626 GtkWidget *value;
4627 owner_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4628
4629 /* Static text in this case. */
4630 value = attach_value_field (window,
4631 page_grid,
4632 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4633 "owner",
4634 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4635 FALSE(0));
4636 gtk_label_set_mnemonic_widget (owner_label, value);
4637 }
4638
4639 if (!is_multi_file_window (window) && caja_file_can_set_group (get_target_file (window))) {
4640 GtkComboBox *group_combo_box;
4641
4642 group_label = attach_title_field (page_grid, _("_Group:")dcgettext (((void*)0), "_Group:", 5));
4643
4644 /* Combo box in this case. */
4645 group_combo_box = attach_group_combo_box (page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4646 get_target_file (window));
4647 gtk_label_set_mnemonic_widget (group_label,
4648 GTK_WIDGET (group_combo_box)((((GtkWidget*) (void *) ((group_combo_box))))));
4649 } else {
4650 group_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4651
4652 /* Static text in this case. */
4653 attach_value_field (window, page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4654 "group",
4655 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4656 FALSE(0));
4657 }
4658
4659 append_blank_slim_row (page_grid);
4660
4661 has_directory = files_has_directory (window);
4662 has_file = files_has_file (window);
4663
4664 if (has_directory) {
4665 if (has_file || window->details->has_recursive_apply) {
4666 attach_title_field (page_grid, _("Folder Permissions:")dcgettext (((void*)0), "Folder Permissions:", 5));
4667 }
4668 create_permission_checkboxes (window, page_grid, TRUE(!(0)));
4669 }
4670
4671 if (has_file || window->details->has_recursive_apply) {
4672 if (has_directory) {
4673 attach_title_field (page_grid, _("File Permissions:")dcgettext (((void*)0), "File Permissions:", 5));
4674 }
4675 create_permission_checkboxes (window, page_grid, FALSE(0));
4676 }
4677
4678 append_blank_slim_row (page_grid);
4679 append_special_execution_flags (window, page_grid);
4680
4681 append_title_value_pair
4682 (window, page_grid, _("Text view:")dcgettext (((void*)0), "Text view:", 5),
4683 "permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4684 FALSE(0));
4685}
4686
4687static void
4688set_recursive_permissions_done (gpointer callback_data)
4689{
4690 FMPropertiesWindow *window;
4691
4692 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
4693 end_long_operation (window);
4694
4695 g_object_unref (window);
4696}
4697
4698
4699static void
4700apply_recursive_clicked (GtkWidget *recursive_button,
4701 FMPropertiesWindow *window)
4702{
4703 guint32 file_permission, file_permission_mask;
4704 guint32 dir_permission, dir_permission_mask;
4705 guint32 vfs_mask, vfs_new_perm, p;
4706 gboolean active, is_folder, is_special, use_original;
4707 GList *l;
4708 GtkTreeModel *model;
4709 GtkTreeIter iter;
4710 PermissionType type;
4711 int new_perm, mask;
4712 GtkWidget *button = NULL((void*)0);
4713 GtkWidget *combo = NULL((void*)0);
4714
4715 file_permission = 0;
4716 file_permission_mask = 0;
4717 dir_permission = 0;
4718 dir_permission_mask = 0;
4719
4720 /* Advanced mode and execute checkbox: */
4721 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
4722 button = l->data;
4723
4724 if (gtk_toggle_button_get_inconsistent (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))))) {
4725 continue;
4726 }
4727
4728 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))));
4729 p = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
4730 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
4731 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
4732 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
4733 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
4734 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
4735
4736 if (is_folder || is_special) {
4737 dir_permission_mask |= p;
4738 if (active) {
4739 dir_permission |= p;
4740 }
4741 }
4742 if (!is_folder || is_special) {
4743 file_permission_mask |= p;
4744 if (active) {
4745 file_permission |= p;
4746 }
4747 }
4748 }
4749 /* Simple mode, minus exec checkbox */
4750 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
4751 combo = l->data;
4752
4753 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4754 continue;
4755 }
4756
4757 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4758 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
4759 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4760
4761 model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))));
4762 gtk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
4763 if (use_original) {
4764 continue;
4765 }
4766 vfs_new_perm = permission_to_vfs (type, new_perm);
4767
4768 if (is_folder) {
4769 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4770 } else {
4771 mask = PERMISSION_READ|PERMISSION_WRITE;
4772 }
4773 vfs_mask = permission_to_vfs (type, mask);
4774
4775 if (is_folder) {
4776 dir_permission_mask |= vfs_mask;
4777 dir_permission |= vfs_new_perm;
4778 } else {
4779 file_permission_mask |= vfs_mask;
4780 file_permission |= vfs_new_perm;
4781 }
4782 }
4783
4784 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4785 CajaFile *file;
4786
4787 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4788
4789 if (caja_file_is_directory (file) &&
4790 caja_file_can_set_permissions (file)) {
4791 char *uri;
4792
4793 uri = caja_file_get_uri (file);
4794 start_long_operation (window);
4795 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
4796 caja_file_set_permissions_recursive (uri,
4797 file_permission,
4798 file_permission_mask,
4799 dir_permission,
4800 dir_permission_mask,
4801 set_recursive_permissions_done,
4802 window);
4803 g_free (uri);
4804 }
4805 }
4806}
4807
4808static void
4809create_permissions_page (FMPropertiesWindow *window)
4810{
4811 GtkWidget *vbox;
4812 GList *file_list;
4813
4814 vbox = create_page_with_vbox (window->details->notebook,
4815 _("Permissions")dcgettext (((void*)0), "Permissions", 5));
4816
4817 file_list = window->details->original_files;
4818
4819 window->details->initial_permissions = NULL((void*)0);
4820
4821 if (all_can_get_permissions (file_list) && all_can_get_permissions (window->details->target_files)) {
4822 GtkGrid *page_grid;
4823
4824 window->details->initial_permissions = get_initial_permissions (window->details->target_files);
4825 window->details->has_recursive_apply = files_has_changable_permissions_directory (window);
4826
4827 if (!all_can_set_permissions (file_list)) {
4828 add_prompt_and_separator (
4829 vbox,
4830 _("You are not the owner, so you cannot change these permissions.")dcgettext (((void*)0), "You are not the owner, so you cannot change these permissions."
, 5)
);
4831 }
4832
4833 page_grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
4834
4835 gtk_widget_show (GTK_WIDGET (page_grid)((((GtkWidget*) (void *) ((page_grid))))));
4836 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))),
4837 GTK_WIDGET (page_grid)((((GtkWidget*) (void *) ((page_grid))))),
4838 TRUE(!(0)), TRUE(!(0)), 0);
4839
4840 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_ADVANCED_PERMISSIONS"show-advanced-permissions")) {
4841 create_advanced_permissions (window, page_grid);
4842 } else {
4843 create_simple_permissions (window, page_grid);
4844 }
4845
4846 append_blank_slim_row (page_grid);
4847
4848#ifdef HAVE_SELINUX1
4849 append_title_value_pair
4850 (window, page_grid, _("SELinux context:")dcgettext (((void*)0), "SELinux context:", 5),
4851 "selinux_context", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4852 FALSE(0));
4853#endif
4854 append_title_value_pair
4855 (window, page_grid, _("Last changed:")dcgettext (((void*)0), "Last changed:", 5),
4856 "date_permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4857 FALSE(0));
4858
4859 if (window->details->has_recursive_apply) {
4860 GtkWidget *button, *hbox;
4861
4862 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4863 gtk_widget_show (hbox);
4864 gtk_container_add_with_properties (GTK_CONTAINER (page_grid)((((GtkContainer*) (void *) ((page_grid))))), hbox,
4865 "width", 2,
4866 NULL((void*)0));
4867
4868 button = gtk_button_new_with_mnemonic (_("Apply Permissions to Enclosed Files")dcgettext (((void*)0), "Apply Permissions to Enclosed Files",
5)
);
4869 gtk_widget_show (button);
4870 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
4871 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4872 G_CALLBACK (apply_recursive_clicked),g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4873 window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
;
4874 }
4875 } else {
4876 char *prompt_text;
4877
4878 if (!is_multi_file_window (window)) {
4879 char *file_name;
4880
4881 file_name = caja_file_get_display_name (get_target_file (window));
4882 prompt_text = g_strdup_printf (_("The permissions of \"%s\" could not be determined.")dcgettext (((void*)0), "The permissions of \"%s\" could not be determined."
, 5)
, file_name);
4883 g_free (file_name);
4884 } else {
4885 prompt_text = g_strdup (_("The permissions of the selected file could not be determined."))g_strdup_inline (dcgettext (((void*)0), "The permissions of the selected file could not be determined."
, 5))
;
4886 }
4887
4888 add_prompt (vbox, prompt_text, TRUE(!(0)));
4889 g_free (prompt_text);
4890 }
4891}
4892
4893static void
4894append_extension_pages (FMPropertiesWindow *window)
4895{
4896 GList *providers;
4897 GList *module_providers;
4898 GList *p;
4899
4900 providers = caja_extensions_get_for_type (CAJA_TYPE_PROPERTY_PAGE_PROVIDER(caja_property_page_provider_get_type ()));
4901
4902 /* FIXME: we also need the property pages from two old modules that
4903 * are not registered as proper extensions. This is going to work
4904 * this way until some generic solution is introduced.
4905 */
4906 module_providers = caja_module_get_extensions_for_type (CAJA_TYPE_PROPERTY_PAGE_PROVIDER(caja_property_page_provider_get_type ()));
4907 for (p = module_providers; p != NULL((void*)0); p = p->next) {
4908 const gchar *type_name = G_OBJECT_TYPE_NAME (G_OBJECT (p->data))(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (((((GObject
*) (void *) ((p->data)))))))->g_class))->g_type)))))
;
4909 if (g_strcmp0 (type_name, "CajaNotesViewerProvider") == 0 ||
4910 g_strcmp0 (type_name, "CajaImagePropertiesPageProvider") == 0) {
4911 providers = g_list_prepend (providers, p->data);
4912 }
4913 }
4914
4915 for (p = providers; p != NULL((void*)0); p = p->next) {
4916 CajaPropertyPageProvider *provider;
4917 GList *pages;
4918 GList *l;
4919
4920 provider = CAJA_PROPERTY_PAGE_PROVIDER (p->data)((((CajaPropertyPageProvider*) (void *) ((p->data)))));
4921
4922 pages = caja_property_page_provider_get_pages
4923 (provider, window->details->original_files);
4924
4925 for (l = pages; l != NULL((void*)0); l = l->next) {
4926 CajaPropertyPage *page;
4927 GtkWidget *page_widget;
4928 GtkWidget *label;
4929
4930 page = CAJA_PROPERTY_PAGE (l->data)((((CajaPropertyPage*) (void *) ((l->data)))));
4931
4932 g_object_get (G_OBJECT (page)((((GObject*) (void *) ((page))))),
4933 "page", &page_widget, "label", &label,
4934 NULL((void*)0));
4935
4936 gtk_notebook_append_page (window->details->notebook,
4937 page_widget, label);
4938
4939 g_object_set_data (G_OBJECT (page_widget)((((GObject*) (void *) ((page_widget))))),
4940 "is-extension-page",
4941 page);
4942
4943 g_object_unref (page_widget);
4944 g_object_unref (label);
4945
4946 g_object_unref (page);
4947 }
4948
4949 g_list_free (pages);
4950 }
4951
4952 caja_module_extension_list_free (providers);
4953}
4954
4955static gboolean
4956should_show_emblems (FMPropertiesWindow *window)
4957{
4958 /* FIXME bugzilla.gnome.org 45643:
4959 * Emblems aren't displayed on the the desktop Trash icon, so
4960 * we shouldn't pretend that they work by showing them here.
4961 * When bug 5643 is fixed we can remove this case.
4962 */
4963 if (!is_multi_file_window (window)
4964 && is_merged_trash_directory (get_target_file (window))) {
4965 return FALSE(0);
4966 }
4967
4968 return TRUE(!(0));
4969}
4970
4971static gboolean
4972should_show_permissions (FMPropertiesWindow *window)
4973{
4974 CajaFile *file;
4975
4976 file = get_target_file (window);
4977
4978 /* Don't show permissions for Trash and Computer since they're not
4979 * really file system objects.
4980 */
4981 if (!is_multi_file_window (window)
4982 && (is_merged_trash_directory (file) ||
4983 is_computer_directory (file))) {
4984 return FALSE(0);
4985 }
4986
4987 return TRUE(!(0));
4988}
4989
4990static char *
4991get_pending_key (GList *file_list)
4992{
4993 GList *l;
4994 GList *uris;
4995 GString *key;
4996 char *ret;
4997
4998 uris = NULL((void*)0);
4999 for (l = file_list; l != NULL((void*)0); l = l->next) {
5000 uris = g_list_prepend (uris, caja_file_get_uri (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))))));
5001 }
5002 uris = g_list_sort (uris, (GCompareFunc)strcmp);
5003
5004 key = g_string_new ("");
5005 for (l = uris; l != NULL((void*)0); l = l->next) {
5006 g_string_append (key, l->data)(__builtin_constant_p (l->data) ? __extension__ ({ const char
* const __val = (l->data); g_string_append_len_inline (key
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if (__val != ((void*)0)) _g_boolean_var_272 = 1; else _g_boolean_var_272
= 0; _g_boolean_var_272; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(key, l->data, (gssize) -1))
;
5007 g_string_append (key, ";")(__builtin_constant_p (";") ? __extension__ ({ const char * const
__val = (";"); g_string_append_len_inline (key, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_273; if (__val != ((void
*)0)) _g_boolean_var_273 = 1; else _g_boolean_var_273 = 0; _g_boolean_var_273
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (key, ";", (gssize) -1)
)
;
5008 }
5009
5010 g_list_free_full (uris, g_free);
5011
5012 ret = key->str;
5013 g_string_free (key, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((key)
, ((0))) : g_string_free_and_steal (key)) : (g_string_free) (
(key), ((0))))
;
5014
5015 return ret;
5016}
5017
5018static StartupData *
5019startup_data_new (GList *original_files,
5020 GList *target_files,
5021 const char *pending_key,
5022 GtkWidget *parent_widget)
5023{
5024 StartupData *data;
5025 GList *l;
5026
5027 data = g_new0 (StartupData, 1)(StartupData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (StartupData); 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; }))
;
5028 data->original_files = caja_file_list_copy (original_files);
5029 data->target_files = caja_file_list_copy (target_files);
5030 data->parent_widget = parent_widget;
5031 data->pending_key = g_strdup (pending_key)g_strdup_inline (pending_key);
5032 data->pending_files = g_hash_table_new (g_direct_hash,
5033 g_direct_equal);
5034
5035 for (l = data->target_files; l != NULL((void*)0); l = l->next) {
5036 g_hash_table_insert (data->pending_files, l->data, l->data);
5037 }
5038
5039 return data;
5040}
5041
5042static void
5043startup_data_free (StartupData *data)
5044{
5045 caja_file_list_free (data->original_files);
5046 caja_file_list_free (data->target_files);
5047 g_hash_table_destroy (data->pending_files);
5048 g_free (data->pending_key);
5049 g_free (data);
5050}
5051
5052static void
5053file_changed_callback (CajaFile *file, gpointer user_data)
5054{
5055 FMPropertiesWindow *window = FM_PROPERTIES_WINDOW (user_data)((((FMPropertiesWindow*) (void *) ((user_data)))));
5056
5057 if (!g_list_find (window->details->changed_files, file)) {
5058 caja_file_ref (file);
5059 window->details->changed_files = g_list_prepend (window->details->changed_files, file);
5060
5061 schedule_files_update (window);
5062 }
5063}
5064
5065static gboolean
5066is_a_special_file (CajaFile *file)
5067{
5068 if (file == NULL((void*)0) ||
5069 CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
||
5070 is_merged_trash_directory (file) ||
5071 is_computer_directory (file)) {
5072 return TRUE(!(0));
5073 }
5074 return FALSE(0);
5075}
5076
5077static gboolean
5078should_show_open_with (FMPropertiesWindow *window)
5079{
5080 CajaFile *file;
5081
5082 /* Don't show open with tab for desktop special icons (trash, etc)
5083 * We don't get the open-with menu for these anyway.
5084 *
5085 * Also don't show it for folders. Changing the default app for folders
5086 * leads to all sort of hard to understand errors.
5087 */
5088
5089 if (is_multi_file_window (window)) {
5090 if (!file_list_attributes_identical (window->details->original_files,
5091 "mime_type")) {
5092 return FALSE(0);
5093 } else {
5094
5095 GList *l;
5096
5097 for (l = window->details->original_files; l; l = l->next) {
5098 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5099 if (caja_file_is_directory (file) ||
5100 is_a_special_file (file)) {
5101 return FALSE(0);
5102 }
5103 }
5104 }
5105 } else {
5106 file = get_original_file (window);
5107 if (caja_file_is_directory (file) ||
5108 is_a_special_file (file)) {
5109 return FALSE(0);
5110 }
5111 }
5112 return TRUE(!(0));
5113}
5114
5115static void
5116create_open_with_page (FMPropertiesWindow *window)
5117{
5118 GtkWidget *vbox;
5119 char *mime_type;
5120
5121 mime_type = caja_file_get_mime_type (get_target_file (window));
5122
5123 if (!is_multi_file_window (window)) {
5124 char *uri;
5125
5126 uri = caja_file_get_uri (get_target_file (window));
5127
5128 if (uri == NULL((void*)0)) {
5129 return;
5130 }
5131
5132 vbox = caja_mime_application_chooser_new (uri, mime_type);
5133
5134 g_free (uri);
5135 } else {
5136 GList *uris;
5137
5138 uris = window->details->original_files;
5139 if (uris == NULL((void*)0)) {
5140 return;
5141 }
5142 vbox = caja_mime_application_chooser_new_for_multiple_files (uris, mime_type);
5143 }
5144
5145 gtk_widget_show (vbox);
5146 g_free (mime_type);
5147
5148 gtk_notebook_append_page (window->details->notebook,
5149 vbox, gtk_label_new (_("Open With")dcgettext (((void*)0), "Open With", 5)));
5150}
5151
5152
5153static FMPropertiesWindow *
5154create_properties_window (StartupData *startup_data)
5155{
5156 FMPropertiesWindow *window;
5157 GList *l;
5158 GtkWidget *action_area;
5159
5160 window = FM_PROPERTIES_WINDOW (gtk_widget_new (fm_properties_window_get_type (), NULL))((((FMPropertiesWindow*) (void *) ((gtk_widget_new (fm_properties_window_get_type
(), ((void*)0)))))))
;
5161
5162 window->details->original_files = caja_file_list_copy (startup_data->original_files);
5163
5164 window->details->target_files = caja_file_list_copy (startup_data->target_files);
5165
5166 gtk_window_set_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
5167 gtk_widget_get_screen (startup_data->parent_widget));
5168
5169 gtk_window_set_type_hint (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), GDK_WINDOW_TYPE_HINT_DIALOG);
5170
5171 /* Set initial window title */
5172 update_properties_window_title (window);
5173
5174 /* Start monitoring the file attributes we display. Note that some
5175 * of the attributes are for the original file, and some for the
5176 * target files.
5177 */
5178
5179 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5180 CajaFile *file;
5181 CajaFileAttributes attributes;
5182
5183 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5184
5185 attributes =
5186 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
|
5187 CAJA_FILE_ATTRIBUTE_INFO |
5188 CAJA_FILE_ATTRIBUTE_LINK_INFO;
5189
5190 caja_file_monitor_add (file,
5191 &window->details->original_files,
5192 attributes);
5193 }
5194
5195 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5196 CajaFile *file;
5197 CajaFileAttributes attributes;
5198
5199 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5200
5201 attributes = 0;
5202 if (caja_file_is_directory (file)) {
5203 attributes |= CAJA_FILE_ATTRIBUTE_DEEP_COUNTS;
5204 }
5205
5206 attributes |= CAJA_FILE_ATTRIBUTE_INFO;
5207 caja_file_monitor_add (file, &window->details->target_files, attributes);
5208 }
5209
5210 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5211 g_signal_connect_object (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5212 "changed",
5213 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5214 G_OBJECT (window)((((GObject*) (void *) ((window))))),
5215 0);
5216 }
5217
5218 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5219 g_signal_connect_object (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5220 "changed",
5221 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5222 G_OBJECT (window)((((GObject*) (void *) ((window))))),
5223 0);
5224 }
5225
5226 /* Create the notebook tabs. */
5227 window->details->notebook = GTK_NOTEBOOK (gtk_notebook_new ())((((GtkNotebook*) (void *) ((gtk_notebook_new ())))));
5228
5229 gtk_widget_add_events (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
, GDK_SCROLL_MASK);
5230 g_signal_connect (window->details->notebook,g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5231 "scroll-event",g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5232 G_CALLBACK (eel_notebook_scroll_event_cb),g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5233 NULL)g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
;
5234
5235 gtk_widget_show (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
);
5236 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((window)))))))))))
,
5237 GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
,
5238 TRUE(!(0)), TRUE(!(0)), 0);
5239
5240 /* Create the pages. */
5241 create_basic_page (window);
5242
5243 if (should_show_emblems (window)) {
5244 create_emblems_page (window);
5245 }
5246
5247 if (should_show_permissions (window)) {
5248 create_permissions_page (window);
5249 }
5250
5251 if (should_show_open_with (window)) {
5252 create_open_with_page (window);
5253 }
5254
5255 /* append pages from available views */
5256 append_extension_pages (window);
5257
5258 eel_dialog_add_button (GTK_DIALOG (window)((((GtkDialog*) (void *) ((window))))),
5259 _("_Help")dcgettext (((void*)0), "_Help", 5),
5260 "help-browser",
5261 GTK_RESPONSE_HELP);
5262
5263 action_area = gtk_widget_get_parent (eel_dialog_add_button (GTK_DIALOG (window)((((GtkDialog*) (void *) ((window))))),
5264 _("_Close")dcgettext (((void*)0), "_Close", 5),
5265 "window-close",
5266 GTK_RESPONSE_CLOSE));
5267
5268 /* FIXME - HIGificiation, should be done inside GTK+ */
5269 gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkContainer*) (void *) ((gtk_dialog_get_content_area (((
((GtkDialog*) (void *) ((window)))))))))))
, 12);
5270 gtk_container_set_border_width (GTK_CONTAINER (action_area)((((GtkContainer*) (void *) ((action_area))))), 0);
5271 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((window)))))))))))
, 12);
5272
5273 /* Update from initial state */
5274 properties_window_update (window, NULL((void*)0));
5275
5276 return window;
5277}
5278
5279static GList *
5280get_target_file_list (GList *original_files)
5281{
5282 GList *ret;
5283 GList *l;
5284
5285 ret = NULL((void*)0);
5286
5287 for (l = original_files; l != NULL((void*)0); l = l->next) {
5288 CajaFile *target;
5289
5290 target = get_target_file_for_original_file (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))));
5291
5292 ret = g_list_prepend (ret, target);
5293 }
5294
5295 ret = g_list_reverse (ret);
5296
5297 return ret;
5298}
5299
5300static void
5301add_window (FMPropertiesWindow *window)
5302{
5303 if (!is_multi_file_window (window)) {
5304 g_hash_table_insert (windows,
5305 get_original_file (window),
5306 window);
5307 g_object_set_data (G_OBJECT (window)((((GObject*) (void *) ((window))))), "window_key",
5308 get_original_file (window));
5309 }
5310}
5311
5312static void
5313remove_window (FMPropertiesWindow *window)
5314{
5315 gpointer key;
5316
5317 key = g_object_get_data (G_OBJECT (window)((((GObject*) (void *) ((window))))), "window_key");
5318 if (key) {
5319 g_hash_table_remove (windows, key);
5320 }
5321}
5322
5323static GtkWindow *
5324get_existing_window (GList *file_list)
5325{
5326 if (!file_list->next) {
5327 return g_hash_table_lookup (windows, file_list->data);
5328 }
5329
5330 return NULL((void*)0);
5331}
5332
5333static void
5334cancel_create_properties_window_callback (gpointer callback_data)
5335{
5336 remove_pending ((StartupData *)callback_data, TRUE(!(0)), FALSE(0), TRUE(!(0)));
5337}
5338
5339static void
5340parent_widget_destroyed_callback (GtkWidget *widget, gpointer callback_data)
5341{
5342 g_assert (widget == ((StartupData *)callback_data)->parent_widget)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_274
; if (widget == ((StartupData *)callback_data)->parent_widget
) _g_boolean_var_274 = 1; else _g_boolean_var_274 = 0; _g_boolean_var_274
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5342, ((const char*) (__func__)), "widget == ((StartupData *)callback_data)->parent_widget"
); } while (0)
;
5343
5344 remove_pending ((StartupData *)callback_data, TRUE(!(0)), TRUE(!(0)), FALSE(0));
5345}
5346
5347static void
5348cancel_call_when_ready_callback (gpointer key,
5349 gpointer value,
5350 gpointer user_data)
5351{
5352 caja_file_cancel_call_when_ready
5353 (CAJA_FILE (key)((((CajaFile*) (void *) ((key))))),
5354 is_directory_ready_callback,
5355 user_data);
5356}
5357
5358static void
5359remove_pending (StartupData *startup_data,
5360 gboolean cancel_call_when_ready,
5361 gboolean cancel_timed_wait,
5362 gboolean cancel_destroy_handler)
5363{
5364 if (cancel_call_when_ready) {
5365 g_hash_table_foreach (startup_data->pending_files,
5366 cancel_call_when_ready_callback,
5367 startup_data);
5368
5369 }
5370 if (cancel_timed_wait) {
5371 eel_timed_wait_stop
5372 (cancel_create_properties_window_callback, startup_data);
5373 }
5374 if (cancel_destroy_handler) {
5375 g_signal_handlers_disconnect_by_func (startup_data->parent_widget,g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5376 G_CALLBACK (parent_widget_destroyed_callback),g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5377 startup_data)g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
;
5378 }
5379
5380 g_hash_table_remove (pending_lists, startup_data->pending_key);
5381
5382 startup_data_free (startup_data);
5383}
5384
5385static void
5386is_directory_ready_callback (CajaFile *file,
5387 gpointer data)
5388{
5389 StartupData *startup_data;
5390
5391 startup_data = data;
5392
5393 g_hash_table_remove (startup_data->pending_files, file);
5394
5395 if (g_hash_table_size (startup_data->pending_files) == 0) {
5396 FMPropertiesWindow *new_window;
5397
5398 new_window = create_properties_window (startup_data);
5399
5400 add_window (new_window);
5401
5402 remove_pending (startup_data, FALSE(0), TRUE(!(0)), TRUE(!(0)));
5403
5404 gtk_window_present (GTK_WINDOW (new_window)((((GtkWindow*) (void *) ((new_window))))));
5405 }
5406}
5407
5408
5409void
5410fm_properties_window_present (GList *original_files,
5411 GtkWidget *parent_widget)
5412{
5413 GList *l, *next;
5414 GtkWidget *parent_window;
5415 StartupData *startup_data;
5416 GList *target_files;
5417 GtkWindow *existing_window;
5418 char *pending_key;
5419
5420 g_return_if_fail (original_files != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_275
; if (original_files != ((void*)0)) _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__
)), "original_files != NULL"); return; } } while (0)
;
5421 g_return_if_fail (GTK_IS_WIDGET (parent_widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_276
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent_widget)); GType __t = ((gtk_widget_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__)), "GTK_IS_WIDGET (parent_widget)")
; return; } } while (0)
;
5422
5423 /* Create the hash tables first time through. */
5424 if (windows == NULL((void*)0)) {
5425 windows = eel_g_hash_table_new_free_at_exit
5426 (NULL((void*)0), NULL((void*)0), "property windows");
5427 }
5428
5429 if (pending_lists == NULL((void*)0)) {
5430 pending_lists = eel_g_hash_table_new_free_at_exit
5431 (g_str_hash, g_str_equal, "pending property window files");
5432 }
5433
5434 /* Look to see if there's already a window for this file. */
5435 existing_window = get_existing_window (original_files);
5436 if (existing_window != NULL((void*)0)) {
5437 gtk_window_set_screen (existing_window,
5438 gtk_widget_get_screen (parent_widget));
5439 gtk_window_present (existing_window);
5440 return;
5441 }
5442
5443
5444 pending_key = get_pending_key (original_files);
5445
5446 /* Look to see if we're already waiting for a window for this file. */
5447 if (g_hash_table_lookup (pending_lists, pending_key) != NULL((void*)0)) {
5448 return;
5449 }
5450
5451 target_files = get_target_file_list (original_files);
5452
5453 startup_data = startup_data_new (original_files,
5454 target_files,
5455 pending_key,
5456 parent_widget);
5457
5458 caja_file_list_free (target_files);
5459 g_free(pending_key);
5460
5461 /* Wait until we can tell whether it's a directory before showing, since
5462 * some one-time layout decisions depend on that info.
5463 */
5464
5465 g_hash_table_insert (pending_lists, startup_data->pending_key, startup_data->pending_key);
5466 g_signal_connect (parent_widget, "destroy",g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
5467 G_CALLBACK (parent_widget_destroyed_callback), startup_data)g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
;
5468
5469 parent_window = gtk_widget_get_ancestor (parent_widget, GTK_TYPE_WINDOW(gtk_window_get_type ()));
5470
5471 eel_timed_wait_start
5472 (cancel_create_properties_window_callback,
5473 startup_data,
5474 _("Creating Properties window.")dcgettext (((void*)0), "Creating Properties window.", 5),
5475 parent_window == NULL((void*)0) ? NULL((void*)0) : GTK_WINDOW (parent_window)((((GtkWindow*) (void *) ((parent_window))))));
5476
5477
5478 for (l = startup_data->target_files; l != NULL((void*)0); l = next) {
5479 next = l->next;
5480 caja_file_call_when_ready
5481 (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5482 CAJA_FILE_ATTRIBUTE_INFO,
5483 is_directory_ready_callback,
5484 startup_data);
5485 }
5486}
5487
5488static void
5489real_response (GtkDialog *dialog,
5490 int response)
5491{
5492 GError *error = NULL((void*)0);
5493
5494 switch (response) {
5495 case GTK_RESPONSE_HELP:
5496 gtk_show_uri_on_window (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))),
5497 "help:mate-user-guide/goscaja-51",
5498 gtk_get_current_event_time (),
5499 &error);
5500 if (error != NULL((void*)0)) {
5501 eel_show_error_dialog (_("There was an error displaying help.")dcgettext (((void*)0), "There was an error displaying help.",
5)
, error->message,
5502 GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))));
5503 g_error_free (error);
5504 }
5505 break;
5506
5507 case GTK_RESPONSE_NONE:
5508 case GTK_RESPONSE_CLOSE:
5509 case GTK_RESPONSE_DELETE_EVENT:
5510 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
5511 break;
5512
5513 default:
5514 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5514, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5515 break;
5516 }
5517}
5518
5519static void
5520real_destroy (GtkWidget *object)
5521{
5522 FMPropertiesWindow *window;
5523 GList *l;
5524
5525 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) ((object)))));
5526
5527 remove_window (window);
5528
5529 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5530 caja_file_monitor_remove (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))), &window->details->original_files);
5531 }
5532 caja_file_list_free (window->details->original_files);
5533 window->details->original_files = NULL((void*)0);
5534
5535 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5536 caja_file_monitor_remove (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))), &window->details->target_files);
5537 }
5538 caja_file_list_free (window->details->target_files);
5539 window->details->target_files = NULL((void*)0);
5540
5541 caja_file_list_free (window->details->changed_files);
5542 window->details->changed_files = NULL((void*)0);
5543
5544 window->details->name_field = NULL((void*)0);
5545
5546 g_list_free (window->details->emblem_buttons);
5547 window->details->emblem_buttons = NULL((void*)0);
5548
5549 if (window->details->initial_emblems) {
5550 g_hash_table_destroy (window->details->initial_emblems);
5551 window->details->initial_emblems = NULL((void*)0);
5552 }
5553
5554 g_list_free (window->details->permission_buttons);
5555 window->details->permission_buttons = NULL((void*)0);
5556
5557 g_list_free (window->details->permission_combos);
5558 window->details->permission_combos = NULL((void*)0);
5559
5560 if (window->details->initial_permissions) {
5561 g_hash_table_destroy (window->details->initial_permissions);
5562 window->details->initial_permissions = NULL((void*)0);
5563 }
5564
5565 g_list_free (window->details->value_fields);
5566 window->details->value_fields = NULL((void*)0);
5567
5568 if (window->details->update_directory_contents_timeout_id != 0) {
5569 g_source_remove (window->details->update_directory_contents_timeout_id);
5570 window->details->update_directory_contents_timeout_id = 0;
5571 }
5572
5573 if (window->details->update_files_timeout_id != 0) {
5574 g_source_remove (window->details->update_files_timeout_id);
5575 window->details->update_files_timeout_id = 0;
5576 }
5577
5578 GTK_WIDGET_CLASS (fm_properties_window_parent_class)((((GtkWidgetClass*) (void *) ((fm_properties_window_parent_class
)))))
->destroy (object);
5579}
5580
5581static void
5582real_finalize (GObject *object)
5583{
5584 FMPropertiesWindow *window;
5585
5586 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) ((object)))));
5587
5588 g_list_free_full (window->details->mime_list, g_free);
5589
5590 g_free (window->details->pending_name);
5591
5592 G_OBJECT_CLASS (fm_properties_window_parent_class)((((GObjectClass*) (void *) ((fm_properties_window_parent_class
)))))
->finalize (object);
5593}
5594
5595/* converts
5596 * file://foo/foobar/foofoo/bar
5597 * to
5598 * foofoo/bar
5599 * if
5600 * file://foo/foobar
5601 * is the parent
5602 *
5603 * It does not resolve any symlinks.
5604 * */
5605static char *
5606make_relative_uri_from_full (const char *uri,
5607 const char *base_uri)
5608{
5609 g_assert (uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_277
; if (uri != ((void*)0)) _g_boolean_var_277 = 1; else _g_boolean_var_277
= 0; _g_boolean_var_277; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5609, ((const char*
) (__func__)), "uri != NULL"); } while (0)
;
5610 g_assert (base_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_278
; if (base_uri != ((void*)0)) _g_boolean_var_278 = 1; else _g_boolean_var_278
= 0; _g_boolean_var_278; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5610, ((const char*
) (__func__)), "base_uri != NULL"); } while (0)
;
5611
5612 if (g_str_has_prefix (uri, base_uri)(__builtin_constant_p (base_uri)? __extension__ ({ const char
* const __str = (uri); const char * const __prefix = (base_uri
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_279; if (__str == ((void*)0) || __prefix
== ((void*)0)) _g_boolean_var_279 = 1; else _g_boolean_var_279
= 0; _g_boolean_var_279; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (uri, base_uri) )
) {
5613 uri += strlen (base_uri);
5614 if (*uri != '/') {
5615 return NULL((void*)0);
5616 }
5617
5618 while (*uri == '/') {
5619 uri++;
5620 }
5621
5622 if (*uri != '\0') {
5623 return g_strdup (uri)g_strdup_inline (uri);
5624 }
5625 }
5626
5627 return NULL((void*)0);
5628}
5629
5630/* icon selection callback to set the image of the file object to the selected file */
5631static void
5632set_icon (const char* icon_uri, FMPropertiesWindow *properties_window)
5633{
5634 char *icon_path;
5635
5636 g_assert (icon_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_280
; if (icon_uri != ((void*)0)) _g_boolean_var_280 = 1; else _g_boolean_var_280
= 0; _g_boolean_var_280; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5636, ((const char*
) (__func__)), "icon_uri != NULL"); } while (0)
;
5637 g_assert (FM_IS_PROPERTIES_WINDOW (properties_window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_281
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((properties_window)); GType __t = (fm_properties_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_281 = 1; else _g_boolean_var_281 =
0; _g_boolean_var_281; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5637, ((const char*
) (__func__)), "FM_IS_PROPERTIES_WINDOW (properties_window)")
; } while (0)
;
5638
5639 icon_path = g_filename_from_uri (icon_uri, NULL((void*)0), NULL((void*)0));
5640 /* we don't allow remote URIs */
5641 if (icon_path != NULL((void*)0)) {
5642 GList *l;
5643 CajaFile *file = NULL((void*)0);
5644
5645 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
5646 char *file_uri;
5647
5648 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5649
5650 file_uri = caja_file_get_uri (file);
5651
5652 if (caja_file_is_mime_type (file, "application/x-desktop")) {
5653 if (caja_link_local_set_icon (file_uri, icon_path)) {
5654 caja_file_invalidate_attributes (file,
5655 CAJA_FILE_ATTRIBUTE_INFO |
5656 CAJA_FILE_ATTRIBUTE_LINK_INFO);
5657 }
5658 } else {
5659 char *real_icon_uri;
5660
5661 real_icon_uri = make_relative_uri_from_full (icon_uri, file_uri);
5662
5663 if (real_icon_uri == NULL((void*)0)) {
5664 real_icon_uri = g_strdup (icon_uri)g_strdup_inline (icon_uri);
5665 }
5666
5667 caja_file_set_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0), real_icon_uri);
5668 caja_file_set_metadata (file, CAJA_METADATA_KEY_ICON_SCALE"icon-scale", NULL((void*)0), NULL((void*)0));
5669
5670 g_free (real_icon_uri);
5671 }
5672
5673 g_free (file_uri);
5674 }
5675
5676 g_free (icon_path);
5677 }
5678}
5679
5680static void
5681update_preview_callback (GtkFileChooser *icon_chooser,
5682 FMPropertiesWindow *window)
5683{
5684 GdkPixbuf *pixbuf, *scaled_pixbuf;
5685 char *filename;
5686
5687 pixbuf = NULL((void*)0);
5688
5689 filename = gtk_file_chooser_get_filename (icon_chooser);
5690 if (filename != NULL((void*)0)) {
5691 pixbuf = gdk_pixbuf_new_from_file (filename, NULL((void*)0));
5692 }
5693
5694 if (pixbuf != NULL((void*)0)) {
5695 GtkWidget *preview_widget;
5696
5697 preview_widget = gtk_file_chooser_get_preview_widget (icon_chooser);
5698 gtk_file_chooser_set_preview_widget_active (icon_chooser, TRUE(!(0)));
5699
5700 if (gdk_pixbuf_get_width (pixbuf) > PREVIEW_IMAGE_WIDTH96) {
5701 double scale;
5702
5703 scale = (double)gdk_pixbuf_get_height (pixbuf) /
5704 gdk_pixbuf_get_width (pixbuf);
5705
5706 scaled_pixbuf = gdk_pixbuf_scale_simple
5707 (pixbuf,
5708 PREVIEW_IMAGE_WIDTH96,
5709 scale * PREVIEW_IMAGE_WIDTH96,
5710 GDK_INTERP_HYPER);
5711 g_object_unref (pixbuf);
5712 pixbuf = scaled_pixbuf;
5713 }
5714
5715 gtk_image_set_from_pixbuf (GTK_IMAGE (preview_widget)((((GtkImage*) (void *) ((preview_widget))))), pixbuf);
5716 } else {
5717 gtk_file_chooser_set_preview_widget_active (icon_chooser, FALSE(0));
5718 }
5719
5720 g_free (filename);
5721
5722 if (pixbuf != NULL((void*)0)) {
5723 g_object_unref (pixbuf);
5724 }
5725}
5726
5727static void
5728custom_icon_file_chooser_response_cb (GtkDialog *dialog,
5729 gint response,
5730 FMPropertiesWindow *window)
5731{
5732 char *uri;
5733
5734 switch (response) {
5735 case GTK_RESPONSE_NO:
5736 reset_icon (window);
5737 break;
5738
5739 case GTK_RESPONSE_OK:
5740 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))));
5741 set_icon (uri, window);
5742 g_free (uri);
5743 break;
5744
5745 default:
5746 break;
5747 }
5748
5749 gtk_widget_hide (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
5750}
5751
5752static void
5753select_image_button_callback (GtkWidget *widget,
5754 FMPropertiesWindow *window)
5755{
5756 GtkWidget *dialog;
5757 GList *l;
5758 CajaFile *file;
5759 char *image_path;
5760 gboolean revert_is_sensitive;
5761
5762 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_282 = 1; else _g_boolean_var_282 = 0; _g_boolean_var_282
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5762, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
5763
5764 dialog = window->details->icon_chooser;
5765
5766 if (dialog == NULL((void*)0)) {
5767 GtkWidget *preview;
5768 GtkFileFilter *filter;
5769
5770 dialog = eel_file_chooser_dialog_new (_("Select Custom Icon")dcgettext (((void*)0), "Select Custom Icon", 5), GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
5771 GTK_FILE_CHOOSER_ACTION_OPEN,
5772 "document-revert", GTK_RESPONSE_NO,
5773 "process-stop", GTK_RESPONSE_CANCEL,
5774 "document-open", GTK_RESPONSE_OK,
5775 NULL((void*)0));
5776 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), ICONDIR"/usr/local/share/icons", NULL((void*)0));
5777 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), PIXMAPDIR"/usr/local/share/pixmaps", NULL((void*)0));
5778 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
5779
5780 filter = gtk_file_filter_new ();
5781 gtk_file_filter_add_pixbuf_formats (filter);
5782 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), filter);
5783
5784 preview = gtk_image_new ();
5785 gtk_widget_set_size_request (preview, PREVIEW_IMAGE_WIDTH96, -1);
5786 gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), preview);
5787 gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), FALSE(0));
5788 gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), FALSE(0));
5789
5790 g_signal_connect (dialog, "update-preview",g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
5791 G_CALLBACK (update_preview_callback), window)g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
5792
5793 window->details->icon_chooser = dialog;
5794
5795 g_object_add_weak_pointer (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))),
5796 (gpointer *) &window->details->icon_chooser);
5797 }
5798
5799 /* it's likely that the user wants to pick an icon that is inside a local directory */
5800 if (g_list_length (window->details->original_files) == 1) {
5801 file = CAJA_FILE (window->details->original_files->data)((((CajaFile*) (void *) ((window->details->original_files
->data)))))
;
5802
5803 if (caja_file_is_directory (file)) {
5804 char *uri;
5805
5806 uri = caja_file_get_uri (file);
5807
5808 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
5809 if (image_path != NULL((void*)0)) {
5810 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), image_path);
5811 g_free (image_path);
5812 }
5813
5814 g_free (uri);
5815 }
5816 }
5817
5818 revert_is_sensitive = FALSE(0);
5819 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5820 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5821 image_path = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
5822 revert_is_sensitive = (image_path != NULL((void*)0));
5823 g_free (image_path);
5824
5825 if (revert_is_sensitive) {
5826 break;
5827 }
5828 }
5829 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_NO, revert_is_sensitive);
5830
5831 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
5832 G_CALLBACK (custom_icon_file_chooser_response_cb), window)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
;
5833 gtk_widget_show (dialog);
5834}
5835
5836static void
5837fm_properties_window_class_init (FMPropertiesWindowClass *class)
5838{
5839 GtkBindingSet *binding_set;
5840
5841 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = real_finalize;
5842
5843 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->destroy = real_destroy;
5844
5845 GTK_DIALOG_CLASS (class)((((GtkDialogClass*) (void *) ((class)))))->response = real_response;
5846
5847 binding_set = gtk_binding_set_by_class (class);
5848 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape0xff1b, 0,
5849 "close", 0);
5850}
5851
5852static void
5853fm_properties_window_init (FMPropertiesWindow *window)
5854{
5855 window->details = fm_properties_window_get_instance_private (window);
5856}
diff --git a/2024-07-29-023715-6438-1/report-79066c.html b/2024-07-29-023715-6438-1/report-79066c.html new file mode 100644 index 000000000..681b198a6 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-79066c.html @@ -0,0 +1,3222 @@ + + + +caja-window-manage-views.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-window-manage-views.c
Warning:line 2219, column 104
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'error')
+ +

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 caja-window-manage-views.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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-window-manage-views.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 * Caja
5 *
6 * Copyright (C) 1999, 2000 Red Hat, Inc.
7 * Copyright (C) 1999, 2000, 2001 Eazel, Inc.
8 *
9 * Caja is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * Caja 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 GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 * Authors: Elliot Lee <sopwith@redhat.com>
24 * John Sullivan <sullivan@eazel.com>
25 * Darin Adler <darin@bentspoon.com>
26 */
27
28#include <config.h>
29
30#include <gtk/gtk.h>
31#include <gdk/gdkx.h>
32#include <glib/gi18n.h>
33
34#include <eel/eel-accessibility.h>
35#include <eel/eel-debug.h>
36#include <eel/eel-gdk-extensions.h>
37#include <eel/eel-glib-extensions.h>
38#include <eel/eel-gtk-extensions.h>
39#include <eel/eel-gtk-macros.h>
40#include <eel/eel-stock-dialogs.h>
41#include <eel/eel-string.h>
42#include <eel/eel-vfs-extensions.h>
43
44#include <libcaja-private/caja-debug-log.h>
45#include <libcaja-private/caja-extensions.h>
46#include <libcaja-private/caja-file-attributes.h>
47#include <libcaja-private/caja-file-utilities.h>
48#include <libcaja-private/caja-file.h>
49#include <libcaja-private/caja-global-preferences.h>
50#include <libcaja-private/caja-metadata.h>
51#include <libcaja-private/caja-mime-actions.h>
52#include <libcaja-private/caja-module.h>
53#include <libcaja-private/caja-monitor.h>
54#include <libcaja-private/caja-search-directory.h>
55#include <libcaja-private/caja-view-factory.h>
56#include <libcaja-private/caja-window-info.h>
57#include <libcaja-private/caja-window-slot-info.h>
58#include <libcaja-private/caja-autorun.h>
59
60#include <libcaja-extension/caja-location-widget-provider.h>
61
62#include "caja-window-manage-views.h"
63#include "caja-actions.h"
64#include "caja-application.h"
65#include "caja-location-bar.h"
66#include "caja-search-bar.h"
67#include "caja-pathbar.h"
68#include "caja-window-private.h"
69#include "caja-window-slot.h"
70#include "caja-navigation-window-slot.h"
71#include "caja-trash-bar.h"
72#include "caja-x-content-bar.h"
73#include "caja-navigation-window-pane.h"
74
75/* FIXME bugzilla.gnome.org 41243:
76 * We should use inheritance instead of these special cases
77 * for the desktop window.
78 */
79#include "caja-desktop-window.h"
80
81/* This number controls a maximum character count for a URL that is
82 * displayed as part of a dialog. It's fairly arbitrary -- big enough
83 * to allow most "normal" URIs to display in full, but small enough to
84 * prevent the dialog from getting insanely wide.
85 */
86#define MAX_URI_IN_DIALOG_LENGTH60 60
87
88static void begin_location_change (CajaWindowSlot *slot,
89 GFile *location,
90 GFile *previous_location,
91 GList *new_selection,
92 CajaLocationChangeType type,
93 guint distance,
94 const char *scroll_pos,
95 CajaWindowGoToCallback callback,
96 gpointer user_data);
97static void free_location_change (CajaWindowSlot *slot);
98static void end_location_change (CajaWindowSlot *slot);
99static void cancel_location_change (CajaWindowSlot *slot);
100static void got_file_info_for_view_selection_callback (CajaFile *file,
101 gpointer callback_data);
102static void create_content_view (CajaWindowSlot *slot,
103 const char *view_id);
104static void display_view_selection_failure (CajaWindow *window,
105 CajaFile *file,
106 GFile *location,
107 GError *error);
108static void load_new_location (CajaWindowSlot *slot,
109 GFile *location,
110 GList *selection,
111 gboolean tell_current_content_view,
112 gboolean tell_new_content_view);
113static void location_has_really_changed (CajaWindowSlot *slot);
114static void update_for_new_location (CajaWindowSlot *slot);
115
116void
117caja_window_report_selection_changed (CajaWindowInfo *window)
118{
119 if (window->details->temporarily_ignore_view_signals)
120 {
121 return;
122 }
123
124 g_signal_emit_by_name (window, "selection_changed");
125}
126
127/* set_displayed_location:
128 */
129static void
130set_displayed_location (CajaWindowSlot *slot, GFile *location)
131{
132 gboolean recreate;
133
134 if (slot->current_location_bookmark == NULL((void*)0) || location == NULL((void*)0))
135 {
136 recreate = TRUE(!(0));
137 }
138 else
139 {
140 GFile *bookmark_location;
141
142 bookmark_location = caja_bookmark_get_location (slot->current_location_bookmark);
143 recreate = !g_file_equal (bookmark_location, location);
144 g_object_unref (bookmark_location);
145 }
146
147 if (recreate)
148 {
149 char *name;
150
151 /* We've changed locations, must recreate bookmark for current location. */
152 if (slot->last_location_bookmark != NULL((void*)0))
153 {
154 g_object_unref (slot->last_location_bookmark);
155 }
156 slot->last_location_bookmark = slot->current_location_bookmark;
157 name = g_file_get_basename (location);
158 slot->current_location_bookmark = (location == NULL((void*)0)) ? NULL((void*)0)
159 : caja_bookmark_new (location, name, FALSE(0), NULL((void*)0));
160 g_free (name);
161 }
162}
163
164static void
165check_bookmark_location_matches (CajaBookmark *bookmark, GFile *location)
166{
167 GFile *bookmark_location;
168
169 bookmark_location = caja_bookmark_get_location (bookmark);
170 if (!g_file_equal (location, bookmark_location))
171 {
172 char *bookmark_uri, *uri;
173
174 bookmark_uri = g_file_get_uri (bookmark_location);
175 uri = g_file_get_uri (location);
176 g_warning ("bookmark uri is %s, but expected %s", bookmark_uri, uri);
177 g_free (uri);
178 g_free (bookmark_uri);
179 }
180 g_object_unref (bookmark_location);
181}
182
183/* Debugging function used to verify that the last_location_bookmark
184 * is in the state we expect when we're about to use it to update the
185 * Back or Forward list.
186 */
187static void
188check_last_bookmark_location_matches_slot (CajaWindowSlot *slot)
189{
190 check_bookmark_location_matches (slot->last_location_bookmark,
191 slot->location);
192}
193
194static void
195handle_go_back (CajaNavigationWindowSlot *navigation_slot,
196 GFile *location)
197{
198 CajaWindowSlot *slot;
199 guint i;
200 GList *link;
201 CajaBookmark *bookmark = NULL((void*)0);
202
203 slot = CAJA_WINDOW_SLOT (navigation_slot)((((CajaWindowSlot*) (void *) ((navigation_slot)))));
204
205 /* Going back. Move items from the back list to the forward list. */
206 g_assert (g_list_length (navigation_slot->back_list) > slot->location_change_distance)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_53
; if (g_list_length (navigation_slot->back_list) > slot
->location_change_distance) _g_boolean_var_53 = 1; else _g_boolean_var_53
= 0; _g_boolean_var_53; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 206, ((const char
*) (__func__)), "g_list_length (navigation_slot->back_list) > slot->location_change_distance"
); } while (0)
;
207 check_bookmark_location_matches (CAJA_BOOKMARK (g_list_nth_data (navigation_slot->back_list,((((CajaBookmark*) (void *) ((g_list_nth_data (navigation_slot
->back_list, slot->location_change_distance))))))
208 slot->location_change_distance))((((CajaBookmark*) (void *) ((g_list_nth_data (navigation_slot
->back_list, slot->location_change_distance))))))
,
209 location);
210 g_assert (slot->location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_54
; if (slot->location != ((void*)0)) _g_boolean_var_54 = 1;
else _g_boolean_var_54 = 0; _g_boolean_var_54; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 210, ((const char*) (__func__)), "slot->location != NULL"
); } while (0)
;
211
212 /* Move current location to Forward list */
213
214 check_last_bookmark_location_matches_slot (slot);
215
216 /* Use the first bookmark in the history list rather than creating a new one. */
217 navigation_slot->forward_list = g_list_prepend (navigation_slot->forward_list,
218 slot->last_location_bookmark);
219 g_object_ref (navigation_slot->forward_list->data)((__typeof__ (navigation_slot->forward_list->data)) (g_object_ref
) (navigation_slot->forward_list->data))
;
220
221 /* Move extra links from Back to Forward list */
222 for (i = 0; i < slot->location_change_distance; ++i)
223 {
224 bookmark = CAJA_BOOKMARK (navigation_slot->back_list->data)((((CajaBookmark*) (void *) ((navigation_slot->back_list->
data)))))
;
225 navigation_slot->back_list =
226 g_list_remove (navigation_slot->back_list, bookmark);
227 navigation_slot->forward_list =
228 g_list_prepend (navigation_slot->forward_list, bookmark);
229 }
230
231 /* One bookmark falls out of back/forward lists and becomes viewed location */
232 link = navigation_slot->back_list;
233 navigation_slot->back_list = g_list_remove_link (navigation_slot->back_list, link);
234 g_object_unref (link->data);
235 g_list_free_1 (link);
236}
237
238static void
239handle_go_forward (CajaNavigationWindowSlot *navigation_slot,
240 GFile *location)
241{
242 CajaWindowSlot *slot;
243 guint i;
244 GList *link;
245 CajaBookmark *bookmark = NULL((void*)0);
246
247 slot = CAJA_WINDOW_SLOT (navigation_slot)((((CajaWindowSlot*) (void *) ((navigation_slot)))));
248
249 /* Going forward. Move items from the forward list to the back list. */
250 g_assert (g_list_length (navigation_slot->forward_list) > slot->location_change_distance)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_55
; if (g_list_length (navigation_slot->forward_list) > slot
->location_change_distance) _g_boolean_var_55 = 1; else _g_boolean_var_55
= 0; _g_boolean_var_55; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 250, ((const char
*) (__func__)), "g_list_length (navigation_slot->forward_list) > slot->location_change_distance"
); } while (0)
;
251 check_bookmark_location_matches (CAJA_BOOKMARK (g_list_nth_data (navigation_slot->forward_list,((((CajaBookmark*) (void *) ((g_list_nth_data (navigation_slot
->forward_list, slot->location_change_distance))))))
252 slot->location_change_distance))((((CajaBookmark*) (void *) ((g_list_nth_data (navigation_slot
->forward_list, slot->location_change_distance))))))
,
253 location);
254 g_assert (slot->location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_56
; if (slot->location != ((void*)0)) _g_boolean_var_56 = 1;
else _g_boolean_var_56 = 0; _g_boolean_var_56; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 254, ((const char*) (__func__)), "slot->location != NULL"
); } while (0)
;
255
256 /* Move current location to Back list */
257 check_last_bookmark_location_matches_slot (slot);
258
259 /* Use the first bookmark in the history list rather than creating a new one. */
260 navigation_slot->back_list = g_list_prepend (navigation_slot->back_list,
261 slot->last_location_bookmark);
262 g_object_ref (navigation_slot->back_list->data)((__typeof__ (navigation_slot->back_list->data)) (g_object_ref
) (navigation_slot->back_list->data))
;
263
264 /* Move extra links from Forward to Back list */
265 for (i = 0; i < slot->location_change_distance; ++i)
266 {
267 bookmark = CAJA_BOOKMARK (navigation_slot->forward_list->data)((((CajaBookmark*) (void *) ((navigation_slot->forward_list
->data)))))
;
268 navigation_slot->forward_list =
269 g_list_remove (navigation_slot->back_list, bookmark);
270 navigation_slot->back_list =
271 g_list_prepend (navigation_slot->forward_list, bookmark);
272 }
273
274 /* One bookmark falls out of back/forward lists and becomes viewed location */
275 link = navigation_slot->forward_list;
276 navigation_slot->forward_list = g_list_remove_link (navigation_slot->forward_list, link);
277 g_object_unref (link->data);
278 g_list_free_1 (link);
279}
280
281static void
282handle_go_elsewhere (CajaWindowSlot *slot, GFile *location)
283{
284 if (CAJA_IS_NAVIGATION_WINDOW_SLOT (slot)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(slot)); GType __t = ((caja_navigation_window_slot_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; }))))
)
285 {
286 CajaNavigationWindowSlot *navigation_slot;
287
288 navigation_slot = CAJA_NAVIGATION_WINDOW_SLOT (slot)((((CajaNavigationWindowSlot*) (void *) ((slot)))));
289
290 /* Clobber the entire forward list, and move displayed location to back list */
291 caja_navigation_window_slot_clear_forward_list (navigation_slot);
292
293 if (slot->location != NULL((void*)0))
294 {
295 /* If we're returning to the same uri somehow, don't put this uri on back list.
296 * This also avoids a problem where set_displayed_location
297 * didn't update last_location_bookmark since the uri didn't change.
298 */
299 if (!g_file_equal (slot->location, location))
300 {
301 /* Store bookmark for current location in back list, unless there is no current location */
302 check_last_bookmark_location_matches_slot (slot);
303 /* Use the first bookmark in the history list rather than creating a new one. */
304 navigation_slot->back_list = g_list_prepend (navigation_slot->back_list,
305 slot->last_location_bookmark);
306 g_object_ref (navigation_slot->back_list->data)((__typeof__ (navigation_slot->back_list->data)) (g_object_ref
) (navigation_slot->back_list->data))
;
307 }
308 }
309 }
310}
311
312void
313caja_window_update_up_button (CajaWindow *window)
314{
315 CajaWindowSlot *slot;
316 gboolean allowed;
317 GFile *parent;
318
319 slot = window->details->active_pane->active_slot;
320
321 allowed = FALSE(0);
322 if (slot->location != NULL((void*)0))
323 {
324 parent = g_file_get_parent (slot->location);
325 allowed = parent != NULL((void*)0);
326 if (parent != NULL((void*)0))
327 {
328 g_object_unref (parent);
329 }
330 }
331
332 caja_window_allow_up (window, allowed);
333}
334
335static void
336viewed_file_changed_callback (CajaFile *file,
337 CajaWindowSlot *slot)
338{
339 CajaWindow *window;
340 GFile *new_location;
341 gboolean is_in_trash, was_in_trash;
342
343 window = slot->pane->window;
344
345 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_57
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_57
= 1; else _g_boolean_var_57 = 0; _g_boolean_var_57; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 345, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
346 g_assert (CAJA_IS_WINDOW_PANE (slot->pane))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_58
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot->pane)); GType __t = ((caja_window_pane_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_assertion_message_expr (
((gchar*) 0), "caja-window-manage-views.c", 346, ((const char
*) (__func__)), "CAJA_IS_WINDOW_PANE (slot->pane)"); } while
(0)
;
347 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_59
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_59
= 1; else _g_boolean_var_59 = 0; _g_boolean_var_59; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 347, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)")
; } while (0)
;
348
349 g_assert (file == slot->viewed_file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_60
; if (file == slot->viewed_file) _g_boolean_var_60 = 1; else
_g_boolean_var_60 = 0; _g_boolean_var_60; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 349, ((const char
*) (__func__)), "file == slot->viewed_file"); } while (0)
;
350
351 if (!caja_file_is_not_yet_confirmed (file))
352 {
353 slot->viewed_file_seen = TRUE(!(0));
354 }
355
356 was_in_trash = slot->viewed_file_in_trash;
357
358 slot->viewed_file_in_trash = is_in_trash = caja_file_is_in_trash (file);
359
360 /* Close window if the file it's viewing has been deleted or moved to trash. */
361 if (caja_file_is_gone (file) || (is_in_trash && !was_in_trash))
362 {
363 /* Don't close the window in the case where the
364 * file was never seen in the first place.
365 */
366 if (slot->viewed_file_seen)
367 {
368 /* Detecting a file is gone may happen in the
369 * middle of a pending location change, we
370 * need to cancel it before closing the window
371 * or things break.
372 */
373 /* FIXME: It makes no sense that this call is
374 * needed. When the window is destroyed, it
375 * calls caja_window_manage_views_destroy,
376 * which calls free_location_change, which
377 * should be sufficient. Also, if this was
378 * really needed, wouldn't it be needed for
379 * all other caja_window_close callers?
380 */
381 end_location_change (slot);
382
383 if (CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
)
384 {
385 /* auto-show existing parent. */
386 GFile *go_to_file, *parent, *location;
387
388 go_to_file = NULL((void*)0);
389 location = caja_file_get_location (file);
390 parent = g_file_get_parent (location);
391 g_object_unref (location);
392 if (parent)
393 {
394 go_to_file = caja_find_existing_uri_in_hierarchy (parent);
395 g_object_unref (parent);
396 }
397
398 if (go_to_file != NULL((void*)0))
399 {
400 /* the path bar URI will be set to go_to_uri immediately
401 * in begin_location_change, but we don't want the
402 * inexistant children to show up anymore */
403 if (slot == slot->pane->active_slot)
404 {
405 /* multiview-TODO also update CajaWindowSlot
406 * [which as of writing doesn't save/store any path bar state]
407 */
408 caja_path_bar_clear_buttons (CAJA_PATH_BAR (CAJA_NAVIGATION_WINDOW_PANE (slot->pane)->path_bar)((((CajaPathBar*) (void *) ((((((CajaNavigationWindowPane*) (
void *) ((slot->pane)))))->path_bar)))))
);
409 }
410
411 caja_window_slot_go_to (slot, go_to_file, FALSE)caja_window_slot_open_location_full(slot, go_to_file, CAJA_WINDOW_OPEN_ACCORDING_TO_MODE
, ((0) ? CAJA_WINDOW_OPEN_FLAG_NEW_TAB : 0), ((void*)0), ((void
*)0), ((void*)0))
;
412 g_object_unref (go_to_file);
413 }
414 else
415 {
416 caja_window_slot_go_home (slot, FALSE(0));
417 }
418 }
419 else
420 {
421 caja_window_close (window);
422 }
423 }
424 }
425 else
426 {
427 new_location = caja_file_get_location (file);
428
429 /* If the file was renamed, update location and/or
430 * title. */
431 if (!g_file_equal (new_location,
432 slot->location))
433 {
434 g_object_unref (slot->location);
435 slot->location = new_location;
436 if (slot == slot->pane->active_slot)
437 {
438 caja_window_pane_sync_location_widgets (slot->pane);
439 }
440 }
441 else
442 {
443 /* TODO?
444 * why do we update title & icon at all in this case? */
445 g_object_unref (new_location);
446 }
447
448 caja_window_slot_update_title (slot);
449 caja_window_slot_update_icon (slot);
450 }
451}
452
453static void
454update_history (CajaWindowSlot *slot,
455 CajaLocationChangeType type,
456 GFile *new_location)
457{
458 switch (type)
459 {
460 case CAJA_LOCATION_CHANGE_STANDARD:
461 case CAJA_LOCATION_CHANGE_FALLBACK:
462 caja_window_slot_add_current_location_to_history_list (slot);
463 handle_go_elsewhere (slot, new_location);
464 return;
465 case CAJA_LOCATION_CHANGE_RELOAD:
466 /* for reload there is no work to do */
467 return;
468 case CAJA_LOCATION_CHANGE_BACK:
469 caja_window_slot_add_current_location_to_history_list (slot);
470 handle_go_back (CAJA_NAVIGATION_WINDOW_SLOT (slot)((((CajaNavigationWindowSlot*) (void *) ((slot))))), new_location);
471 return;
472 case CAJA_LOCATION_CHANGE_FORWARD:
473 caja_window_slot_add_current_location_to_history_list (slot);
474 handle_go_forward (CAJA_NAVIGATION_WINDOW_SLOT (slot)((((CajaNavigationWindowSlot*) (void *) ((slot))))), new_location);
475 return;
476 case CAJA_LOCATION_CHANGE_REDIRECT:
477 /* for the redirect case, the caller can do the updating */
478 return;
479 }
480 g_return_if_fail (FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_61
; if ((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__)), "FALSE"); return;
} } while (0)
;
481}
482
483static void
484cancel_viewed_file_changed_callback (CajaWindowSlot *slot)
485{
486 CajaFile *file;
487
488 file = slot->viewed_file;
489 if (file != NULL((void*)0))
490 {
491 g_signal_handlers_disconnect_by_func (G_OBJECT (file),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
((file)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (viewed_file_changed_callback
))), (slot))
492 G_CALLBACK (viewed_file_changed_callback),g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
((file)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (viewed_file_changed_callback
))), (slot))
493 slot)g_signal_handlers_disconnect_matched ((((((GObject*) (void *)
((file)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (viewed_file_changed_callback
))), (slot))
;
494 caja_file_monitor_remove (file, &slot->viewed_file);
495 }
496}
497
498static void
499new_window_show_callback (GtkWidget *widget,
500 gpointer user_data)
501{
502 CajaWindow *window;
503
504 window = CAJA_WINDOW (user_data)((((CajaWindow*) (void *) ((user_data)))));
505
506 caja_window_close (window);
507
508 g_signal_handlers_disconnect_by_func (widget,g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (new_window_show_callback))), (user_data))
509 G_CALLBACK (new_window_show_callback),g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (new_window_show_callback))), (user_data))
510 user_data)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (new_window_show_callback))), (user_data))
;
511}
512
513
514void
515caja_window_slot_open_location_full (CajaWindowSlot *slot,
516 GFile *location,
517 CajaWindowOpenMode mode,
518 CajaWindowOpenFlags flags,
519 GList *new_selection,
520 CajaWindowGoToCallback callback,
521 gpointer user_data)
522{
523 CajaWindow *window;
524 CajaWindow *target_window;
525 CajaWindowPane *pane;
526 CajaWindowSlot *target_slot;
527 CajaWindowOpenFlags slot_flags;
528 gboolean existing = FALSE(0);
529 GFile *old_location;
530 char *old_uri, *new_uri;
531 GList *l;
532 gboolean target_navigation = FALSE(0);
533 gboolean target_same = FALSE(0);
534 gboolean is_desktop = FALSE(0);
535 gboolean is_navigation = FALSE(0);
536
537 window = slot->pane->window;
538
539 target_window = NULL((void*)0);
540 target_slot = NULL((void*)0);
541
542 old_uri = caja_window_slot_get_location_uri (slot);
543 if (old_uri == NULL((void*)0))
544 {
545 old_uri = g_strdup ("(none)")g_strdup_inline ("(none)");
546 }
547 new_uri = g_file_get_uri (location);
548 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
549 "window %p open location: old=\"%s\", new=\"%s\"",
550 window,
551 old_uri,
552 new_uri);
553 g_free (old_uri);
554 g_free (new_uri);
555
556 g_assert (!((flags & CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 &&do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_62
; if (!((flags & CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 &&
(flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0)) _g_boolean_var_62
= 1; else _g_boolean_var_62 = 0; _g_boolean_var_62; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 557, ((const char*) (__func__)), "!((flags & CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 && (flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0)"
); } while (0)
557 (flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_62
; if (!((flags & CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 &&
(flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0)) _g_boolean_var_62
= 1; else _g_boolean_var_62 = 0; _g_boolean_var_62; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 557, ((const char*) (__func__)), "!((flags & CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 && (flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0)"
); } while (0)
;
558
559 is_desktop = CAJA_IS_DESKTOP_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_desktop_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; }))))
;
560 is_navigation = CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
;
561 target_same = is_desktop &&
562 !caja_desktop_window_loaded (CAJA_DESKTOP_WINDOW (window)((((CajaDesktopWindow*) (void *) ((window))))));
563
564 old_location = caja_window_slot_get_location (slot);
565
566 switch (mode)
567 {
568 case CAJA_WINDOW_OPEN_ACCORDING_TO_MODE :
569 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
570 /* always use browser: if we're on the desktop the target is a new navigation window,
571 * otherwise it's the same window.
572 */
573 if (is_desktop) {
574 new_uri = g_file_get_uri (location);
575 if (g_str_has_prefix (new_uri, EEL_DESKTOP_URI)(__builtin_constant_p ("x-caja-desktop:")? __extension__ ({ const
char * const __str = (new_uri); const char * const __prefix =
("x-caja-desktop:"); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_63; if (__str == ((void
*)0) || __prefix == ((void*)0)) _g_boolean_var_63 = 1; else _g_boolean_var_63
= 0; _g_boolean_var_63; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (new_uri, "x-caja-desktop:"
) )
)
576 target_same = TRUE(!(0));
577 else
578 target_navigation = TRUE(!(0));
579 g_free (new_uri);
580 } else {
581 target_same = TRUE(!(0));
582 }
583 } else if (flags & CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW) {
584 /* if it's specified to open a new window, and we're not using spatial,
585 * the target is a navigation.
586 */
587 target_navigation = TRUE(!(0));
588 } else if (is_navigation) {
589 target_same = TRUE(!(0));
590 }
591 break;
592 case CAJA_WINDOW_OPEN_IN_NAVIGATION :
593 target_navigation = TRUE(!(0));
594 break;
595 default :
596 g_critical ("Unknown open location mode");
597 g_object_unref (old_location);
598 return;
599 }
600
601 /* now get/create the window according to the mode */
602 if (target_same) {
603 target_window = window;
604 } else if (target_navigation) {
605 target_window = caja_application_create_navigation_window
606 (window->application,
607 gtk_window_get_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window)))))));
608 } else {
609 target_window = caja_application_get_spatial_window
610 (window->application,
611 window,
612 NULL((void*)0),
613 location,
614 gtk_window_get_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window)))))),
615 &existing);
616 }
617
618 /* if the spatial window is already showing, present it and set the
619 * new selection, if present.
620 */
621 if (existing) {
622 target_slot = target_window->details->active_pane->active_slot;
623
624 gtk_window_present (GTK_WINDOW (target_window)((((GtkWindow*) (void *) ((target_window))))));
625
626 if (new_selection != NULL((void*)0) && slot->content_view != NULL((void*)0)) {
627 caja_view_set_selection (target_slot->content_view, new_selection);
628 }
629
630 /* call the callback successfully */
631 if (callback != NULL((void*)0)) {
632 callback (window, NULL((void*)0), user_data);
633 }
634
635 return;
636 }
637
638 g_assert (target_window != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_64
; if (target_window != ((void*)0)) _g_boolean_var_64 = 1; else
_g_boolean_var_64 = 0; _g_boolean_var_64; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 638, ((const char
*) (__func__)), "target_window != NULL"); } while (0)
;
639
640 if ((flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0 &&
641 CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
)
642 {
643 g_assert (target_window == window)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_65
; if (target_window == window) _g_boolean_var_65 = 1; else _g_boolean_var_65
= 0; _g_boolean_var_65; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 643, ((const char
*) (__func__)), "target_window == window"); } while (0)
;
644
645 int new_slot_position;
646
647 slot_flags = 0;
648
649 new_slot_position = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_NEW_TAB_POSITION"tabs-open-position");
650 if (new_slot_position == CAJA_NEW_TAB_POSITION_END)
651 {
652 slot_flags = CAJA_WINDOW_OPEN_SLOT_APPEND;
653 }
654
655 target_slot = caja_window_open_slot (window->details->active_pane, slot_flags);
656 }
657
658 if ((flags & CAJA_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0)
659 {
660 if (CAJA_IS_SPATIAL_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_spatial_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; }))))
&& !CAJA_IS_DESKTOP_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_desktop_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; }))))
)
661 {
662 if (gtk_widget_get_visible (GTK_WIDGET (target_window)((((GtkWidget*) (void *) ((target_window)))))))
663 {
664 caja_window_close (window);
665 }
666 else
667 {
668 g_signal_connect_object (target_window,
669 "show",
670 G_CALLBACK (new_window_show_callback)((GCallback) (new_window_show_callback)),
671 window,
672 G_CONNECT_AFTER);
673 }
674 }
675 }
676
677 if (target_slot == NULL((void*)0))
678 {
679 if (target_window == window)
680 {
681 target_slot = slot;
682 }
683 else
684 {
685 target_slot = target_window->details->active_pane->active_slot;
686 }
687 }
688
689 if (!(is_desktop && target_same) && (target_window == window && target_slot == slot &&
690 old_location && g_file_equal (old_location, location))) {
691
692 if (callback != NULL((void*)0)) {
693 callback (window, NULL((void*)0), user_data);
694 }
695
696 g_object_unref (old_location);
697 return;
698 }
699
700 begin_location_change (target_slot, location, old_location, new_selection,
701 (is_desktop && target_same) ? CAJA_LOCATION_CHANGE_RELOAD : CAJA_LOCATION_CHANGE_STANDARD, 0, NULL((void*)0), callback, user_data);
702
703 /* Additionally, load this in all slots that have no location, this means
704 we load both panes in e.g. a newly opened dual pane window. */
705 for (l = target_window->details->panes; l != NULL((void*)0); l = l->next)
706 {
707 pane = l->data;
708 slot = pane->active_slot;
709 if (slot->location == NULL((void*)0) && slot->pending_location == NULL((void*)0)) {
710 begin_location_change (slot, location, old_location, new_selection,
711 CAJA_LOCATION_CHANGE_STANDARD, 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
712 }
713 }
714
715 if (old_location)
716 {
717 g_object_unref (old_location);
718 }
719}
720
721void
722caja_window_slot_open_location (CajaWindowSlot *slot,
723 GFile *location,
724 gboolean close_behind)
725{
726 CajaWindowOpenFlags flags;
727
728 flags = 0;
729 if (close_behind)
730 {
731 flags = CAJA_WINDOW_OPEN_FLAG_CLOSE_BEHIND;
732 }
733
734 caja_window_slot_open_location_full (slot, location,
735 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
736 flags, NULL((void*)0), NULL((void*)0), NULL((void*)0));
737}
738
739void
740caja_window_slot_open_location_with_selection (CajaWindowSlot *slot,
741 GFile *location,
742 GList *selection,
743 gboolean close_behind)
744{
745 CajaWindowOpenFlags flags;
746
747 flags = 0;
748 if (close_behind)
749 {
750 flags = CAJA_WINDOW_OPEN_FLAG_CLOSE_BEHIND;
751 }
752 caja_window_slot_open_location_full (slot, location,
753 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
754 flags, selection, NULL((void*)0), NULL((void*)0));
755}
756
757
758void
759caja_window_slot_go_home (CajaWindowSlot *slot, gboolean new_tab)
760{
761 GFile *home;
762 CajaWindowOpenFlags flags;
763
764 g_return_if_fail (CAJA_IS_WINDOW_SLOT (slot))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_66
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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__)), "CAJA_IS_WINDOW_SLOT (slot)"); return; } } while
(0)
;
765
766 if (new_tab)
767 {
768 flags = CAJA_WINDOW_OPEN_FLAG_NEW_TAB;
769 }
770 else
771 {
772 flags = 0;
773 }
774
775 home = g_file_new_for_path (g_get_home_dir ());
776 caja_window_slot_open_location_full (slot, home,
777 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
778 flags, NULL((void*)0), NULL((void*)0), NULL((void*)0));
779 g_object_unref (home);
780}
781
782static char *
783caja_window_slot_get_view_error_label (CajaWindowSlot *slot)
784{
785 const CajaViewInfo *info;
786
787 info = caja_view_factory_lookup (caja_window_slot_get_content_view_id (slot));
788
789 return g_strdup (info->error_label)g_strdup_inline (info->error_label);
790}
791
792static char *
793caja_window_slot_get_view_startup_error_label (CajaWindowSlot *slot)
794{
795 const CajaViewInfo *info;
796
797 info = caja_view_factory_lookup (caja_window_slot_get_content_view_id (slot));
798
799 return g_strdup (info->startup_error_label)g_strdup_inline (info->startup_error_label);
800}
801
802static void
803report_current_content_view_failure_to_user (CajaWindowSlot *slot)
804{
805 CajaWindow *window;
806 char *message;
807
808 window = slot->pane->window;
809
810 message = caja_window_slot_get_view_startup_error_label (slot);
811 eel_show_error_dialog (message,
812 _("You can choose another view or go to a different location.")dcgettext (((void*)0), "You can choose another view or go to a different location."
, 5)
,
813 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
814 g_free (message);
815}
816
817static void
818report_nascent_content_view_failure_to_user (CajaWindowSlot *slot,
819 CajaView *view)
820{
821 CajaWindow *window;
822 char *message;
823
824 window = slot->pane->window;
825
826 /* TODO? why are we using the current view's error label here, instead of the next view's?
827 * This behavior has already been present in pre-slot days.
828 */
829 message = caja_window_slot_get_view_error_label (slot);
830 eel_show_error_dialog (message,
831 _("The location cannot be displayed with this viewer.")dcgettext (((void*)0), "The location cannot be displayed with this viewer."
, 5)
,
832 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
833 g_free (message);
834}
835
836
837const char *
838caja_window_slot_get_content_view_id (CajaWindowSlot *slot)
839{
840 if (slot->content_view == NULL((void*)0))
841 {
842 return NULL((void*)0);
843 }
844 return caja_view_get_view_id (slot->content_view);
845}
846
847gboolean
848caja_window_slot_content_view_matches_iid (CajaWindowSlot *slot,
849 const char *iid)
850{
851 if (slot->content_view == NULL((void*)0))
852 {
853 return FALSE(0);
854 }
855 return g_strcmp0 (caja_view_get_view_id (slot->content_view), iid) == 0;
856}
857
858static gboolean
859report_callback (CajaWindowSlot *slot,
860 GError *error)
861{
862 if (slot->open_callback != NULL((void*)0)) {
863 slot->open_callback (slot->pane->window, error, slot->open_callback_user_data);
864 slot->open_callback = NULL((void*)0);
865 slot->open_callback_user_data = NULL((void*)0);
866
867 return TRUE(!(0));
868 }
869
870 return FALSE(0);
871}
872
873static gpointer
874copy_object (gconstpointer obj,
875 gpointer user_data)
876{
877 (void) user_data;
878 return g_object_ref (G_OBJECT (obj))((__typeof__ (((((GObject*) (void *) ((obj))))))) (g_object_ref
) (((((GObject*) (void *) ((obj)))))))
;
879}
880
881/*
882 * begin_location_change
883 *
884 * Change a window's location.
885 * @window: The CajaWindow whose location should be changed.
886 * @location: A url specifying the location to load
887 * @previous_location: The url that was previously shown in the window that initialized the change, if any
888 * @new_selection: The initial selection to present after loading the location
889 * @type: Which type of location change is this? Standard, back, forward, or reload?
890 * @distance: If type is back or forward, the index into the back or forward chain. If
891 * type is standard or reload, this is ignored, and must be 0.
892 * @scroll_pos: The file to scroll to when the location is loaded.
893 * @callback: function to be called when the location is changed.
894 * @user_data: data for @callback.
895 *
896 * This is the core function for changing the location of a window. Every change to the
897 * location begins here.
898 */
899static void
900begin_location_change (CajaWindowSlot *slot,
901 GFile *location,
902 GFile *previous_location,
903 GList *new_selection,
904 CajaLocationChangeType type,
905 guint distance,
906 const char *scroll_pos,
907 CajaWindowGoToCallback callback,
908 gpointer user_data)
909{
910 CajaWindow *window;
911 CajaDirectory *directory;
912 gboolean force_reload;
913 GFile *parent;
914
915 g_assert (slot != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_67
; if (slot != ((void*)0)) _g_boolean_var_67 = 1; else _g_boolean_var_67
= 0; _g_boolean_var_67; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 915, ((const char
*) (__func__)), "slot != NULL"); } while (0)
;
916 g_assert (location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_68
; if (location != ((void*)0)) _g_boolean_var_68 = 1; else _g_boolean_var_68
= 0; _g_boolean_var_68; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 916, ((const char
*) (__func__)), "location != NULL"); } while (0)
;
917 g_assert (type == CAJA_LOCATION_CHANGE_BACKdo { if (__builtin_expect (__extension__ ({ int _g_boolean_var_69
; if (type == CAJA_LOCATION_CHANGE_BACK || type == CAJA_LOCATION_CHANGE_FORWARD
|| distance == 0) _g_boolean_var_69 = 1; else _g_boolean_var_69
= 0; _g_boolean_var_69; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 919, ((const char
*) (__func__)), "type == CAJA_LOCATION_CHANGE_BACK || type == CAJA_LOCATION_CHANGE_FORWARD || distance == 0"
); } while (0)
918 || type == CAJA_LOCATION_CHANGE_FORWARDdo { if (__builtin_expect (__extension__ ({ int _g_boolean_var_69
; if (type == CAJA_LOCATION_CHANGE_BACK || type == CAJA_LOCATION_CHANGE_FORWARD
|| distance == 0) _g_boolean_var_69 = 1; else _g_boolean_var_69
= 0; _g_boolean_var_69; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 919, ((const char
*) (__func__)), "type == CAJA_LOCATION_CHANGE_BACK || type == CAJA_LOCATION_CHANGE_FORWARD || distance == 0"
); } while (0)
919 || distance == 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_69
; if (type == CAJA_LOCATION_CHANGE_BACK || type == CAJA_LOCATION_CHANGE_FORWARD
|| distance == 0) _g_boolean_var_69 = 1; else _g_boolean_var_69
= 0; _g_boolean_var_69; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 919, ((const char
*) (__func__)), "type == CAJA_LOCATION_CHANGE_BACK || type == CAJA_LOCATION_CHANGE_FORWARD || distance == 0"
); } while (0)
;
920
921 /* If there is no new selection and the new location is
922 * a (grand)parent of the old location then we automatically
923 * select the folder the previous location was in */
924 if (new_selection == NULL((void*)0) && previous_location != NULL((void*)0) &&
925 g_file_has_prefix (previous_location, location)) {
926 GFile *from_folder;
927
928 from_folder = g_object_ref (previous_location)((__typeof__ (previous_location)) (g_object_ref) (previous_location
))
;
929 parent = g_file_get_parent (from_folder);
930 while (parent != NULL((void*)0) && !g_file_equal (parent, location)) {
931 g_object_unref (from_folder);
932 from_folder = parent;
933 parent = g_file_get_parent (from_folder);
934 }
935 if (parent != NULL((void*)0)) {
936 new_selection = g_list_prepend (NULL((void*)0), g_object_ref(from_folder)((__typeof__ (from_folder)) (g_object_ref) (from_folder)));
937 }
938 g_object_unref (from_folder);
939 g_object_unref (parent);
940 }
941
942 window = slot->pane->window;
943 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_70
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_70
= 1; else _g_boolean_var_70 = 0; _g_boolean_var_70; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 943, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)")
; } while (0)
;
944 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
945
946 end_location_change (slot);
947
948 caja_window_slot_set_allow_stop (slot, TRUE(!(0)));
949 caja_window_slot_set_status (slot, " ");
950
951 g_assert (slot->pending_location == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_71
; if (slot->pending_location == ((void*)0)) _g_boolean_var_71
= 1; else _g_boolean_var_71 = 0; _g_boolean_var_71; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 951, ((const char*) (__func__)), "slot->pending_location == NULL"
); } while (0)
;
952 g_assert (slot->pending_selection == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_72
; if (slot->pending_selection == ((void*)0)) _g_boolean_var_72
= 1; else _g_boolean_var_72 = 0; _g_boolean_var_72; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 952, ((const char*) (__func__)), "slot->pending_selection == NULL"
); } while (0)
;
953
954 slot->pending_location = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
955 slot->location_change_type = type;
956 slot->location_change_distance = distance;
957 slot->tried_mount = FALSE(0);
958 slot->pending_selection = g_list_copy_deep (new_selection, copy_object, NULL((void*)0));
959
960 slot->pending_scroll_to = g_strdup (scroll_pos)g_strdup_inline (scroll_pos);
961
962 slot->open_callback = callback;
963 slot->open_callback_user_data = user_data;
964
965 directory = caja_directory_get (location);
966
967 /* The code to force a reload is here because if we do it
968 * after determining an initial view (in the components), then
969 * we end up fetching things twice.
970 */
971 if (type == CAJA_LOCATION_CHANGE_RELOAD)
972 {
973 force_reload = TRUE(!(0));
974 }
975 else if (!caja_monitor_active ())
976 {
977 force_reload = TRUE(!(0));
978 }
979 else
980 {
981 force_reload = !caja_directory_is_local (directory);
982 }
983
984 if (force_reload)
985 {
986 CajaFile *file;
987
988 caja_directory_force_reload (directory);
989 file = caja_directory_get_corresponding_file (directory);
990 caja_file_invalidate_all_attributes (file);
991 caja_file_unref (file);
992 }
993
994 caja_directory_unref (directory);
995
996 /* Set current_bookmark scroll pos */
997 if (slot->current_location_bookmark != NULL((void*)0) &&
998 slot->content_view != NULL((void*)0))
999 {
1000 char *current_pos;
1001
1002 current_pos = caja_view_get_first_visible_file (slot->content_view);
1003 caja_bookmark_set_scroll_pos (slot->current_location_bookmark, current_pos);
1004 g_free (current_pos);
1005 }
1006
1007 /* Get the info needed for view selection */
1008
1009 slot->determine_view_file = caja_file_get (location);
1010 g_assert (slot->determine_view_file != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_73
; if (slot->determine_view_file != ((void*)0)) _g_boolean_var_73
= 1; else _g_boolean_var_73 = 0; _g_boolean_var_73; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1010, ((const char*) (__func__)), "slot->determine_view_file != NULL"
); } while (0)
;
1011
1012 /* if the currently viewed file is marked gone while loading the new location,
1013 * this ensures that the window isn't destroyed */
1014 cancel_viewed_file_changed_callback (slot);
1015
1016 caja_file_call_when_ready (slot->determine_view_file,
1017 CAJA_FILE_ATTRIBUTE_INFO |
1018 CAJA_FILE_ATTRIBUTE_MOUNT,
1019 got_file_info_for_view_selection_callback,
1020 slot);
1021
1022 g_object_unref (window);
1023}
1024
1025static void
1026setup_new_spatial_window (CajaWindowSlot *slot, CajaFile *file)
1027{
1028 CajaWindow *window;
1029 char *scroll_string;
1030 gboolean maximized, sticky, above;
1031
1032 window = slot->pane->window;
1033
1034 if (CAJA_IS_SPATIAL_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_spatial_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; }))))
&& !CAJA_IS_DESKTOP_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_desktop_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; }))))
)
1035 {
1036 char *show_hidden_file_setting;
1037 char *geometry_string;
1038
1039 /* load show hidden state */
1040 show_hidden_file_setting = caja_file_get_metadata
1041 (file, CAJA_METADATA_KEY_WINDOW_SHOW_HIDDEN_FILES"caja-window-show-hidden-files",
1042 NULL((void*)0));
1043 if (show_hidden_file_setting != NULL((void*)0))
1044 {
1045 GtkAction *action;
1046
1047 if (strcmp (show_hidden_file_setting, "1") == 0)
1048 {
1049 window->details->show_hidden_files_mode = CAJA_WINDOW_SHOW_HIDDEN_FILES_ENABLE;
1050 }
1051 else
1052 {
1053 window->details->show_hidden_files_mode = CAJA_WINDOW_SHOW_HIDDEN_FILES_DISABLE;
1054 }
1055
1056 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
1057 /* Update the UI, since we initialize it to the default */
1058 action = gtk_action_group_get_action (window->details->main_action_group, CAJA_ACTION_SHOW_HIDDEN_FILES"Show Hidden Files");
1059 gtk_action_block_activate (action);
1060 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))),
1061 window->details->show_hidden_files_mode == CAJA_WINDOW_SHOW_HIDDEN_FILES_ENABLE);
1062 gtk_action_unblock_activate (action);
1063 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
1064 }
1065 else
1066 {
1067 CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->show_hidden_files_mode = CAJA_WINDOW_SHOW_HIDDEN_FILES_DEFAULT;
1068 }
1069 g_free (show_hidden_file_setting);
1070
1071 /* load the saved window geometry */
1072 maximized = caja_file_get_boolean_metadata
1073 (file, CAJA_METADATA_KEY_WINDOW_MAXIMIZED"caja-window-maximized", FALSE(0));
1074 if (maximized)
1075 {
1076 gtk_window_maximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1077 }
1078 else
1079 {
1080 gtk_window_unmaximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1081 }
1082
1083 sticky = caja_file_get_boolean_metadata
1084 (file, CAJA_METADATA_KEY_WINDOW_STICKY"caja-window-sticky", FALSE(0));
1085 if (sticky)
1086 {
1087 gtk_window_stick (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1088 }
1089 else
1090 {
1091 gtk_window_unstick (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1092 }
1093
1094 above = caja_file_get_boolean_metadata
1095 (file, CAJA_METADATA_KEY_WINDOW_KEEP_ABOVE"caja-window-keep-above", FALSE(0));
1096 if (above)
1097 {
1098 gtk_window_set_keep_above (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), TRUE(!(0)));
1099 }
1100 else
1101 {
1102 gtk_window_set_keep_above (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), FALSE(0));
1103 }
1104
1105 geometry_string = caja_file_get_metadata
1106 (file, CAJA_METADATA_KEY_WINDOW_GEOMETRY"caja-window-geometry", NULL((void*)0));
1107 if (geometry_string != NULL((void*)0))
1108 {
1109 eel_gtk_window_set_initial_geometry_from_string
1110 (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
1111 geometry_string,
1112 CAJA_SPATIAL_WINDOW_MIN_WIDTH100,
1113 CAJA_SPATIAL_WINDOW_MIN_HEIGHT100,
1114 FALSE(0));
1115 }
1116 g_free (geometry_string);
1117
1118 if (slot->pending_selection == NULL((void*)0))
1119 {
1120 /* If there is no pending selection, then load the saved scroll position. */
1121 scroll_string = caja_file_get_metadata
1122 (file, CAJA_METADATA_KEY_WINDOW_SCROLL_POSITION"caja-window-scroll-position",
1123 NULL((void*)0));
1124 }
1125 else
1126 {
1127 /* If there is a pending selection, we want to scroll to an item in
1128 * the pending selection list. */
1129 scroll_string = g_file_get_uri (slot->pending_selection->data);
1130 }
1131
1132 /* scroll_string might be NULL if there was no saved scroll position. */
1133 if (scroll_string != NULL((void*)0))
1134 {
1135 slot->pending_scroll_to = scroll_string;
1136 }
1137 }
1138}
1139
1140typedef struct
1141{
1142 GCancellable *cancellable;
1143 CajaWindowSlot *slot;
1144} MountNotMountedData;
1145
1146static void
1147mount_not_mounted_callback (GObject *source_object,
1148 GAsyncResult *res,
1149 gpointer user_data)
1150{
1151 MountNotMountedData *data;
1152 CajaWindowSlot *slot;
1153 GError *error;
1154 GCancellable *cancellable;
1155
1156 data = user_data;
1157 slot = data->slot;
1158 cancellable = data->cancellable;
1159 g_free (data);
1160
1161 if (g_cancellable_is_cancelled (cancellable))
1
Assuming the condition is false
2
Taking false branch
1162 {
1163 /* Cancelled, don't call back */
1164 g_object_unref (cancellable);
1165 return;
1166 }
1167
1168 slot->mount_cancellable = NULL((void*)0);
1169
1170 slot->determine_view_file = caja_file_get (slot->pending_location);
1171
1172 error = NULL((void*)0);
1173 if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error))
3
Assuming the condition is true
4
Taking true branch
1174 {
1175 slot->mount_error = error;
1176 got_file_info_for_view_selection_callback (slot->determine_view_file, slot);
5
Calling 'got_file_info_for_view_selection_callback'
1177 slot->mount_error = NULL((void*)0);
1178 g_error_free (error);
1179 }
1180 else
1181 {
1182 caja_file_invalidate_all_attributes (slot->determine_view_file);
1183 caja_file_call_when_ready (slot->determine_view_file,
1184 CAJA_FILE_ATTRIBUTE_INFO,
1185 got_file_info_for_view_selection_callback,
1186 slot);
1187 }
1188
1189 g_object_unref (cancellable);
1190}
1191
1192static void
1193got_file_info_for_view_selection_callback (CajaFile *file,
1194 gpointer callback_data)
1195{
1196 GError *error;
1197 char *view_id;
1198 CajaWindow *window;
1199 CajaWindowSlot *slot;
1200 GFile *location;
1201 MountNotMountedData *data;
1202 slot = callback_data;
1203 g_assert (CAJA_IS_WINDOW_SLOT (slot))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_74
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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_74
= 1; else _g_boolean_var_74 = 0; _g_boolean_var_74; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1203, ((const char*) (__func__)), "CAJA_IS_WINDOW_SLOT (slot)"
); } while (0)
;
6
Taking false branch
7
Assuming field 'g_class' is null
8
Assuming the condition is true
9
Taking true branch
10
Taking true branch
11
Loop condition is false. Exiting loop
1204 g_assert (slot->determine_view_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_75
; if (slot->determine_view_file == file) _g_boolean_var_75
= 1; else _g_boolean_var_75 = 0; _g_boolean_var_75; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1204, ((const char*) (__func__)), "slot->determine_view_file == file"
); } while (0)
;
12
Taking true branch
13
Taking true branch
14
Loop condition is false. Exiting loop
1205
1206 window = slot->pane->window;
1207 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_76
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_76
= 1; else _g_boolean_var_76 = 0; _g_boolean_var_76; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1207, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
15
Assuming '__inst' is non-null
16
Taking false branch
17
Assuming field 'g_class' is null
18
Assuming the condition is true
19
Taking true branch
20
Taking true branch
21
Loop condition is false. Exiting loop
1208
1209 slot->determine_view_file = NULL((void*)0);
1210
1211 if (slot->mount_error)
22
Assuming field 'mount_error' is null
23
Taking false branch
1212 {
1213 error = slot->mount_error;
1214 }
1215 else
1216 {
1217 error = caja_file_get_file_info_error (file);
24
Value assigned to 'error'
1218 }
1219
1220 if (error && error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_NOT_MOUNTED &&
25
Assuming 'error' is null
1221 !slot->tried_mount)
1222 {
1223 GMountOperation *mount_op;
1224
1225 slot->tried_mount = TRUE(!(0));
1226
1227 mount_op = gtk_mount_operation_new (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1228 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
1229 location = caja_file_get_location (file);
1230 data = g_new0 (MountNotMountedData, 1)(MountNotMountedData *) (__extension__ ({ gsize __n = (gsize)
(1); gsize __s = sizeof (MountNotMountedData); 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; }))
;
1231 data->cancellable = g_cancellable_new ();
1232 data->slot = slot;
1233 slot->mount_cancellable = data->cancellable;
1234 g_file_mount_enclosing_volume (location, 0, mount_op, slot->mount_cancellable,
1235 mount_not_mounted_callback, data);
1236 g_object_unref (location);
1237 g_object_unref (mount_op);
1238
1239 caja_file_unref (file);
1240
1241 return;
1242 }
1243
1244 location = slot->pending_location;
1245
1246 view_id = NULL((void*)0);
1247
1248 if (error
25.1
'error' is equal to NULL
== NULL((void*)0) ||
1249 (error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_NOT_SUPPORTED))
1250 {
1251 char *mimetype;
1252
1253 /* We got the information we need, now pick what view to use: */
1254
1255 mimetype = caja_file_get_mime_type (file);
1256
1257 /* If fallback, don't use view from metadata */
1258 if (slot->location_change_type != CAJA_LOCATION_CHANGE_FALLBACK)
26
Assuming field 'location_change_type' is equal to CAJA_LOCATION_CHANGE_FALLBACK
27
Taking false branch
1259 {
1260 /* Look in metadata for view */
1261 view_id = caja_file_get_metadata
1262 (file, CAJA_METADATA_KEY_DEFAULT_VIEW"caja-default-view", NULL((void*)0));
1263 if (view_id != NULL((void*)0) &&
1264 !caja_view_factory_view_supports_uri (view_id,
1265 location,
1266 caja_file_get_file_type (file),
1267 mimetype))
1268 {
1269 g_free (view_id);
1270 view_id = NULL((void*)0);
1271 }
1272 }
1273
1274 /* Otherwise, use default */
1275 if (view_id
27.1
'view_id' is equal to NULL
== NULL((void*)0))
28
Taking true branch
1276 {
1277 char *uri;
1278 uri = caja_file_get_uri (file);
1279
1280 /* Use same view settings for search results as the current folder */
1281 if (eel_uri_is_search (uri))
29
Assuming the condition is false
30
Taking false branch
1282 {
1283 view_id = g_strdup (caja_view_get_view_id (slot->content_view))g_strdup_inline (caja_view_get_view_id (slot->content_view
))
;
1284 }
1285 else
1286 {
1287 view_id = caja_global_preferences_get_default_folder_viewer_preference_as_iid ();
1288 }
1289
1290 g_free (uri);
1291
1292 if (view_id != NULL((void*)0) &&
31
Assuming 'view_id' is equal to NULL
1293 !caja_view_factory_view_supports_uri (view_id,
1294 location,
1295 caja_file_get_file_type (file),
1296 mimetype))
1297 {
1298 g_free (view_id);
1299 view_id = NULL((void*)0);
1300 }
1301 }
1302
1303 g_free (mimetype);
1304 }
1305
1306 if (view_id
31.1
'view_id' is equal to NULL
!= NULL((void*)0))
32
Taking false branch
1307 {
1308 if (!gtk_widget_get_visible (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))) && CAJA_IS_SPATIAL_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_spatial_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; }))))
)
1309 {
1310 /* We now have the metadata to set up the window position, etc */
1311 setup_new_spatial_window (slot, file);
1312 }
1313 create_content_view (slot, view_id);
1314 g_free (view_id);
1315
1316 report_callback (slot, NULL((void*)0));
1317 }
1318 else
1319 {
1320 if (!report_callback (slot, error)) {
33
Taking true branch
1321 display_view_selection_failure (window, file,
35
Calling 'display_view_selection_failure'
1322 location, error);
34
Passing null pointer value via 4th parameter 'error'
1323 }
1324
1325 if (!gtk_widget_get_visible (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))))
1326 {
1327 CajaApplication *app;
1328
1329 /* Destroy never-had-a-chance-to-be-seen window. This case
1330 * happens when a new window cannot display its initial URI.
1331 */
1332 /* if this is the only window, we don't want to quit, so we redirect it to home */
1333 app = CAJA_APPLICATION (g_application_get_default ())((((CajaApplication*) (void *) ((g_application_get_default ()
)))))
;
1334
1335 if (g_list_length (gtk_application_get_windows (GTK_APPLICATION (app)((((GtkApplication*) (void *) ((app))))))) == 1) {
1336
1337 /* the user could have typed in a home directory that doesn't exist,
1338 in which case going home would cause an infinite loop, so we
1339 better test for that */
1340
1341 if (!caja_is_root_directory (location))
1342 {
1343 if (!caja_is_home_directory (location))
1344 {
1345 caja_window_slot_go_home (slot, FALSE(0));
1346 }
1347 else
1348 {
1349 GFile *root;
1350
1351 root = g_file_new_for_path ("/");
1352 /* the last fallback is to go to a known place that can't be deleted! */
1353 caja_window_slot_go_to (slot, location, FALSE)caja_window_slot_open_location_full(slot, location, CAJA_WINDOW_OPEN_ACCORDING_TO_MODE
, ((0) ? CAJA_WINDOW_OPEN_FLAG_NEW_TAB : 0), ((void*)0), ((void
*)0), ((void*)0))
;
1354 g_object_unref (root);
1355 }
1356 }
1357 else
1358 {
1359 gtk_widget_destroy (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
1360 }
1361 }
1362 else
1363 {
1364 /* Since this is a window, destroying it will also unref it. */
1365 gtk_widget_destroy (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
1366 }
1367 }
1368 else
1369 {
1370 /* Clean up state of already-showing window */
1371 end_location_change (slot);
1372
1373 /* TODO? shouldn't we call
1374 * cancel_viewed_file_changed_callback (slot);
1375 * at this point, or in end_location_change()
1376 */
1377 /* We're missing a previous location (if opened location
1378 * in a new tab) so close it and return */
1379 if (slot->location == NULL((void*)0))
1380 {
1381 caja_window_slot_close (slot);
1382 }
1383 else
1384 {
1385 CajaFile *viewed_file;
1386
1387 /* We disconnected this, so we need to re-connect it */
1388 viewed_file = caja_file_get (slot->location);
1389 caja_window_slot_set_viewed_file (slot, viewed_file);
1390 caja_file_monitor_add (viewed_file, &slot->viewed_file, 0);
1391 g_signal_connect_object (viewed_file, "changed",
1392 G_CALLBACK (viewed_file_changed_callback)((GCallback) (viewed_file_changed_callback)), slot, 0);
1393 caja_file_unref (viewed_file);
1394
1395 /* Leave the location bar showing the bad location that the user
1396 * typed (or maybe achieved by dragging or something). Many times
1397 * the mistake will just be an easily-correctable typo. The user
1398 * can choose "Refresh" to get the original URI back in the location bar.
1399 */
1400 }
1401 }
1402 }
1403
1404 caja_file_unref (file);
1405}
1406
1407/* Load a view into the window, either reusing the old one or creating
1408 * a new one. This happens when you want to load a new location, or just
1409 * switch to a different view.
1410 * If pending_location is set we're loading a new location and
1411 * pending_location/selection will be used. If not, we're just switching
1412 * view, and the current location will be used.
1413 */
1414static void
1415create_content_view (CajaWindowSlot *slot,
1416 const char *view_id)
1417{
1418 CajaWindow *window;
1419 CajaView *view;
1420 GList *selection;
1421
1422 window = slot->pane->window;
1423
1424 /* FIXME bugzilla.gnome.org 41243:
1425 * We should use inheritance instead of these special cases
1426 * for the desktop window.
1427 */
1428 if (CAJA_IS_DESKTOP_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_desktop_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; }))))
)
1429 {
1430 /* We force the desktop to use a desktop_icon_view. It's simpler
1431 * to fix it here than trying to make it pick the right view in
1432 * the first place.
1433 */
1434 view_id = CAJA_DESKTOP_ICON_VIEW_IID"OAFIID:Caja_File_Manager_Desktop_Icon_View";
1435 }
1436
1437 if (slot->content_view != NULL((void*)0) &&
1438 g_strcmp0 (caja_view_get_view_id (slot->content_view),
1439 view_id) == 0)
1440 {
1441 /* reuse existing content view */
1442 view = slot->content_view;
1443 slot->new_content_view = view;
1444 g_object_ref (view)((__typeof__ (view)) (g_object_ref) (view));
1445 }
1446 else
1447 {
1448 /* create a new content view */
1449 view = caja_view_factory_create (view_id,
1450 CAJA_WINDOW_SLOT_INFO (slot)((((CajaWindowSlotInfo*) (void *) ((slot))))));
1451
1452 eel_accessibility_set_name (view, _("Content View")dcgettext (((void*)0), "Content View", 5));
1453 eel_accessibility_set_description (view, _("View of the current folder")dcgettext (((void*)0), "View of the current folder", 5));
1454
1455 slot->new_content_view = view;
1456 caja_window_slot_connect_content_view (slot, slot->new_content_view);
1457 }
1458
1459 /* Actually load the pending location and selection: */
1460
1461 if (slot->pending_location != NULL((void*)0))
1462 {
1463 load_new_location (slot,
1464 slot->pending_location,
1465 slot->pending_selection,
1466 FALSE(0),
1467 TRUE(!(0)));
1468
1469 g_list_free_full (slot->pending_selection, g_object_unref);
1470 slot->pending_selection = NULL((void*)0);
1471 }
1472 else if (slot->location != NULL((void*)0))
1473 {
1474 selection = caja_view_get_selection (slot->content_view);
1475 load_new_location (slot,
1476 slot->location,
1477 selection,
1478 FALSE(0),
1479 TRUE(!(0)));
1480 g_list_free_full (selection, g_object_unref);
1481 }
1482 else
1483 {
1484 /* Something is busted, there was no location to load.
1485 Just load the homedir. */
1486 caja_window_slot_go_home (slot, FALSE(0));
1487
1488 }
1489}
1490
1491static void
1492load_new_location (CajaWindowSlot *slot,
1493 GFile *location,
1494 GList *selection,
1495 gboolean tell_current_content_view,
1496 gboolean tell_new_content_view)
1497{
1498 CajaWindow *window;
1499 GList *selection_copy;
1500 CajaView *view;
1501 char *uri;
1502
1503 g_assert (slot != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_77
; if (slot != ((void*)0)) _g_boolean_var_77 = 1; else _g_boolean_var_77
= 0; _g_boolean_var_77; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 1503, ((const char
*) (__func__)), "slot != NULL"); } while (0)
;
1504 g_assert (location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_78
; if (location != ((void*)0)) _g_boolean_var_78 = 1; else _g_boolean_var_78
= 0; _g_boolean_var_78; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 1504, ((const char
*) (__func__)), "location != NULL"); } while (0)
;
1505
1506 window = slot->pane->window;
1507 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_79
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_79
= 1; else _g_boolean_var_79 = 0; _g_boolean_var_79; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1507, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
1508
1509 selection_copy = g_list_copy_deep (selection, copy_object, NULL((void*)0));
1510
1511 view = NULL((void*)0);
1512
1513 /* Note, these may recurse into report_load_underway */
1514 if (slot->content_view != NULL((void*)0) && tell_current_content_view)
1515 {
1516 view = slot->content_view;
1517 uri = g_file_get_uri (location);
1518 caja_view_load_location (slot->content_view, uri);
1519 g_free (uri);
1520 }
1521
1522 if (slot->new_content_view != NULL((void*)0) && tell_new_content_view &&
1523 (!tell_current_content_view ||
1524 slot->new_content_view != slot->content_view) )
1525 {
1526 view = slot->new_content_view;
1527 uri = g_file_get_uri (location);
1528 caja_view_load_location (slot->new_content_view, uri);
1529 g_free (uri);
1530 }
1531 if (view != NULL((void*)0))
1532 {
1533 /* slot->new_content_view might have changed here if
1534 report_load_underway was called from load_location */
1535 caja_view_set_selection (view, selection_copy);
1536 }
1537
1538 g_list_free_full (selection_copy, g_object_unref);
1539}
1540
1541/* A view started to load the location its viewing, either due to
1542 * a load_location request, or some internal reason. Expect
1543 * a matching load_compete later
1544 */
1545void
1546caja_window_report_load_underway (CajaWindow *window,
1547 CajaView *view)
1548{
1549 CajaWindowSlot *slot;
1550
1551 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_80
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_80
= 1; else _g_boolean_var_80 = 0; _g_boolean_var_80; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1551, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
1552
1553 if (window->details->temporarily_ignore_view_signals)
1554 {
1555 return;
1556 }
1557
1558 slot = caja_window_get_slot_for_view (window, view);
1559 g_assert (slot != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (slot != ((void*)0)) _g_boolean_var_81 = 1; else _g_boolean_var_81
= 0; _g_boolean_var_81; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 1559, ((const char
*) (__func__)), "slot != NULL"); } while (0)
;
1560
1561 if (view == slot->new_content_view)
1562 {
1563 location_has_really_changed (slot);
1564 }
1565 else
1566 {
1567 caja_window_slot_set_allow_stop (slot, TRUE(!(0)));
1568 }
1569}
1570
1571static void
1572caja_window_emit_location_change (CajaWindow *window,
1573 GFile *location)
1574{
1575 char *uri;
1576
1577 uri = g_file_get_uri (location);
1578 g_signal_emit_by_name (window, "loading_uri", uri);
1579 g_free (uri);
1580}
1581
1582/* reports location change to window's "loading-uri" clients, i.e.
1583 * sidebar panels [used when switching tabs]. It will emit the pending
1584 * location, or the existing location if none is pending.
1585 */
1586void
1587caja_window_report_location_change (CajaWindow *window)
1588{
1589 CajaWindowSlot *slot;
1590 GFile *location;
1591
1592 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_82
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1592, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
1593
1594 slot = window->details->active_pane->active_slot;
1595 g_assert (CAJA_IS_WINDOW_SLOT (slot))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_83
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1595, ((const char*) (__func__)), "CAJA_IS_WINDOW_SLOT (slot)"
); } while (0)
;
1596
1597 location = NULL((void*)0);
1598
1599 if (slot->pending_location != NULL((void*)0))
1600 {
1601 location = slot->pending_location;
1602 }
1603
1604 if (location == NULL((void*)0) && slot->location != NULL((void*)0))
1605 {
1606 location = slot->location;
1607 }
1608
1609 if (location != NULL((void*)0))
1610 {
1611 caja_window_emit_location_change (window, location);
1612 }
1613}
1614
1615/* This is called when we have decided we can actually change to the new view/location situation. */
1616static void
1617location_has_really_changed (CajaWindowSlot *slot)
1618{
1619 CajaWindow *window;
1620 GFile *location_copy;
1621
1622 window = slot->pane->window;
1623
1624 if (slot->new_content_view != NULL((void*)0))
1625 {
1626 GtkWidget *widget;
1627
1628 widget = caja_view_get_widget (slot->new_content_view);
1629 /* Switch to the new content view. */
1630 if (gtk_widget_get_parent (widget) == NULL((void*)0))
1631 {
1632 if (slot->content_view != NULL((void*)0))
1633 {
1634 caja_window_slot_disconnect_content_view (slot, slot->content_view);
1635 }
1636 caja_window_slot_set_content_view_widget (slot, slot->new_content_view);
1637 }
1638 g_object_unref (slot->new_content_view);
1639 slot->new_content_view = NULL((void*)0);
1640 }
1641
1642 if (slot->pending_location != NULL((void*)0))
1643 {
1644 /* Tell the window we are finished. */
1645 update_for_new_location (slot);
1646 }
1647
1648 location_copy = NULL((void*)0);
1649 if (slot->location != NULL((void*)0))
1650 {
1651 location_copy = g_object_ref (slot->location)((__typeof__ (slot->location)) (g_object_ref) (slot->location
))
;
1652 }
1653
1654 free_location_change (slot);
1655
1656 if (location_copy != NULL((void*)0))
1657 {
1658 if (slot == caja_window_get_active_slot (window))
1659 {
1660 caja_window_emit_location_change (window, location_copy);
1661 }
1662
1663 g_object_unref (location_copy);
1664 }
1665}
1666
1667static void
1668slot_add_extension_extra_widgets (CajaWindowSlot *slot)
1669{
1670 GList *providers, *l;
1671 char *uri;
1672 GtkWidget *widget = NULL((void*)0);
1673
1674 providers = caja_extensions_get_for_type (CAJA_TYPE_LOCATION_WIDGET_PROVIDER(caja_location_widget_provider_get_type ()));
1675
1676 uri = g_file_get_uri (slot->location);
1677 for (l = providers; l != NULL((void*)0); l = l->next)
1678 {
1679 CajaLocationWidgetProvider *provider;
1680
1681 provider = CAJA_LOCATION_WIDGET_PROVIDER (l->data)((((CajaLocationWidgetProvider*) (void *) ((l->data)))));
1682 widget = caja_location_widget_provider_get_widget (provider, uri, GTK_WIDGET (slot->pane->window)((((GtkWidget*) (void *) ((slot->pane->window))))));
1683 if (widget != NULL((void*)0))
1684 {
1685 caja_window_slot_add_extra_location_widget (slot, widget);
1686 }
1687 }
1688 g_free (uri);
1689
1690 caja_module_extension_list_free (providers);
1691}
1692
1693static void
1694caja_window_slot_show_x_content_bar (CajaWindowSlot *slot, GMount *mount, const char **x_content_types)
1695{
1696 unsigned int n;
1697
1698 g_assert (CAJA_IS_WINDOW_SLOT (slot))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1698, ((const char*) (__func__)), "CAJA_IS_WINDOW_SLOT (slot)"
); } while (0)
;
1699
1700 for (n = 0; x_content_types[n] != NULL((void*)0); n++)
1701 {
1702 GAppInfo *default_app;
1703
1704 /* skip blank media; the burn:/// location will provide it's own cluebar */
1705 if (g_str_has_prefix (x_content_types[n], "x-content/blank-")(__builtin_constant_p ("x-content/blank-")? __extension__ ({ const
char * const __str = (x_content_types[n]); const char * const
__prefix = ("x-content/blank-"); gboolean __result = (0); if
(__builtin_expect (__extension__ ({ int _g_boolean_var_85; if
(__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_85
= 1; else _g_boolean_var_85 = 0; _g_boolean_var_85; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
x_content_types[n], "x-content/blank-") )
)
1706 {
1707 continue;
1708 }
1709
1710 /* don't show the cluebar for windows software */
1711 if (g_content_type_is_a (x_content_types[n], "x-content/win32-software"))
1712 {
1713 continue;
1714 }
1715
1716 /* only show the cluebar if a default app is available */
1717 default_app = g_app_info_get_default_for_type (x_content_types[n], FALSE(0));
1718 if (default_app != NULL((void*)0))
1719 {
1720 GtkWidget *bar;
1721 bar = caja_x_content_bar_new (mount, x_content_types[n]);
1722 gtk_widget_show (bar);
1723 caja_window_slot_add_extra_location_widget (slot, bar);
1724 g_object_unref (default_app);
1725 }
1726 }
1727}
1728
1729static void
1730caja_window_slot_show_trash_bar (CajaWindowSlot *slot,
1731 CajaWindow *window)
1732{
1733 GtkWidget *bar;
1734
1735 bar = caja_trash_bar_new (window);
1736 gtk_widget_show (bar);
1737
1738 caja_window_slot_add_extra_location_widget (slot, bar);
1739}
1740
1741typedef struct
1742{
1743 CajaWindowSlot *slot;
1744 GCancellable *cancellable;
1745 GMount *mount;
1746} FindMountData;
1747
1748static void
1749found_content_type_cb (const char **x_content_types, FindMountData *data)
1750{
1751 CajaWindowSlot *slot;
1752
1753 if (g_cancellable_is_cancelled (data->cancellable))
1754 {
1755 goto out;
1756 }
1757
1758 slot = data->slot;
1759
1760 if (x_content_types != NULL((void*)0) && x_content_types[0] != NULL((void*)0))
1761 {
1762 caja_window_slot_show_x_content_bar (slot, data->mount, x_content_types);
1763 }
1764
1765 slot->find_mount_cancellable = NULL((void*)0);
1766
1767out:
1768 g_object_unref (data->mount);
1769 g_object_unref (data->cancellable);
1770 g_free (data);
1771}
1772
1773static void
1774found_mount_cb (GObject *source_object,
1775 GAsyncResult *res,
1776 gpointer user_data)
1777{
1778 FindMountData *data = user_data;
1779 GMount *mount;
1780
1781 if (g_cancellable_is_cancelled (data->cancellable))
1782 {
1783 goto out;
1784 }
1785
1786 mount = g_file_find_enclosing_mount_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
1787 res,
1788 NULL((void*)0));
1789 if (mount != NULL((void*)0))
1790 {
1791 data->mount = mount;
1792 caja_autorun_get_x_content_types_for_mount_async (mount,
1793 (CajaAutorunGetContent)found_content_type_cb,
1794 data->cancellable,
1795 data);
1796 return;
1797 }
1798
1799 data->slot->find_mount_cancellable = NULL((void*)0);
1800
1801out:
1802 g_object_unref (data->cancellable);
1803 g_free (data);
1804}
1805
1806/* Handle the changes for the CajaWindow itself. */
1807static void
1808update_for_new_location (CajaWindowSlot *slot)
1809{
1810 CajaWindow *window;
1811 GFile *new_location;
1812 CajaFile *file;
1813 gboolean location_really_changed;
1814 FindMountData *data;
1815
1816 window = slot->pane->window;
1817
1818 new_location = slot->pending_location;
1819 slot->pending_location = NULL((void*)0);
1820
1821 set_displayed_location (slot, new_location);
1822
1823 update_history (slot, slot->location_change_type, new_location);
1824
1825 location_really_changed =
1826 slot->location == NULL((void*)0) ||
1827 !g_file_equal (slot->location, new_location);
1828
1829 /* Set the new location. */
1830 if (slot->location)
1831 {
1832 g_object_unref (slot->location);
1833 }
1834 slot->location = new_location;
1835
1836 /* Create a CajaFile for this location, so we can catch it
1837 * if it goes away.
1838 */
1839 cancel_viewed_file_changed_callback (slot);
1840 file = caja_file_get (slot->location);
1841 caja_window_slot_set_viewed_file (slot, file);
1842 slot->viewed_file_seen = !caja_file_is_not_yet_confirmed (file);
1843 slot->viewed_file_in_trash = caja_file_is_in_trash (file);
1844 caja_file_monitor_add (file, &slot->viewed_file, 0);
1845 g_signal_connect_object (file, "changed",
1846 G_CALLBACK (viewed_file_changed_callback)((GCallback) (viewed_file_changed_callback)), slot, 0);
1847 caja_file_unref (file);
1848
1849 if (slot == window->details->active_pane->active_slot)
1850 {
1851 /* Check if we can go up. */
1852 caja_window_update_up_button (window);
1853
1854 caja_window_sync_zoom_widgets (window);
1855
1856 /* Set up the content view menu for this new location. */
1857 caja_window_load_view_as_menus (window);
1858
1859 /* Load menus from caja extensions for this location */
1860 caja_window_load_extension_menus (window);
1861 }
1862
1863 if (location_really_changed)
1864 {
1865 CajaDirectory *directory;
1866
1867 caja_window_slot_remove_extra_location_widgets (slot);
1868
1869 directory = caja_directory_get (slot->location);
1870
1871 caja_window_slot_update_query_editor (slot);
1872
1873 if (caja_directory_is_in_trash (directory))
1874 {
1875 caja_window_slot_show_trash_bar (slot, window);
1876 }
1877
1878 /* need the mount to determine if we should put up the x-content cluebar */
1879 if (slot->find_mount_cancellable != NULL((void*)0))
1880 {
1881 g_cancellable_cancel (slot->find_mount_cancellable);
1882 slot->find_mount_cancellable = NULL((void*)0);
1883 }
1884
1885 data = g_new (FindMountData, 1)(FindMountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (FindMountData); 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; }))
;
1886 data->slot = slot;
1887 data->cancellable = g_cancellable_new ();
1888 data->mount = NULL((void*)0);
1889
1890 slot->find_mount_cancellable = data->cancellable;
1891 g_file_find_enclosing_mount_async (slot->location,
1892 G_PRIORITY_DEFAULT0,
1893 data->cancellable,
1894 found_mount_cb,
1895 data);
1896
1897 caja_directory_unref (directory);
1898
1899 slot_add_extension_extra_widgets (slot);
1900 }
1901
1902 caja_window_slot_update_title (slot);
1903 caja_window_slot_update_icon (slot);
1904
1905 if (slot == slot->pane->active_slot)
1906 {
1907 caja_window_pane_sync_location_widgets (slot->pane);
1908
1909 if (location_really_changed)
1910 {
1911 caja_window_pane_sync_search_widgets (slot->pane);
1912 }
1913
1914 if (CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
&&
1915 slot->pane == window->details->active_pane)
1916 {
1917 caja_navigation_window_load_extension_toolbar_items (CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window))))));
1918 }
1919 }
1920}
1921
1922/* A location load previously announced by load_underway
1923 * has been finished */
1924void
1925caja_window_report_load_complete (CajaWindow *window,
1926 CajaView *view)
1927{
1928 CajaWindowSlot *slot;
1929
1930 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1930, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
1931
1932 if (window->details->temporarily_ignore_view_signals)
1933 {
1934 return;
1935 }
1936
1937 slot = caja_window_get_slot_for_view (window, view);
1938 g_assert (slot != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (slot != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 1938, ((const char
*) (__func__)), "slot != NULL"); } while (0)
;
1939
1940 /* Only handle this if we're expecting it.
1941 * Don't handle it if its from an old view we've switched from */
1942 if (view == slot->content_view)
1943 {
1944 if (slot->pending_scroll_to != NULL((void*)0))
1945 {
1946 caja_view_scroll_to_file (slot->content_view,
1947 slot->pending_scroll_to);
1948 }
1949 end_location_change (slot);
1950 }
1951}
1952
1953static void
1954end_location_change (CajaWindowSlot *slot)
1955{
1956 CajaWindow *window;
1957 char *uri;
1958
1959 window = slot->pane->window;
1960
1961 uri = caja_window_slot_get_location_uri (slot);
1962 if (uri)
1963 {
1964 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1965 "finished loading window %p: %s", window, uri);
1966 g_free (uri);
1967 }
1968
1969 caja_window_slot_set_allow_stop (slot, FALSE(0));
1970
1971 /* Now we can free pending_scroll_to, since the load_complete
1972 * callback already has been emitted.
1973 */
1974 g_free (slot->pending_scroll_to);
1975 slot->pending_scroll_to = NULL((void*)0);
1976
1977 free_location_change (slot);
1978}
1979
1980static void
1981free_location_change (CajaWindowSlot *slot)
1982{
1983 CajaWindow *window;
1984
1985 window = slot->pane->window;
1986 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 1986, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
1987
1988 if (slot->pending_location)
1989 {
1990 g_object_unref (slot->pending_location);
1991 }
1992 slot->pending_location = NULL((void*)0);
1993
1994 g_list_free_full (slot->pending_selection, g_object_unref);
1995 slot->pending_selection = NULL((void*)0);
1996
1997 /* Don't free pending_scroll_to, since thats needed until
1998 * the load_complete callback.
1999 */
2000
2001 if (slot->mount_cancellable != NULL((void*)0))
2002 {
2003 g_cancellable_cancel (slot->mount_cancellable);
2004 slot->mount_cancellable = NULL((void*)0);
2005 }
2006
2007 if (slot->determine_view_file != NULL((void*)0))
2008 {
2009 caja_file_cancel_call_when_ready
2010 (slot->determine_view_file,
2011 got_file_info_for_view_selection_callback, slot);
2012 slot->determine_view_file = NULL((void*)0);
2013 }
2014
2015 if (slot->new_content_view != NULL((void*)0))
2016 {
2017 window->details->temporarily_ignore_view_signals = TRUE(!(0));
2018 caja_view_stop_loading (slot->new_content_view);
2019 window->details->temporarily_ignore_view_signals = FALSE(0);
2020
2021 caja_window_slot_disconnect_content_view (slot, slot->new_content_view);
2022 g_object_unref (slot->new_content_view);
2023 slot->new_content_view = NULL((void*)0);
2024 }
2025}
2026
2027static void
2028cancel_location_change (CajaWindowSlot *slot)
2029{
2030 if (slot->pending_location != NULL((void*)0)
2031 && slot->location != NULL((void*)0)
2032 && slot->content_view != NULL((void*)0))
2033 {
2034 GList *selection;
2035
2036 /* No need to tell the new view - either it is the
2037 * same as the old view, in which case it will already
2038 * be told, or it is the very pending change we wish
2039 * to cancel.
2040 */
2041 selection = caja_view_get_selection (slot->content_view);
2042 load_new_location (slot,
2043 slot->location,
2044 selection,
2045 TRUE(!(0)),
2046 FALSE(0));
2047 g_list_free_full (selection, g_object_unref);
2048 }
2049
2050 end_location_change (slot);
2051}
2052
2053void
2054caja_window_report_view_failed (CajaWindow *window,
2055 CajaView *view)
2056{
2057 CajaWindowSlot *slot;
2058 gboolean do_close_window;
2059 GFile *fallback_load_location;
2060
2061 if (window->details->temporarily_ignore_view_signals)
2062 {
2063 return;
2064 }
2065
2066 slot = caja_window_get_slot_for_view (window, view);
2067 g_assert (slot != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if (slot != ((void*)0)) _g_boolean_var_89 = 1; else _g_boolean_var_89
= 0; _g_boolean_var_89; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 2067, ((const char
*) (__func__)), "slot != NULL"); } while (0)
;
2068
2069 g_warning ("A view failed. The UI will handle this with a dialog but this should be debugged.");
2070
2071 do_close_window = FALSE(0);
2072 fallback_load_location = NULL((void*)0);
2073
2074 if (view == slot->content_view)
2075 {
2076 caja_window_slot_disconnect_content_view (slot, view);
2077 caja_window_slot_set_content_view_widget (slot, NULL((void*)0));
2078
2079 report_current_content_view_failure_to_user (slot);
2080 }
2081 else
2082 {
2083 /* Only report error on first try */
2084 if (slot->location_change_type != CAJA_LOCATION_CHANGE_FALLBACK)
2085 {
2086 report_nascent_content_view_failure_to_user (slot, view);
2087
2088 fallback_load_location = g_object_ref (slot->pending_location)((__typeof__ (slot->pending_location)) (g_object_ref) (slot
->pending_location))
;
2089 }
2090 else
2091 {
2092 if (!gtk_widget_get_visible (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))))
2093 {
2094 do_close_window = TRUE(!(0));
2095 }
2096 }
2097 }
2098
2099 cancel_location_change (slot);
2100
2101 if (fallback_load_location != NULL((void*)0))
2102 {
2103 /* We loose the pending selection change here, but who cares... */
2104 begin_location_change (slot, fallback_load_location, NULL((void*)0), NULL((void*)0),
2105 CAJA_LOCATION_CHANGE_FALLBACK, 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
2106 g_object_unref (fallback_load_location);
2107 }
2108
2109 if (do_close_window)
2110 {
2111 gtk_widget_destroy (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
2112 }
2113}
2114
2115static void
2116display_view_selection_failure (CajaWindow *window, CajaFile *file,
2117 GFile *location, GError *error)
2118{
2119 char *full_uri_for_display;
2120 char *uri_for_display;
2121 char *error_message;
2122 char *detail_message;
2123 char *scheme_string;
2124
2125 /* Some sort of failure occurred. How 'bout we tell the user? */
2126 full_uri_for_display = g_file_get_parse_name (location);
2127 /* Truncate the URI so it doesn't get insanely wide. Note that even
2128 * though the dialog uses wrapped text, if the URI doesn't contain
2129 * white space then the text-wrapping code is too stupid to wrap it.
2130 */
2131 uri_for_display = eel_str_middle_truncate
2132 (full_uri_for_display, MAX_URI_IN_DIALOG_LENGTH60);
2133 g_free (full_uri_for_display);
2134
2135 error_message = NULL((void*)0);
2136 detail_message = NULL((void*)0);
2137 if (error
35.1
'error' is equal to NULL
== NULL((void*)0))
36
Taking true branch
2138 {
2139 if (caja_file_is_directory (file))
37
Assuming the condition is false
38
Taking false branch
2140 {
2141 error_message = g_strdup_printf
2142 (_("Could not display \"%s\".")dcgettext (((void*)0), "Could not display \"%s\".", 5),
2143 uri_for_display);
2144 detail_message = g_strdupg_strdup_inline (dcgettext (((void*)0), "Caja has no installed viewer capable of displaying the folder."
, 5))
2145 (_("Caja has no installed viewer capable of displaying the folder."))g_strdup_inline (dcgettext (((void*)0), "Caja has no installed viewer capable of displaying the folder."
, 5))
;
2146 }
2147 else
2148 {
2149 error_message = g_strdup_printf
2150 (_("Could not display \"%s\".")dcgettext (((void*)0), "Could not display \"%s\".", 5),
2151 uri_for_display);
2152 detail_message = g_strdupg_strdup_inline (dcgettext (((void*)0), "The location is not a folder."
, 5))
2153 (_("The location is not a folder."))g_strdup_inline (dcgettext (((void*)0), "The location is not a folder."
, 5))
;
2154 }
2155 }
2156 else if (error->domain == G_IO_ERRORg_io_error_quark())
2157 {
2158 switch (error->code)
2159 {
2160 case G_IO_ERROR_NOT_FOUND:
2161 error_message = g_strdup_printf
2162 (_("Could not find \"%s\".")dcgettext (((void*)0), "Could not find \"%s\".", 5),
2163 uri_for_display);
2164 detail_message = g_strdupg_strdup_inline (dcgettext (((void*)0), "Please check the spelling and try again."
, 5))
2165 (_("Please check the spelling and try again."))g_strdup_inline (dcgettext (((void*)0), "Please check the spelling and try again."
, 5))
;
2166 break;
2167 case G_IO_ERROR_NOT_SUPPORTED:
2168 scheme_string = g_file_get_uri_scheme (location);
2169
2170 error_message = g_strdup_printf (_("Could not display \"%s\".")dcgettext (((void*)0), "Could not display \"%s\".", 5),
2171 uri_for_display);
2172 if (scheme_string != NULL((void*)0))
2173 {
2174 detail_message = g_strdup_printf (_("Caja cannot handle \"%s\" locations.")dcgettext (((void*)0), "Caja cannot handle \"%s\" locations."
, 5)
,
2175 scheme_string);
2176 }
2177 else
2178 {
2179 detail_message = g_strdup (_("Caja cannot handle this kind of location."))g_strdup_inline (dcgettext (((void*)0), "Caja cannot handle this kind of location."
, 5))
;
2180 }
2181 g_free (scheme_string);
2182 break;
2183 case G_IO_ERROR_NOT_MOUNTED:
2184 error_message = g_strdup_printf (_("Could not display \"%s\".")dcgettext (((void*)0), "Could not display \"%s\".", 5),
2185 uri_for_display);
2186 detail_message = g_strdup (_("Unable to mount the location."))g_strdup_inline (dcgettext (((void*)0), "Unable to mount the location."
, 5))
;
2187 break;
2188
2189 case G_IO_ERROR_PERMISSION_DENIED:
2190 error_message = g_strdup_printf (_("Could not display \"%s\".")dcgettext (((void*)0), "Could not display \"%s\".", 5),
2191 uri_for_display);
2192 detail_message = g_strdup (_("Access was denied."))g_strdup_inline (dcgettext (((void*)0), "Access was denied.",
5))
;
2193 break;
2194
2195 case G_IO_ERROR_HOST_NOT_FOUND:
2196 /* This case can be hit for user-typed strings like "foo" due to
2197 * the code that guesses web addresses when there's no initial "/".
2198 * But this case is also hit for legitimate web addresses when
2199 * the proxy is set up wrong.
2200 */
2201 error_message = g_strdup_printf (_("Could not display \"%s\", because the host could not be found.")dcgettext (((void*)0), "Could not display \"%s\", because the host could not be found."
, 5)
,
2202 uri_for_display);
2203 detail_message = g_strdup (_("Check that the spelling is correct and that your proxy settings are correct."))g_strdup_inline (dcgettext (((void*)0), "Check that the spelling is correct and that your proxy settings are correct."
, 5))
;
2204 break;
2205 case G_IO_ERROR_CANCELLED:
2206 case G_IO_ERROR_FAILED_HANDLED:
2207 g_free (uri_for_display);
2208 return;
2209
2210 default:
2211 break;
2212 }
2213 }
2214
2215 if (error_message == NULL((void*)0))
39
Assuming 'error_message' is equal to NULL
40
Taking true branch
2216 {
2217 error_message = g_strdup_printf (_("Could not display \"%s\".")dcgettext (((void*)0), "Could not display \"%s\".", 5),
2218 uri_for_display);
2219 detail_message = g_strdup_printf (_("Error: %s\nPlease select another viewer and try again.")dcgettext (((void*)0), "Error: %s\nPlease select another viewer and try again."
, 5)
, error->message);
41
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'error')
2220 }
2221
2222 eel_show_error_dialog (error_message, detail_message, NULL((void*)0));
2223
2224 g_free (uri_for_display);
2225 g_free (error_message);
2226 g_free (detail_message);
2227}
2228
2229
2230void
2231caja_window_slot_stop_loading (CajaWindowSlot *slot)
2232{
2233 CajaWindow *window;
2234
2235 window = CAJA_WINDOW (slot->pane->window)((((CajaWindow*) (void *) ((slot->pane->window)))));
2236 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_90
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 2236, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
2237
2238 caja_view_stop_loading (slot->content_view);
2239
2240 if (slot->new_content_view != NULL((void*)0))
2241 {
2242 window->details->temporarily_ignore_view_signals = TRUE(!(0));
2243 caja_view_stop_loading (slot->new_content_view);
2244 window->details->temporarily_ignore_view_signals = FALSE(0);
2245 }
2246
2247 cancel_location_change (slot);
2248}
2249
2250void
2251caja_window_slot_set_content_view (CajaWindowSlot *slot,
2252 const char *id)
2253{
2254 CajaWindow *window;
2255 CajaFile *file;
2256 char *uri;
2257
2258 g_assert (slot != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_91
; if (slot != ((void*)0)) _g_boolean_var_91 = 1; else _g_boolean_var_91
= 0; _g_boolean_var_91; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 2258, ((const char
*) (__func__)), "slot != NULL"); } while (0)
;
2259 g_assert (slot->location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_92
; if (slot->location != ((void*)0)) _g_boolean_var_92 = 1;
else _g_boolean_var_92 = 0; _g_boolean_var_92; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 2259, ((const char*) (__func__)), "slot->location != NULL"
); } while (0)
;
2260 g_assert (id != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if (id != ((void*)0)) _g_boolean_var_93 = 1; else _g_boolean_var_93
= 0; _g_boolean_var_93; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-window-manage-views.c", 2260, ((const char
*) (__func__)), "id != NULL"); } while (0)
;
2261
2262 window = slot->pane->window;
2263 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_94
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 2263, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
2264
2265 uri = caja_window_slot_get_location_uri (slot);
2266 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
2267 "change view of window %p: \"%s\" to \"%s\"",
2268 window, uri, id);
2269 g_free (uri);
2270
2271 if (caja_window_slot_content_view_matches_iid (slot, id))
2272 {
2273 return;
2274 }
2275
2276 end_location_change (slot);
2277
2278 file = caja_file_get (slot->location);
2279 caja_file_set_metadata
2280 (file, CAJA_METADATA_KEY_DEFAULT_VIEW"caja-default-view", NULL((void*)0), id);
2281 caja_file_unref (file);
2282
2283 caja_window_slot_set_allow_stop (slot, TRUE(!(0)));
2284
2285 if (caja_view_get_selection_count (slot->content_view) == 0)
2286 {
2287 /* If there is no selection, queue a scroll to the same icon that
2288 * is currently visible */
2289 slot->pending_scroll_to = caja_view_get_first_visible_file (slot->content_view);
2290 }
2291 slot->location_change_type = CAJA_LOCATION_CHANGE_RELOAD;
2292
2293 create_content_view (slot, id);
2294}
2295
2296void
2297caja_window_manage_views_close_slot (CajaWindowPane *pane,
2298 CajaWindowSlot *slot)
2299{
2300 if (slot->content_view != NULL((void*)0))
2301 {
2302 caja_window_slot_disconnect_content_view (slot, slot->content_view);
2303 }
2304
2305 free_location_change (slot);
2306 cancel_viewed_file_changed_callback (slot);
2307}
2308
2309void
2310caja_navigation_window_back_or_forward (CajaNavigationWindow *window,
2311 gboolean back, guint distance, gboolean new_tab)
2312{
2313 CajaWindowSlot *slot;
2314 CajaNavigationWindowSlot *navigation_slot;
2315 GList *list;
2316 GFile *location;
2317 guint len;
2318 CajaBookmark *bookmark;
2319
2320 slot = CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->active_pane->active_slot;
2321 navigation_slot = (CajaNavigationWindowSlot *) slot;
2322 list = back ? navigation_slot->back_list : navigation_slot->forward_list;
2323
2324 len = (guint) g_list_length (list);
2325
2326 /* If we can't move in the direction at all, just return. */
2327 if (len == 0)
2328 return;
2329
2330 /* If the distance to move is off the end of the list, go to the end
2331 of the list. */
2332 if (distance >= len)
2333 distance = len - 1;
2334
2335 bookmark = g_list_nth_data (list, distance);
2336 location = caja_bookmark_get_location (bookmark);
2337
2338 if (new_tab)
2339 {
2340 caja_window_slot_open_location_full (slot, location,
2341 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
2342 CAJA_WINDOW_OPEN_FLAG_NEW_TAB,
2343 NULL((void*)0), NULL((void*)0), NULL((void*)0));
2344 }
2345 else
2346 {
2347 GFile *old_location;
2348 char *scroll_pos;
2349
2350 old_location = caja_window_slot_get_location (slot);
2351 scroll_pos = caja_bookmark_get_scroll_pos (bookmark);
2352 begin_location_change
2353 (slot,
2354 location, old_location, NULL((void*)0),
2355 back ? CAJA_LOCATION_CHANGE_BACK : CAJA_LOCATION_CHANGE_FORWARD,
2356 distance,
2357 scroll_pos,
2358 NULL((void*)0), NULL((void*)0));
2359
2360 if (old_location) {
2361 g_object_unref (old_location);
2362 }
2363
2364 g_free (scroll_pos);
2365 }
2366
2367 g_object_unref (location);
2368}
2369
2370/* reload the contents of the window */
2371void
2372caja_window_slot_reload (CajaWindowSlot *slot)
2373{
2374 GFile *location;
2375 char *current_pos;
2376 GList *selection;
2377
2378 g_assert (CAJA_IS_WINDOW_SLOT (slot))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((slot)); GType __t = ((caja_window_slot_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_95
= 1; else _g_boolean_var_95 = 0; _g_boolean_var_95; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-window-manage-views.c"
, 2378, ((const char*) (__func__)), "CAJA_IS_WINDOW_SLOT (slot)"
); } while (0)
;
2379
2380 if (slot->location == NULL((void*)0))
2381 {
2382 return;
2383 }
2384
2385 /* peek_slot_field (window, location) can be free'd during the processing
2386 * of begin_location_change, so make a copy
2387 */
2388 location = g_object_ref (slot->location)((__typeof__ (slot->location)) (g_object_ref) (slot->location
))
;
2389 current_pos = NULL((void*)0);
2390 selection = NULL((void*)0);
2391 if (slot->content_view != NULL((void*)0))
2392 {
2393 current_pos = caja_view_get_first_visible_file (slot->content_view);
2394 selection = caja_view_get_selection (slot->content_view);
2395 }
2396 begin_location_change
2397 (slot, location, location, selection,
2398 CAJA_LOCATION_CHANGE_RELOAD, 0, current_pos,
2399 NULL((void*)0), NULL((void*)0));
2400 g_free (current_pos);
2401 g_object_unref (location);
2402 g_list_free_full (selection, g_object_unref);
2403}
2404
diff --git a/2024-07-29-023715-6438-1/report-7e131c.html b/2024-07-29-023715-6438-1/report-7e131c.html new file mode 100644 index 000000000..4d5e20e6e --- /dev/null +++ b/2024-07-29-023715-6438-1/report-7e131c.html @@ -0,0 +1,6536 @@ + + + +fm-properties-window.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/file-manager/fm-properties-window.c
Warning:line 4551, column 2
Value stored to 'w' 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 fm-properties-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 -fdebug-compilation-dir=/rootdir/src/file-manager -fcoverage-compilation-dir=/rootdir/src/file-manager -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I ../../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D CAJA_DATADIR="/usr/local/share/caja" -D DATADIR="/usr/local/share" -D ICONDIR="/usr/local/share/icons" -D PIXMAPDIR="/usr/local/share/pixmaps" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c fm-properties-window.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* fm-properties-window.c - window that lets user modify file properties
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <string.h>
27#include <cairo.h>
28
29#include <gtk/gtk.h>
30#include <gdk/gdkkeysyms.h>
31#include <glib/gi18n.h>
32#include <sys/stat.h>
33
34#include <eel/eel-accessibility.h>
35#include <eel/eel-gdk-pixbuf-extensions.h>
36#include <eel/eel-glib-extensions.h>
37#include <eel/eel-mate-extensions.h>
38#include <eel/eel-gtk-extensions.h>
39#include <eel/eel-labeled-image.h>
40#include <eel/eel-stock-dialogs.h>
41#include <eel/eel-vfs-extensions.h>
42#include <eel/eel-wrap-table.h>
43
44#include <libcaja-extension/caja-property-page-provider.h>
45
46#include <libcaja-private/caja-mime-application-chooser.h>
47#include <libcaja-private/caja-entry.h>
48#include <libcaja-private/caja-extensions.h>
49#include <libcaja-private/caja-file-attributes.h>
50#include <libcaja-private/caja-file-operations.h>
51#include <libcaja-private/caja-desktop-icon-file.h>
52#include <libcaja-private/caja-global-preferences.h>
53#include <libcaja-private/caja-emblem-utils.h>
54#include <libcaja-private/caja-link.h>
55#include <libcaja-private/caja-metadata.h>
56#include <libcaja-private/caja-module.h>
57#include <libcaja-private/caja-mime-actions.h>
58
59#include "fm-properties-window.h"
60#include "fm-ditem-page.h"
61#include "fm-error-reporting.h"
62
63#if HAVE_SYS_VFS_H1
64#include <sys/vfs.h>
65#elif HAVE_SYS_MOUNT_H1
66#if HAVE_SYS_PARAM_H1
67#include <sys/param.h>
68#endif
69#include <sys/mount.h>
70#endif
71
72#define USED_FILL_R0.988235294 0.988235294
73#define USED_FILL_G0.91372549 0.91372549
74#define USED_FILL_B0.309803922 0.309803922
75
76#define FREE_FILL_R0.447058824 0.447058824
77#define FREE_FILL_G0.623529412 0.623529412
78#define FREE_FILL_B0.811764706 0.811764706
79
80#define PREVIEW_IMAGE_WIDTH96 96
81
82#define ROW_PAD6 6
83
84static GHashTable *windows;
85static GHashTable *pending_lists;
86
87struct _FMPropertiesWindowPrivate {
88 GList *original_files;
89 GList *target_files;
90
91 GtkNotebook *notebook;
92
93 GtkGrid *basic_grid;
94
95 GtkWidget *icon_button;
96 GtkWidget *icon_image;
97 GtkWidget *icon_chooser;
98
99 GtkLabel *name_label;
100 GtkWidget *name_field;
101 unsigned int name_row;
102 char *pending_name;
103
104 GtkLabel *directory_contents_title_field;
105 GtkLabel *directory_contents_value_field;
106 guint update_directory_contents_timeout_id;
107 guint update_files_timeout_id;
108
109 GList *emblem_buttons;
110 GHashTable *initial_emblems;
111
112 CajaFile *group_change_file;
113 char *group_change_group;
114 unsigned int group_change_timeout;
115 CajaFile *owner_change_file;
116 char *owner_change_owner;
117 unsigned int owner_change_timeout;
118
119 GList *permission_buttons;
120 GList *permission_combos;
121 GHashTable *initial_permissions;
122 gboolean has_recursive_apply;
123
124 GList *value_fields;
125
126 GList *mime_list;
127
128 gboolean deep_count_finished;
129
130 guint total_count;
131 goffset total_size;
132 goffset total_size_on_disk;
133
134 guint long_operation_underway;
135
136 GList *changed_files;
137
138 guint64 volume_capacity;
139 guint64 volume_free;
140
141 GdkRGBA used_color;
142 GdkRGBA free_color;
143 GdkRGBA used_stroke_color;
144 GdkRGBA free_stroke_color;
145};
146
147typedef enum {
148 PERMISSIONS_CHECKBOXES_READ,
149 PERMISSIONS_CHECKBOXES_WRITE,
150 PERMISSIONS_CHECKBOXES_EXECUTE
151} CheckboxType;
152
153enum {
154 TITLE_COLUMN,
155 VALUE_COLUMN,
156 COLUMN_COUNT
157};
158
159typedef struct {
160 GList *original_files;
161 GList *target_files;
162 GtkWidget *parent_widget;
163 char *pending_key;
164 GHashTable *pending_files;
165} StartupData;
166
167/* drag and drop definitions */
168
169enum {
170 TARGET_URI_LIST,
171 TARGET_MATE_URI_LIST,
172 TARGET_RESET_BACKGROUND
173};
174
175static const GtkTargetEntry target_table[] = {
176 { "text/uri-list", 0, TARGET_URI_LIST },
177 { "x-special/mate-icon-list", 0, TARGET_MATE_URI_LIST },
178 { "x-special/mate-reset-background", 0, TARGET_RESET_BACKGROUND }
179};
180
181#define DIRECTORY_CONTENTS_UPDATE_INTERVAL200 200 /* milliseconds */
182#define FILES_UPDATE_INTERVAL200 200 /* milliseconds */
183#define STANDARD_EMBLEM_HEIGHT52 52
184#define EMBLEM_LABEL_SPACING2 2
185
186/*
187 * A timeout before changes through the user/group combo box will be applied.
188 * When quickly changing owner/groups (i.e. by keyboard or scroll wheel),
189 * this ensures that the GUI doesn't end up unresponsive.
190 *
191 * Both combos react on changes by scheduling a new change and unscheduling
192 * or cancelling old pending changes.
193 */
194#define CHOWN_CHGRP_TIMEOUT300 300 /* milliseconds */
195
196static void directory_contents_value_field_update (FMPropertiesWindow *window);
197static void file_changed_callback (CajaFile *file,
198 gpointer user_data);
199static void permission_button_update (FMPropertiesWindow *window,
200 GtkToggleButton *button);
201static void permission_combo_update (FMPropertiesWindow *window,
202 GtkComboBox *combo);
203static void value_field_update (FMPropertiesWindow *window,
204 GtkLabel *field);
205static void properties_window_update (FMPropertiesWindow *window,
206 GList *files);
207static void is_directory_ready_callback (CajaFile *file,
208 gpointer data);
209static void cancel_group_change_callback (FMPropertiesWindow *window);
210static void cancel_owner_change_callback (FMPropertiesWindow *window);
211static void parent_widget_destroyed_callback (GtkWidget *widget,
212 gpointer callback_data);
213static void select_image_button_callback (GtkWidget *widget,
214 FMPropertiesWindow *properties_window);
215static void set_icon (const char *icon_path,
216 FMPropertiesWindow *properties_window);
217static void remove_pending (StartupData *data,
218 gboolean cancel_call_when_ready,
219 gboolean cancel_timed_wait,
220 gboolean cancel_destroy_handler);
221static void append_extension_pages (FMPropertiesWindow *window);
222
223static gboolean name_field_focus_out (CajaEntry *name_field,
224 GdkEventFocus *event,
225 gpointer callback_data);
226static void name_field_activate (CajaEntry *name_field,
227 gpointer callback_data);
228static GtkLabel *attach_ellipsizing_value_label (GtkGrid *grid,
229 GtkWidget *sibling,
230
231 const char *initial_text);
232
233static GtkWidget* create_pie_widget (FMPropertiesWindow *window);
234
235G_DEFINE_TYPE_WITH_PRIVATE (FMPropertiesWindow, fm_properties_window, GTK_TYPE_DIALOG)static void fm_properties_window_init (FMPropertiesWindow *self
); static void fm_properties_window_class_init (FMPropertiesWindowClass
*klass); static GType fm_properties_window_get_type_once (void
); static gpointer fm_properties_window_parent_class = ((void
*)0); static gint FMPropertiesWindow_private_offset; static void
fm_properties_window_class_intern_init (gpointer klass) { fm_properties_window_parent_class
= g_type_class_peek_parent (klass); if (FMPropertiesWindow_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &FMPropertiesWindow_private_offset
); fm_properties_window_class_init ((FMPropertiesWindowClass*
) klass); } __attribute__ ((__unused__)) static inline gpointer
fm_properties_window_get_instance_private (FMPropertiesWindow
*self) { return (((gpointer) ((guint8*) (self) + (glong) (FMPropertiesWindow_private_offset
)))); } GType fm_properties_window_get_type (void) { static GType
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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= fm_properties_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType fm_properties_window_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_dialog_get_type ()), g_intern_static_string ("FMPropertiesWindow"
), sizeof (FMPropertiesWindowClass), (GClassInitFunc)(void (*
)(void)) fm_properties_window_class_intern_init, sizeof (FMPropertiesWindow
), (GInstanceInitFunc)(void (*)(void)) fm_properties_window_init
, (GTypeFlags) 0); { {{ FMPropertiesWindow_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (FMPropertiesWindowPrivate)); };} }
return g_define_type_id; }
;
236
237static gboolean
238is_multi_file_window (FMPropertiesWindow *window)
239{
240 GList *l;
241 int count;
242
243 count = 0;
244
245 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
246 if (!caja_file_is_gone (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
247 count++;
248 if (count > 1) {
249 return TRUE(!(0));
250 }
251 }
252 }
253
254 return FALSE(0);
255}
256
257static int
258get_not_gone_original_file_count (FMPropertiesWindow *window)
259{
260 GList *l;
261 int count;
262
263 count = 0;
264
265 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
266 if (!caja_file_is_gone (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
267 count++;
268 }
269 }
270
271 return count;
272}
273
274static CajaFile *
275get_original_file (FMPropertiesWindow *window)
276{
277 g_return_val_if_fail (!is_multi_file_window (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_283
; if (!is_multi_file_window (window)) _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__)), "!is_multi_file_window (window)"); return (((void
*)0)); } } while (0)
;
278
279 if (window->details->original_files == NULL((void*)0)) {
280 return NULL((void*)0);
281 }
282
283 return CAJA_FILE (window->details->original_files->data)((((CajaFile*) (void *) ((window->details->original_files
->data)))))
;
284}
285
286static CajaFile *
287get_target_file_for_original_file (CajaFile *file)
288{
289 CajaFile *target_file;
290
291 target_file = NULL((void*)0);
292 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
293 CajaDesktopLink *link;
294
295 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
296
297 if (link != NULL((void*)0)) {
298 GFile *location;
299
300 /* map to linked URI for these types of links */
301 location = caja_desktop_link_get_activation_location (link);
302
303 if (location) {
304 target_file = caja_file_get (location);
305 g_object_unref (location);
306 }
307
308 g_object_unref (link);
309 }
310 } else {
311 char *uri_to_display;
312
313 uri_to_display = caja_file_get_activation_uri (file);
314
315 if (uri_to_display != NULL((void*)0)) {
316 target_file = caja_file_get_by_uri (uri_to_display);
317 g_free (uri_to_display);
318 }
319 }
320
321 if (target_file != NULL((void*)0)) {
322 return target_file;
323 }
324
325 /* Ref passed-in file here since we've decided to use it. */
326 caja_file_ref (file);
327 return file;
328}
329
330static CajaFile *
331get_target_file (FMPropertiesWindow *window)
332{
333 return CAJA_FILE (window->details->target_files->data)((((CajaFile*) (void *) ((window->details->target_files
->data)))))
;
334}
335
336static void
337add_prompt (GtkWidget *vbox, const char *prompt_text, gboolean pack_at_start)
338{
339 GtkWidget *prompt;
340
341 prompt = gtk_label_new (prompt_text);
342 gtk_label_set_justify (GTK_LABEL (prompt)((((GtkLabel*) (void *) ((prompt))))), GTK_JUSTIFY_LEFT);
343 gtk_label_set_line_wrap (GTK_LABEL (prompt)((((GtkLabel*) (void *) ((prompt))))), TRUE(!(0)));
344 gtk_widget_show (prompt);
345 if (pack_at_start) {
346 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), prompt, FALSE(0), FALSE(0), 0);
347 } else {
348 gtk_box_pack_end (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), prompt, FALSE(0), FALSE(0), 0);
349 }
350}
351
352static void
353add_prompt_and_separator (GtkWidget *vbox, const char *prompt_text)
354{
355 GtkWidget *separator_line;
356
357 add_prompt (vbox, prompt_text, FALSE(0));
358
359 separator_line = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
360
361 gtk_widget_show (separator_line);
362 gtk_box_pack_end (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), separator_line, TRUE(!(0)), TRUE(!(0)), 2*ROW_PAD6);
363}
364
365static void
366get_image_for_properties_window (FMPropertiesWindow *window,
367 char **icon_name,
368 GdkPixbuf **icon_pixbuf)
369{
370 CajaIconInfo *icon, *new_icon;
371 GList *l;
372 gint icon_scale;
373
374 icon = NULL((void*)0);
375 icon_scale = gtk_widget_get_scale_factor (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
);
376
377 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
378 CajaFile *file;
379
380 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
381
382 if (!icon) {
383 icon = caja_file_get_icon (file, CAJA_ICON_SIZE_STANDARD48, icon_scale,
384 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS |
385 CAJA_FILE_ICON_FLAGS_IGNORE_VISITING);
386 } else {
387 new_icon = caja_file_get_icon (file, CAJA_ICON_SIZE_STANDARD48, icon_scale,
388 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS |
389 CAJA_FILE_ICON_FLAGS_IGNORE_VISITING);
390 if (!new_icon || new_icon != icon) {
391 g_object_unref (icon);
392 g_object_unref (new_icon);
393 icon = NULL((void*)0);
394 break;
395 }
396 g_object_unref (new_icon);
397 }
398 }
399
400 if (!icon) {
401 icon = caja_icon_info_lookup_from_name ("text-x-generic",
402 CAJA_ICON_SIZE_STANDARD48,
403 icon_scale);
404 }
405
406 if (icon_name != NULL((void*)0)) {
407 *icon_name = g_strdup (caja_icon_info_get_used_name (icon))g_strdup_inline (caja_icon_info_get_used_name (icon));
408 }
409
410 if (icon_pixbuf != NULL((void*)0)) {
411 *icon_pixbuf = caja_icon_info_get_pixbuf_at_size (icon, CAJA_ICON_SIZE_STANDARD48);
412 }
413
414 g_object_unref (icon);
415}
416
417
418static void
419update_properties_window_icon (FMPropertiesWindow *window)
420{
421 GdkPixbuf *pixbuf;
422 cairo_surface_t *surface;
423 char *name;
424
425 get_image_for_properties_window (window, &name, &pixbuf);
426
427 if (name != NULL((void*)0)) {
428 gtk_window_set_icon_name (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), name);
429 } else {
430 gtk_window_set_icon (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), pixbuf);
431 }
432
433 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, gtk_widget_get_scale_factor (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))),
434 gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))));
435 gtk_image_set_from_surface (GTK_IMAGE (window->details->icon_image)((((GtkImage*) (void *) ((window->details->icon_image))
)))
, surface);
436
437 g_free (name);
438 g_object_unref (pixbuf);
439 cairo_surface_destroy (surface);
440}
441
442/* utility to test if a uri refers to a local image */
443static gboolean
444uri_is_local_image (const char *uri)
445{
446 GdkPixbuf *pixbuf;
447 char *image_path;
448
449 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
450 if (image_path == NULL((void*)0)) {
451 return FALSE(0);
452 }
453
454 pixbuf = gdk_pixbuf_new_from_file (image_path, NULL((void*)0));
455 g_free (image_path);
456
457 if (pixbuf == NULL((void*)0)) {
458 return FALSE(0);
459 }
460 g_object_unref (pixbuf);
461 return TRUE(!(0));
462}
463
464
465static void
466reset_icon (FMPropertiesWindow *properties_window)
467{
468 GList *l;
469
470 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
471 CajaFile *file;
472
473 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
474
475 caja_file_set_metadata (file,
476 CAJA_METADATA_KEY_ICON_SCALE"icon-scale",
477 NULL((void*)0), NULL((void*)0));
478 caja_file_set_metadata (file,
479 CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon",
480 NULL((void*)0), NULL((void*)0));
481 }
482}
483
484
485static void
486fm_properties_window_drag_data_received (GtkWidget *widget, GdkDragContext *context,
487 int x, int y,
488 GtkSelectionData *selection_data,
489 guint info, guint time)
490{
491 char **uris;
492 gboolean exactly_one;
493 GtkImage *image;
494 GtkWindow *window;
495
496 image = GTK_IMAGE (widget)((((GtkImage*) (void *) ((widget)))));
497 window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (image)))((((GtkWindow*) (void *) ((gtk_widget_get_toplevel (((((GtkWidget
*) (void *) ((image)))))))))))
;
498
499 if (info == TARGET_RESET_BACKGROUND) {
500 reset_icon (FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) ((window))))));
501
502 return;
503 }
504
505 uris = g_strsplit (gtk_selection_data_get_data (selection_data), "\r\n", 0);
506 exactly_one = uris[0] != NULL((void*)0) && (uris[1] == NULL((void*)0) || uris[1][0] == '\0');
507
508
509 if (!exactly_one) {
510 eel_show_error_dialog
511 (_("You cannot assign more than one custom icon at a time!")dcgettext (((void*)0), "You cannot assign more than one custom icon at a time!"
, 5)
,
512 _("Please drag just one image to set a custom icon.")dcgettext (((void*)0), "Please drag just one image to set a custom icon."
, 5)
,
513 window);
514 } else {
515 if (uri_is_local_image (uris[0])) {
516 set_icon (uris[0], FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) ((window))))));
517 } else {
518 GFile *f;
519
520 f = g_file_new_for_uri (uris[0]);
521 if (!g_file_is_native (f)) {
522 eel_show_error_dialog
523 (_("The file that you dropped is not local.")dcgettext (((void*)0), "The file that you dropped is not local."
, 5)
,
524 _("You can only use local images as custom icons.")dcgettext (((void*)0), "You can only use local images as custom icons."
, 5)
,
525 window);
526
527 } else {
528 eel_show_error_dialog
529 (_("The file that you dropped is not an image.")dcgettext (((void*)0), "The file that you dropped is not an image."
, 5)
,
530 _("You can only use local images as custom icons.")dcgettext (((void*)0), "You can only use local images as custom icons."
, 5)
,
531 window);
532 }
533 g_object_unref (f);
534 }
535 }
536 g_strfreev (uris);
537}
538
539static GtkWidget *
540create_image_widget (FMPropertiesWindow *window,
541 gboolean is_customizable)
542{
543 GtkWidget *button;
544 GtkWidget *image;
545
546 image = gtk_image_new ();
547 window->details->icon_image = image;
548
549 update_properties_window_icon (window);
550 gtk_widget_show (image);
551
552 button = NULL((void*)0);
553 if (is_customizable) {
554 button = gtk_button_new ();
555 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), image);
556
557 /* prepare the image to receive dropped objects to assign custom images */
558 gtk_drag_dest_set (GTK_WIDGET (image)((((GtkWidget*) (void *) ((image))))),
559 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
560 target_table, G_N_ELEMENTS (target_table)(sizeof (target_table) / sizeof ((target_table)[0])),
561 GDK_ACTION_COPY | GDK_ACTION_MOVE);
562
563 g_signal_connect (image, "drag_data_received",g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
564 G_CALLBACK (fm_properties_window_drag_data_received), NULL)g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
;
565 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
566 G_CALLBACK (select_image_button_callback), window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
567 }
568
569 window->details->icon_button = button;
570
571 return button != NULL((void*)0) ? button : image;
572}
573
574static void
575set_name_field (FMPropertiesWindow *window,
576 const gchar *original_name,
577 const gchar *name)
578{
579 gboolean new_widget;
580 gboolean use_label;
581
582 /* There are four cases here:
583 * 1) Changing the text of a label
584 * 2) Changing the text of an entry
585 * 3) Creating label (potentially replacing entry)
586 * 4) Creating entry (potentially replacing label)
587 */
588 use_label = is_multi_file_window (window) || !caja_file_can_rename (get_original_file (window));
589 new_widget = !window->details->name_field || (use_label ? CAJA_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (caja_entry_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; }))))
: GTK_IS_LABEL (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = ((gtk_label_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; }))))
);
590
591 if (new_widget) {
592 if (window->details->name_field) {
593 gtk_widget_destroy (window->details->name_field);
594 }
595
596 if (use_label) {
597 window->details->name_field = GTK_WIDGET((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
598 (attach_ellipsizing_value_label (window->details->basic_grid,((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
599 GTK_WIDGET (window->details->name_label),((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
600 name))((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
;
601
602 } else {
603 window->details->name_field = caja_entry_new ();
604 gtk_entry_set_text (GTK_ENTRY (window->details->name_field)((((GtkEntry*) (void *) ((window->details->name_field))
)))
, name);
605 gtk_widget_show (window->details->name_field);
606 gtk_grid_attach_next_to (window->details->basic_grid, window->details->name_field,
607 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
,
608 GTK_POS_RIGHT, 1, 1);
609
610 gtk_label_set_mnemonic_widget (GTK_LABEL (window->details->name_label)((((GtkLabel*) (void *) ((window->details->name_label))
)))
, window->details->name_field);
611
612 g_signal_connect_object (window->details->name_field, "focus_out_event",
613 G_CALLBACK (name_field_focus_out)((GCallback) (name_field_focus_out)), window, 0);
614 g_signal_connect_object (window->details->name_field, "activate",
615 G_CALLBACK (name_field_activate)((GCallback) (name_field_activate)), window, 0);
616 }
617
618 gtk_widget_show (window->details->name_field);
619 }
620 /* Only replace text if the file's name has changed. */
621 else if (original_name == NULL((void*)0) || strcmp (original_name, name) != 0) {
622
623 if (use_label) {
624 gtk_label_set_text (GTK_LABEL (window->details->name_field)((((GtkLabel*) (void *) ((window->details->name_field))
)))
, name);
625 } else {
626 /* Only reset the text if it's different from what is
627 * currently showing. This causes minimal ripples (e.g.
628 * selection change).
629 */
630 gchar *displayed_name = gtk_editable_get_chars (GTK_EDITABLE (window->details->name_field)((((GtkEditable*) (void *) ((window->details->name_field
)))))
, 0, -1);
631 if (strcmp (displayed_name, name) != 0) {
632 gtk_entry_set_text (GTK_ENTRY (window->details->name_field)((((GtkEntry*) (void *) ((window->details->name_field))
)))
, name);
633 }
634 g_free (displayed_name);
635 }
636 }
637}
638
639static void
640update_name_field (FMPropertiesWindow *window)
641{
642 CajaFile *file;
643
644 gtk_label_set_text_with_mnemonic (window->details->name_label,
645 ngettext ("_Name:", "_Names:",dcngettext (((void*)0), "_Name:", "_Names:", get_not_gone_original_file_count
(window), 5)
646 get_not_gone_original_file_count (window))dcngettext (((void*)0), "_Name:", "_Names:", get_not_gone_original_file_count
(window), 5)
);
647
648 if (is_multi_file_window (window)) {
649 /* Multifile property dialog, show all names */
650 GString *str;
651 char *name;
652 gboolean first;
653 GList *l;
654
655 str = g_string_new ("");
656
657 first = TRUE(!(0));
658
659 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
660 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
661
662 if (!caja_file_is_gone (file)) {
663 if (!first) {
664 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_284; if (__val != ((void
*)0)) _g_boolean_var_284 = 1; else _g_boolean_var_284 = 0; _g_boolean_var_284
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
665 }
666 first = FALSE(0);
667
668 name = caja_file_get_display_name (file);
669 g_string_append (str, name)(__builtin_constant_p (name) ? __extension__ ({ const char * const
__val = (name); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_285; if (__val != ((void
*)0)) _g_boolean_var_285 = 1; else _g_boolean_var_285 = 0; _g_boolean_var_285
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, name, (gssize) -1
))
;
670 g_free (name);
671 }
672 }
673 set_name_field (window, NULL((void*)0), str->str);
674 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
675 } else {
676 const char *original_name = NULL((void*)0);
677 char *current_name;
678
679 file = get_original_file (window);
680
681 if (file == NULL((void*)0) || caja_file_is_gone (file)) {
682 current_name = g_strdup ("")g_strdup_inline ("");
683 } else {
684 current_name = caja_file_get_display_name (file);
685 }
686
687 /* If the file name has changed since the original name was stored,
688 * update the text in the text field, possibly (deliberately) clobbering
689 * an edit in progress. If the name hasn't changed (but some other
690 * aspect of the file might have), then don't clobber changes.
691 */
692 if (window->details->name_field) {
693 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
, "original_name");
694 }
695
696 set_name_field (window, original_name, current_name);
697
698 if (original_name == NULL((void*)0) ||
699 g_strcmp0 (original_name, current_name) != 0) {
700 g_object_set_data_full (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
,
701 "original_name",
702 current_name,
703 g_free);
704 } else {
705 g_free (current_name);
706 }
707 }
708}
709
710static void
711name_field_restore_original_name (CajaEntry *name_field)
712{
713 const char *original_name;
714 char *displayed_name;
715
716 original_name = (const char *) g_object_get_data (G_OBJECT (name_field)((((GObject*) (void *) ((name_field))))),
717 "original_name");
718
719 if (!original_name) {
720 return;
721 }
722
723 displayed_name = gtk_editable_get_chars (GTK_EDITABLE (name_field)((((GtkEditable*) (void *) ((name_field))))), 0, -1);
724
725 if (strcmp (original_name, displayed_name) != 0) {
726 gtk_entry_set_text (GTK_ENTRY (name_field)((((GtkEntry*) (void *) ((name_field))))), original_name);
727 }
728 caja_entry_select_all (name_field);
729
730 g_free (displayed_name);
731}
732
733static void
734rename_callback (CajaFile *file, GFile *res_loc, GError *error, gpointer callback_data)
735{
736 FMPropertiesWindow *window;
737
738 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
739
740 /* Complain to user if rename failed. */
741 if (error != NULL((void*)0)) {
742 fm_report_error_renaming_file (file,
743 window->details->pending_name,
744 error,
745 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
746 if (window->details->name_field != NULL((void*)0)) {
747 name_field_restore_original_name (CAJA_ENTRY (window->details->name_field)((((CajaEntry*) (void *) ((window->details->name_field)
))))
);
748 }
749 }
750
751 g_object_unref (window);
752}
753
754static void
755set_pending_name (FMPropertiesWindow *window, const char *name)
756{
757 g_free (window->details->pending_name);
758 window->details->pending_name = g_strdup (name)g_strdup_inline (name);
759}
760
761static void
762name_field_done_editing (CajaEntry *name_field, FMPropertiesWindow *window)
763{
764 CajaFile *file;
765 char *new_name;
766
767 g_return_if_fail (CAJA_IS_ENTRY (name_field))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_286
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (caja_entry_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__)), "CAJA_IS_ENTRY (name_field)"); return; }
} while (0)
;
768
769 /* Don't apply if the dialog has more than one file */
770 if (is_multi_file_window (window)) {
771 return;
772 }
773
774 file = get_original_file (window);
775
776 /* This gets called when the window is closed, which might be
777 * caused by the file having been deleted.
778 */
779 if (file == NULL((void*)0) || caja_file_is_gone (file)) {
780 return;
781 }
782
783 new_name = gtk_editable_get_chars (GTK_EDITABLE (name_field)((((GtkEditable*) (void *) ((name_field))))), 0, -1);
784
785 /* Special case: silently revert text if new text is empty. */
786 if (strlen (new_name) == 0) {
787 name_field_restore_original_name (CAJA_ENTRY (name_field)((((CajaEntry*) (void *) ((name_field))))));
788 } else {
789 const char *original_name;
790
791 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
,
792 "original_name");
793 /* Don't rename if not changed since we read the display name.
794 This is needed so that we don't save the display name to the
795 file when nothing is changed */
796 if (strcmp (new_name, original_name) != 0) {
797 set_pending_name (window, new_name);
798 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
799 caja_file_rename (file, new_name,
800 rename_callback, window);
801 }
802 }
803
804 g_free (new_name);
805}
806
807static gboolean
808name_field_focus_out (CajaEntry *name_field,
809 GdkEventFocus *event,
810 gpointer callback_data)
811{
812 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_287
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_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_287 = 1; else _g_boolean_var_287 =
0; _g_boolean_var_287; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 812, ((const char*)
(__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"); } while
(0)
;
813
814 if (gtk_widget_get_sensitive (GTK_WIDGET (name_field)((((GtkWidget*) (void *) ((name_field))))))) {
815 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data))))));
816 }
817
818 return FALSE(0);
819}
820
821static void
822name_field_activate (CajaEntry *name_field, gpointer callback_data)
823{
824 g_assert (CAJA_IS_ENTRY (name_field))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_288
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (caja_entry_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_288
= 1; else _g_boolean_var_288 = 0; _g_boolean_var_288; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 824, ((const char*) (__func__)), "CAJA_IS_ENTRY (name_field)"
); } while (0)
;
825 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_289
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_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_289 = 1; else _g_boolean_var_289 =
0; _g_boolean_var_289; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 825, ((const char*)
(__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"); } while
(0)
;
826
827 /* Accept changes. */
828 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data))))));
829
830 caja_entry_select_all_at_idle (name_field);
831}
832
833static gboolean
834file_has_keyword (CajaFile *file, const char *keyword)
835{
836 GList *keywords, *word;
837
838 keywords = caja_file_get_keywords (file);
839 word = g_list_find_custom (keywords, keyword, (GCompareFunc) strcmp);
840 g_list_free_full (keywords, g_free);
841
842 return (word != NULL((void*)0));
843}
844
845static void
846get_initial_emblem_state (FMPropertiesWindow *window,
847 const char *name,
848 GList **on,
849 GList **off)
850{
851 GList *l;
852
853 *on = NULL((void*)0);
854 *off = NULL((void*)0);
855
856 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
857 GList *initial_emblems;
858
859 initial_emblems = g_hash_table_lookup (window->details->initial_emblems,
860 l->data);
861
862 if (g_list_find_custom (initial_emblems, name, (GCompareFunc) strcmp)) {
863 *on = g_list_prepend (*on, l->data);
864 } else {
865 *off = g_list_prepend (*off, l->data);
866 }
867 }
868}
869
870static void
871emblem_button_toggled (GtkToggleButton *button,
872 FMPropertiesWindow *window)
873{
874 GList *l;
875 GList *keywords;
876 GList *word;
877 char *name;
878 GList *files_on;
879 GList *files_off;
880
881 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name");
882
883 files_on = NULL((void*)0);
884 files_off = NULL((void*)0);
885 if (gtk_toggle_button_get_active (button)
886 && !gtk_toggle_button_get_inconsistent (button)) {
887 /* Go to the initial state unless the initial state was
888 consistent */
889 get_initial_emblem_state (window, name,
890 &files_on, &files_off);
891
892 if (!(files_on && files_off)) {
893 g_list_free (files_on);
894 g_list_free (files_off);
895 files_on = g_list_copy (window->details->original_files);
896 files_off = NULL((void*)0);
897 }
898 } else if (gtk_toggle_button_get_inconsistent (button)
899 && !gtk_toggle_button_get_active (button)) {
900 files_on = g_list_copy (window->details->original_files);
901 files_off = NULL((void*)0);
902 } else {
903 files_off = g_list_copy (window->details->original_files);
904 files_on = NULL((void*)0);
905 }
906
907 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
908 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
909 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
910
911 gtk_toggle_button_set_active (button, files_on != NULL((void*)0));
912 gtk_toggle_button_set_inconsistent (button, files_on && files_off);
913
914 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
915 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
916 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
917
918 for (l = files_on; l != NULL((void*)0); l = l->next) {
919 CajaFile *file;
920
921 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
922
923 keywords = caja_file_get_keywords (file);
924
925 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
926 if (!word) {
927 keywords = g_list_prepend (keywords, g_strdup (name)g_strdup_inline (name));
928 }
929 caja_file_set_keywords (file, keywords);
930 g_list_free_full (keywords, g_free);
931 }
932
933 for (l = files_off; l != NULL((void*)0); l = l->next) {
934 CajaFile *file;
935
936 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
937
938 keywords = caja_file_get_keywords (file);
939
940 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
941 if (word) {
942 keywords = g_list_remove_link (keywords, word);
943 g_list_free_full (word, g_free);
944 }
945 caja_file_set_keywords (file, keywords);
946 g_list_free_full (keywords, g_free);
947 }
948
949 g_list_free (files_on);
950 g_list_free (files_off);
951}
952
953static void
954emblem_button_update (FMPropertiesWindow *window,
955 GtkToggleButton *button)
956{
957 GList *l;
958 char *name;
959 gboolean all_set;
960 gboolean all_unset;
961
962 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name");
963
964 all_set = TRUE(!(0));
965 all_unset = TRUE(!(0));
966 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
967 gboolean has_keyword;
968 CajaFile *file;
969
970 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
971
972 has_keyword = file_has_keyword (file, name);
973
974 if (has_keyword) {
975 all_unset = FALSE(0);
976 } else {
977 all_set = FALSE(0);
978 }
979 }
980
981 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
982 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
983 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
984
985 gtk_toggle_button_set_active (button, !all_unset);
986 gtk_toggle_button_set_inconsistent (button, !all_unset && !all_set);
987
988 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
989 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
990 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
991
992}
993
994static void
995update_properties_window_title (FMPropertiesWindow *window)
996{
997 char *title;
998
999 g_return_if_fail (GTK_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_290
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((gtk_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_290
= 1; else _g_boolean_var_290 = 0; _g_boolean_var_290; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "GTK_IS_WINDOW (window)"); return; } } while
(0)
;
1000
1001 title = g_strdup_printf (_("Properties")dcgettext (((void*)0), "Properties", 5));
1002
1003 if (!is_multi_file_window (window)) {
1004 CajaFile *file;
1005
1006 file = get_original_file (window);
1007
1008 if (file != NULL((void*)0)) {
1009 char *name;
1010
1011 g_free (title);
1012 name = caja_file_get_display_name (file);
1013 title = g_strdup_printf (_("%s Properties")dcgettext (((void*)0), "%s Properties", 5), name);
1014 g_free (name);
1015 }
1016 }
1017
1018 gtk_window_set_title (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), title);
1019
1020 g_free (title);
1021}
1022
1023static void
1024clear_extension_pages (FMPropertiesWindow *window)
1025{
1026 int i;
1027 int num_pages;
1028 GtkWidget *page = NULL((void*)0);
1029
1030 num_pages = gtk_notebook_get_n_pages
1031 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
);
1032
1033 for (i = 0; i < num_pages; i++) {
1034 page = gtk_notebook_get_nth_page
1035 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
, i);
1036
1037 if (g_object_get_data (G_OBJECT (page)((((GObject*) (void *) ((page))))), "is-extension-page")) {
1038 gtk_notebook_remove_page
1039 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
, i);
1040 num_pages--;
1041 i--;
1042 }
1043 }
1044}
1045
1046static void
1047refresh_extension_pages (FMPropertiesWindow *window)
1048{
1049 clear_extension_pages (window);
1050 append_extension_pages (window);
1051}
1052
1053static void
1054remove_from_dialog (FMPropertiesWindow *window,
1055 CajaFile *file)
1056{
1057 int index;
1058 GList *original_link;
1059 GList *target_link;
1060 CajaFile *original_file;
1061 CajaFile *target_file;
1062
1063 index = g_list_index (window->details->target_files, file);
1064 if (index == -1) {
1065 index = g_list_index (window->details->original_files, file);
1066 g_return_if_fail (index != -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_291
; if (index != -1) _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__)), "index != -1"); return
; } } while (0)
;
1067 }
1068
1069 original_link = g_list_nth (window->details->original_files, index);
1070 target_link = g_list_nth (window->details->target_files, index);
1071
1072 g_return_if_fail (original_link && target_link)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_292
; if (original_link && target_link) _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__)), "original_link && target_link");
return; } } while (0)
;
1073
1074 original_file = CAJA_FILE (original_link->data)((((CajaFile*) (void *) ((original_link->data)))));
1075 target_file = CAJA_FILE (target_link->data)((((CajaFile*) (void *) ((target_link->data)))));
1076
1077 window->details->original_files = g_list_remove_link (window->details->original_files, original_link);
1078 g_list_free (original_link);
1079
1080 window->details->target_files = g_list_remove_link (window->details->target_files, target_link);
1081 g_list_free (target_link);
1082
1083 g_hash_table_remove (window->details->initial_emblems, original_file);
1084 g_hash_table_remove (window->details->initial_permissions, target_file);
1085
1086 g_signal_handlers_disconnect_by_func (original_file,g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1087 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1088 window)g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1089 g_signal_handlers_disconnect_by_func (target_file,g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1090 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1091 window)g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1092
1093 caja_file_monitor_remove (original_file, &window->details->original_files);
1094 caja_file_monitor_remove (target_file, &window->details->target_files);
1095
1096 caja_file_unref (original_file);
1097 caja_file_unref (target_file);
1098
1099}
1100
1101static gboolean
1102mime_list_equal (GList *a, GList *b)
1103{
1104 while (a && b) {
1105 if (strcmp (a->data, b->data)) {
1106 return FALSE(0);
1107 }
1108 a = a->next;
1109 b = b->next;
1110 }
1111
1112 return (a == b);
1113}
1114
1115static GList *
1116get_mime_list (FMPropertiesWindow *window)
1117{
1118 GList *ret;
1119 GList *l;
1120
1121 ret = NULL((void*)0);
1122 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
1123 ret = g_list_append (ret, caja_file_get_mime_type (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))))));
1124 }
1125 ret = g_list_reverse (ret);
1126 return ret;
1127}
1128
1129static void
1130properties_window_update (FMPropertiesWindow *window,
1131 GList *files)
1132{
1133 GList *l;
1134 GList *mime_list;
1135 GList *tmp;
1136 CajaFile *changed_file = NULL((void*)0);
1137 gboolean dirty_original = FALSE(0);
1138 gboolean dirty_target = FALSE(0);
1139
1140 if (files == NULL((void*)0)) {
1141 dirty_original = TRUE(!(0));
1142 dirty_target = TRUE(!(0));
1143 }
1144
1145 for (tmp = files; tmp != NULL((void*)0); tmp = tmp->next) {
1146 changed_file = CAJA_FILE (tmp->data)((((CajaFile*) (void *) ((tmp->data)))));
1147
1148 if (changed_file && caja_file_is_gone (changed_file)) {
1149 /* Remove the file from the property dialog */
1150 remove_from_dialog (window, changed_file);
1151 changed_file = NULL((void*)0);
1152
1153 if (window->details->original_files == NULL((void*)0)) {
1154 return;
1155 }
1156 }
1157 if (changed_file == NULL((void*)0) ||
1158 g_list_find (window->details->original_files, changed_file)) {
1159 dirty_original = TRUE(!(0));
1160 }
1161 if (changed_file == NULL((void*)0) ||
1162 g_list_find (window->details->target_files, changed_file)) {
1163 dirty_target = TRUE(!(0));
1164 }
1165
1166 }
1167
1168 if (dirty_original) {
1169 update_properties_window_title (window);
1170 update_properties_window_icon (window);
1171 update_name_field (window);
1172
1173 for (l = window->details->emblem_buttons; l != NULL((void*)0); l = l->next) {
1174 emblem_button_update (window, GTK_TOGGLE_BUTTON (l->data)((((GtkToggleButton*) (void *) ((l->data))))));
1175 }
1176
1177 /* If any of the value fields start to depend on the original
1178 * value, value_field_updates should be added here */
1179 }
1180
1181 if (dirty_target) {
1182 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
1183 permission_button_update (window, GTK_TOGGLE_BUTTON (l->data)((((GtkToggleButton*) (void *) ((l->data))))));
1184 }
1185
1186 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
1187 permission_combo_update (window, GTK_COMBO_BOX (l->data)((((GtkComboBox*) (void *) ((l->data))))));
1188 }
1189
1190 for (l = window->details->value_fields; l != NULL((void*)0); l = l->next) {
1191 value_field_update (window, GTK_LABEL (l->data)((((GtkLabel*) (void *) ((l->data))))));
1192 }
1193 }
1194
1195 mime_list = get_mime_list (window);
1196
1197 if (!window->details->mime_list) {
1198 window->details->mime_list = mime_list;
1199 } else {
1200 if (!mime_list_equal (window->details->mime_list, mime_list)) {
1201 refresh_extension_pages (window);
1202 }
1203
1204 g_list_free_full (window->details->mime_list, g_free);
1205 window->details->mime_list = mime_list;
1206 }
1207}
1208
1209static gboolean
1210update_files_callback (gpointer data)
1211{
1212 FMPropertiesWindow *window;
1213
1214 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
1215
1216 window->details->update_files_timeout_id = 0;
1217
1218 properties_window_update (window, window->details->changed_files);
1219
1220 if (window->details->original_files == NULL((void*)0)) {
1221 /* Close the window if no files are left */
1222 gtk_widget_destroy (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
1223 } else {
1224 caja_file_list_free (window->details->changed_files);
1225 window->details->changed_files = NULL((void*)0);
1226 }
1227
1228 return FALSE(0);
1229 }
1230
1231static void
1232schedule_files_update (FMPropertiesWindow *window)
1233 {
1234 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_293
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_293 = 1; else _g_boolean_var_293 = 0; _g_boolean_var_293
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1234, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1235
1236 if (window->details->update_files_timeout_id == 0) {
1237 window->details->update_files_timeout_id
1238 = g_timeout_add (FILES_UPDATE_INTERVAL200,
1239 update_files_callback,
1240 window);
1241 }
1242 }
1243
1244static gboolean
1245file_list_attributes_identical (GList *file_list, const char *attribute_name)
1246{
1247 gboolean identical;
1248 char *first_attr;
1249 GList *l;
1250
1251 first_attr = NULL((void*)0);
1252 identical = TRUE(!(0));
1253
1254 for (l = file_list; l != NULL((void*)0); l = l->next) {
1255 CajaFile *file;
1256
1257 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1258
1259 if (caja_file_is_gone (file)) {
1260 continue;
1261 }
1262
1263 if (first_attr == NULL((void*)0)) {
1264 first_attr = caja_file_get_string_attribute_with_default (file, attribute_name);
1265 } else {
1266 char *attr;
1267 attr = caja_file_get_string_attribute_with_default (file, attribute_name);
1268 if (strcmp (attr, first_attr)) {
1269 identical = FALSE(0);
1270 g_free (attr);
1271 break;
1272 }
1273 g_free (attr);
1274 }
1275 }
1276
1277 g_free (first_attr);
1278 return identical;
1279}
1280
1281static char *
1282file_list_get_string_attribute (GList *file_list,
1283 const char *attribute_name,
1284 const char *inconsistent_value)
1285{
1286 if (file_list_attributes_identical (file_list, attribute_name)) {
1287 GList *l;
1288
1289 for (l = file_list; l != NULL((void*)0); l = l->next) {
1290 CajaFile *file;
1291
1292 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1293 if (!caja_file_is_gone (file)) {
1294 return caja_file_get_string_attribute_with_default
1295 (file,
1296 attribute_name);
1297 }
1298 }
1299 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
1300 } else {
1301 return g_strdup (inconsistent_value)g_strdup_inline (inconsistent_value);
1302 }
1303}
1304
1305
1306static gboolean
1307file_list_all_directories (GList *file_list)
1308{
1309 GList *l;
1310 for (l = file_list; l != NULL((void*)0); l = l->next) {
1311 if (!caja_file_is_directory (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
1312 return FALSE(0);
1313 }
1314 }
1315 return TRUE(!(0));
1316}
1317
1318static void
1319value_field_update_internal (GtkLabel *label,
1320 GList *file_list)
1321{
1322 const char *attribute_name;
1323 char *attribute_value;
1324 char *inconsistent_string;
1325
1326 g_assert (GTK_IS_LABEL (label))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_294
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((gtk_label_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_294
= 1; else _g_boolean_var_294 = 0; _g_boolean_var_294; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1326, ((const char*) (__func__)), "GTK_IS_LABEL (label)"); }
while (0)
;
1327
1328 attribute_name = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) ((label))))), "file_attribute");
1329 inconsistent_string = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) ((label))))), "inconsistent_string");
1330 attribute_value = file_list_get_string_attribute (file_list,
1331 attribute_name,
1332 inconsistent_string);
1333 if (!strcmp (attribute_name, "type") && strcmp (attribute_value, inconsistent_string)) {
1334 char *mime_type;
1335
1336 mime_type = file_list_get_string_attribute (file_list,
1337 "mime_type",
1338 inconsistent_string);
1339 if (strcmp (mime_type, inconsistent_string)) {
1340 char *tmp;
1341
1342 tmp = attribute_value;
1343 attribute_value = g_strdup_printf (C_("MIME type description (MIME type)", "%s (%s)")g_dpgettext (((void*)0), "MIME type description (MIME type)" "\004"
"%s (%s)", strlen ("MIME type description (MIME type)") + 1)
, attribute_value, mime_type);
1344 g_free (tmp);
1345 }
1346 g_free (mime_type);
1347 }
1348
1349 gtk_label_set_text (label, attribute_value);
1350 g_free (attribute_value);
1351}
1352
1353static void
1354value_field_update (FMPropertiesWindow *window, GtkLabel *label)
1355{
1356 gboolean use_original;
1357
1358 use_original = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), "show_original"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
label))))), "show_original")))
;
1359
1360 value_field_update_internal (label,
1361 (use_original ?
1362 window->details->original_files :
1363 window->details->target_files));
1364}
1365
1366static GtkLabel *
1367attach_label (GtkGrid *grid,
1368 GtkWidget *sibling,
1369 const char *initial_text,
1370 gboolean ellipsize_text,
1371 gboolean selectable,
1372 gboolean mnemonic)
1373{
1374 GtkWidget *label_field;
1375
1376 if (ellipsize_text) {
1377 label_field = gtk_label_new (initial_text);
1378 gtk_label_set_ellipsize (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))),
1379 PANGO_ELLIPSIZE_END);
1380 } else if (mnemonic) {
1381 label_field = gtk_label_new_with_mnemonic (initial_text);
1382 } else {
1383 label_field = gtk_label_new (initial_text);
1384 }
1385
1386 if (selectable) {
1387 gtk_label_set_selectable (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), TRUE(!(0)));
1388 }
1389
1390 gtk_label_set_xalign (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), 0);
1391 gtk_widget_show (label_field);
1392 if (ellipsize_text) {
1393 gtk_widget_set_hexpand (label_field, TRUE(!(0)));
1394 gtk_label_set_max_width_chars (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), 24);
1395 }
1396
1397 if (sibling != NULL((void*)0)) {
1398 gtk_grid_attach_next_to (grid, label_field, sibling,
1399 GTK_POS_RIGHT, 1, 1);
1400 } else {
1401 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), label_field);
1402 }
1403
1404 return GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field)))));
1405}
1406
1407static GtkLabel *
1408attach_value_label (GtkGrid *grid,
1409 GtkWidget *sibling,
1410 const char *initial_text)
1411{
1412 return attach_label (grid, sibling, initial_text, FALSE(0), TRUE(!(0)), FALSE(0));
1413}
1414
1415static GtkLabel *
1416attach_ellipsizing_value_label (GtkGrid *grid,
1417 GtkWidget *sibling,
1418 const char *initial_text)
1419{
1420 return attach_label (grid, sibling, initial_text, TRUE(!(0)), TRUE(!(0)), FALSE(0));
1421}
1422
1423static GtkWidget*
1424attach_value_field_internal (FMPropertiesWindow *window,
1425 GtkGrid *grid,
1426 GtkWidget *sibling,
1427 const char *file_attribute_name,
1428 const char *inconsistent_string,
1429 gboolean show_original,
1430 gboolean ellipsize_text)
1431{
1432 GtkLabel *value_field;
1433
1434 if (ellipsize_text) {
1435 value_field = attach_ellipsizing_value_label (grid, sibling, "");
1436 } else {
1437 value_field = attach_value_label (grid, sibling, "");
1438 }
1439
1440 /* Stash a copy of the file attribute name in this field for the callback's sake. */
1441 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "file_attribute",
1442 g_strdup (file_attribute_name)g_strdup_inline (file_attribute_name), g_free);
1443
1444 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "inconsistent_string",
1445 g_strdup (inconsistent_string)g_strdup_inline (inconsistent_string), g_free);
1446
1447 g_object_set_data (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "show_original", GINT_TO_POINTER (show_original)((gpointer) (glong) (show_original)));
1448
1449 window->details->value_fields = g_list_prepend (window->details->value_fields,
1450 value_field);
1451 return GTK_WIDGET(value_field)((((GtkWidget*) (void *) ((value_field)))));
1452}
1453
1454static GtkWidget*
1455attach_value_field (FMPropertiesWindow *window,
1456 GtkGrid *grid,
1457 GtkWidget *sibling,
1458 const char *file_attribute_name,
1459 const char *inconsistent_string,
1460 gboolean show_original)
1461{
1462 return attach_value_field_internal (window,
1463 grid, sibling,
1464 file_attribute_name,
1465 inconsistent_string,
1466 show_original,
1467 FALSE(0));
1468}
1469
1470static GtkWidget*
1471attach_ellipsizing_value_field (FMPropertiesWindow *window,
1472 GtkGrid *grid,
1473 GtkWidget *sibling,
1474 const char *file_attribute_name,
1475 const char *inconsistent_string,
1476 gboolean show_original)
1477{
1478 return attach_value_field_internal (window,
1479 grid, sibling,
1480 file_attribute_name,
1481 inconsistent_string,
1482 show_original,
1483 TRUE(!(0)));
1484}
1485
1486static void
1487group_change_callback (CajaFile *file,
1488 GFile *res_loc,
1489 GError *error,
1490 FMPropertiesWindow *window)
1491{
1492 char *group;
1493
1494 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_295
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_295 = 1; else _g_boolean_var_295 = 0; _g_boolean_var_295
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1494, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1495 g_assert (window->details->group_change_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_296
; if (window->details->group_change_file == file) _g_boolean_var_296
= 1; else _g_boolean_var_296 = 0; _g_boolean_var_296; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1495, ((const char*) (__func__)), "window->details->group_change_file == file"
); } while (0)
;
1496
1497 group = window->details->group_change_group;
1498 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_297
; if (group != ((void*)0)) _g_boolean_var_297 = 1; else _g_boolean_var_297
= 0; _g_boolean_var_297; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1498, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1499
1500 /* Report the error if it's an error. */
1501 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1502 fm_report_error_setting_group (file, error, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1503
1504 caja_file_unref (file);
1505 g_free (group);
1506
1507 window->details->group_change_file = NULL((void*)0);
1508 window->details->group_change_group = NULL((void*)0);
1509 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1510}
1511
1512static void
1513cancel_group_change_callback (FMPropertiesWindow *window)
1514{
1515 CajaFile *file;
1516 char *group;
1517
1518 file = window->details->group_change_file;
1519 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_298
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_298
= 1; else _g_boolean_var_298 = 0; _g_boolean_var_298; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1519, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1520
1521 group = window->details->group_change_group;
1522 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_299
; if (group != ((void*)0)) _g_boolean_var_299 = 1; else _g_boolean_var_299
= 0; _g_boolean_var_299; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1522, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1523
1524 caja_file_cancel (file, (CajaFileOperationCallback) group_change_callback, window);
1525
1526 g_free (group);
1527 caja_file_unref (file);
1528
1529 window->details->group_change_file = NULL((void*)0);
1530 window->details->group_change_group = NULL((void*)0);
1531 g_object_unref (window);
1532}
1533
1534static gboolean
1535schedule_group_change_timeout (FMPropertiesWindow *window)
1536{
1537 CajaFile *file;
1538 char *group;
1539
1540 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_300
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_300 = 1; else _g_boolean_var_300 = 0; _g_boolean_var_300
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1540, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1541
1542 file = window->details->group_change_file;
1543 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_301
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_301
= 1; else _g_boolean_var_301 = 0; _g_boolean_var_301; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1543, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1544
1545 group = window->details->group_change_group;
1546 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_302
; if (group != ((void*)0)) _g_boolean_var_302 = 1; else _g_boolean_var_302
= 0; _g_boolean_var_302; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1546, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1547
1548 eel_timed_wait_start
1549 ((EelCancelCallback) cancel_group_change_callback,
1550 window,
1551 _("Cancel Group Change?")dcgettext (((void*)0), "Cancel Group Change?", 5),
1552 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1553
1554 caja_file_set_group
1555 (file, group,
1556 (CajaFileOperationCallback) group_change_callback, window);
1557
1558 window->details->group_change_timeout = 0;
1559 return FALSE(0);
1560}
1561
1562static void
1563schedule_group_change (FMPropertiesWindow *window,
1564 CajaFile *file,
1565 const char *group)
1566{
1567 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_303
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_303 = 1; else _g_boolean_var_303 = 0; _g_boolean_var_303
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1567, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1568 g_assert (window->details->group_change_group == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_304
; if (window->details->group_change_group == ((void*)0)
) _g_boolean_var_304 = 1; else _g_boolean_var_304 = 0; _g_boolean_var_304
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1568, ((const char*) (__func__)), "window->details->group_change_group == NULL"
); } while (0)
;
1569 g_assert (window->details->group_change_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_305
; if (window->details->group_change_file == ((void*)0))
_g_boolean_var_305 = 1; else _g_boolean_var_305 = 0; _g_boolean_var_305
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1569, ((const char*) (__func__)), "window->details->group_change_file == NULL"
); } while (0)
;
1570 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_306
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_306
= 1; else _g_boolean_var_306 = 0; _g_boolean_var_306; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1570, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1571
1572 window->details->group_change_file = caja_file_ref (file);
1573 window->details->group_change_group = g_strdup (group)g_strdup_inline (group);
1574 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) ((window))))))) (g_object_ref
) (((((GObject*) (void *) ((window)))))))
;
1575 window->details->group_change_timeout =
1576 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1577 (GSourceFunc) schedule_group_change_timeout,
1578 window);
1579}
1580
1581static void
1582unschedule_or_cancel_group_change (FMPropertiesWindow *window)
1583{
1584 CajaFile *file;
1585 char *group;
1586
1587 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_307
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_307 = 1; else _g_boolean_var_307 = 0; _g_boolean_var_307
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1587, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1588
1589 file = window->details->group_change_file;
1590 group = window->details->group_change_group;
1591
1592 g_assert ((file == NULL && group == NULL) ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_308
; if ((file == ((void*)0) && group == ((void*)0)) || (
file != ((void*)0) && group != ((void*)0))) _g_boolean_var_308
= 1; else _g_boolean_var_308 = 0; _g_boolean_var_308; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1593, ((const char*) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
1593 (file != NULL && group != NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_308
; if ((file == ((void*)0) && group == ((void*)0)) || (
file != ((void*)0) && group != ((void*)0))) _g_boolean_var_308
= 1; else _g_boolean_var_308 = 0; _g_boolean_var_308; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1593, ((const char*) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
;
1594
1595 if (file != NULL((void*)0)) {
1596 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_309
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_309
= 1; else _g_boolean_var_309 = 0; _g_boolean_var_309; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1596, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1597
1598 if (window->details->group_change_timeout == 0) {
1599 caja_file_cancel (file,
1600 (CajaFileOperationCallback) group_change_callback, window);
1601 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1602 }
1603
1604 caja_file_unref (file);
1605 g_free (group);
1606
1607 window->details->group_change_file = NULL((void*)0);
1608 window->details->group_change_group = NULL((void*)0);
1609 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1610 }
1611
1612 if (window->details->group_change_timeout > 0) {
1613 g_assert (file != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_310
; if (file != ((void*)0)) _g_boolean_var_310 = 1; else _g_boolean_var_310
= 0; _g_boolean_var_310; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1613, ((const char*
) (__func__)), "file != NULL"); } while (0)
;
1614 g_source_remove (window->details->group_change_timeout);
1615 window->details->group_change_timeout = 0;
1616 }
1617}
1618
1619static void
1620changed_group_callback (GtkComboBox *combo_box, CajaFile *file)
1621{
1622 char *group;
1623 char *cur_group;
1624
1625 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_311
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_311
= 1; else _g_boolean_var_311 = 0; _g_boolean_var_311; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1625, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1626 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_312
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_312
= 1; else _g_boolean_var_312 = 0; _g_boolean_var_312; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1626, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1627
1628 group = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))));
1629 cur_group = caja_file_get_group_name (file);
1630
1631 if (group != NULL((void*)0) && strcmp (group, cur_group) != 0) {
1632 FMPropertiesWindow *window;
1633
1634 /* Try to change file group. If this fails, complain to user. */
1635 window = FM_PROPERTIES_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (combo_box), GTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) ((gtk_widget_get_ancestor (
((((GtkWidget*) (void *) ((combo_box))))), (gtk_window_get_type
())))))))
;
1636
1637 unschedule_or_cancel_group_change (window);
1638 schedule_group_change (window, file, group);
1639 }
1640 g_free (group);
1641 g_free (cur_group);
1642}
1643
1644/* checks whether the given column at the first level
1645 * of model has the specified entries in the given order. */
1646static gboolean
1647tree_model_entries_equal (GtkTreeModel *model,
1648 unsigned int column,
1649 GList *entries)
1650{
1651 GtkTreeIter iter;
1652 gboolean empty_model;
1653
1654 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_313
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_313
= 1; else _g_boolean_var_313 = 0; _g_boolean_var_313; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1654, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1655 g_assert (gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_314
; if (gtk_tree_model_get_column_type (model, column) == ((GType
) ((16) << (2)))) _g_boolean_var_314 = 1; else _g_boolean_var_314
= 0; _g_boolean_var_314; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1655, ((const char*
) (__func__)), "gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1656
1657 empty_model = !gtk_tree_model_get_iter_first (model, &iter);
1658
1659 if (!empty_model && entries != NULL((void*)0)) {
1660 GList *l;
1661
1662 l = entries;
1663
1664 do {
1665 char *val;
1666
1667 gtk_tree_model_get (model, &iter,
1668 column, &val,
1669 -1);
1670 if ((val == NULL((void*)0) && l->data != NULL((void*)0)) ||
1671 (val != NULL((void*)0) && l->data == NULL((void*)0)) ||
1672 (val != NULL((void*)0) && strcmp (val, l->data))) {
1673 g_free (val);
1674 return FALSE(0);
1675 }
1676
1677 g_free (val);
1678 l = l->next;
1679 } while (gtk_tree_model_iter_next (model, &iter));
1680
1681 return l == NULL((void*)0);
1682 } else {
1683 return (empty_model && entries == NULL((void*)0)) ||
1684 (!empty_model && entries != NULL((void*)0));
1685 }
1686}
1687
1688static char *
1689combo_box_get_active_entry (GtkComboBox *combo_box,
1690 unsigned int column)
1691{
1692 GtkTreeIter iter;
1693 char *val;
1694
1695 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_315
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1695, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1696
1697 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box))))), &iter)) {
1698 GtkTreeModel *model;
1699
1700 model = gtk_combo_box_get_model (combo_box);
1701 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_316
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_316
= 1; else _g_boolean_var_316 = 0; _g_boolean_var_316; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1701, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1702
1703 gtk_tree_model_get (model, &iter,
1704 column, &val,
1705 -1);
1706 return val;
1707 }
1708
1709 return NULL((void*)0);
1710}
1711
1712/* returns the index of the given entry in the the given column
1713 * at the first level of model. Returns -1 if entry can't be found
1714 * or entry is NULL.
1715 * */
1716static int
1717tree_model_get_entry_index (GtkTreeModel *model,
1718 unsigned int column,
1719 const char *entry)
1720{
1721 GtkTreeIter iter;
1722 gboolean empty_model;
1723
1724 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_317
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_317
= 1; else _g_boolean_var_317 = 0; _g_boolean_var_317; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1724, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1725 g_assert (gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_318
; if (gtk_tree_model_get_column_type (model, column) == ((GType
) ((16) << (2)))) _g_boolean_var_318 = 1; else _g_boolean_var_318
= 0; _g_boolean_var_318; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1725, ((const char*
) (__func__)), "gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1726
1727 empty_model = !gtk_tree_model_get_iter_first (model, &iter);
1728 if (!empty_model && entry != NULL((void*)0)) {
1729 int index;
1730
1731 index = 0;
1732
1733 do {
1734 char *val;
1735
1736 gtk_tree_model_get (model, &iter,
1737 column, &val,
1738 -1);
1739 if (val != NULL((void*)0) && !strcmp (val, entry)) {
1740 g_free (val);
1741 return index;
1742 }
1743
1744 g_free (val);
1745 index++;
1746 } while (gtk_tree_model_iter_next (model, &iter));
1747 }
1748
1749 return -1;
1750}
1751
1752
1753static void
1754synch_groups_combo_box (GtkComboBox *combo_box, CajaFile *file)
1755{
1756 GList *groups;
1757 GList *node;
1758 GtkTreeModel *model;
1759 GtkListStore *store;
1760 char *current_group_name;
1761 int current_group_index;
1762
1763 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_319
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1763, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1764 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_320
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_320
= 1; else _g_boolean_var_320 = 0; _g_boolean_var_320; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1764, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1765
1766 if (caja_file_is_gone (file)) {
1767 return;
1768 }
1769
1770 groups = caja_file_get_settable_group_names (file);
1771
1772 model = gtk_combo_box_get_model (combo_box);
1773 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
1774 g_assert (GTK_IS_LIST_STORE (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_321
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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_321
= 1; else _g_boolean_var_321 = 0; _g_boolean_var_321; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1774, ((const char*) (__func__)), "GTK_IS_LIST_STORE (model)"
); } while (0)
;
1775
1776 if (!tree_model_entries_equal (model, 0, groups)) {
1777 int group_index;
1778
1779 /* Clear the contents of ComboBox in a wacky way because there
1780 * is no function to clear all items and also no function to obtain
1781 * the number of items in a combobox.
1782 */
1783 gtk_list_store_clear (store);
1784
1785 for (node = groups, group_index = 0; node != NULL((void*)0); node = node->next, ++group_index) {
1786 const char *group_name;
1787
1788 group_name = (const char *)node->data;
1789 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), group_name);
1790 }
1791 }
1792
1793 current_group_name = caja_file_get_group_name (file);
1794 current_group_index = tree_model_get_entry_index (model, 0, current_group_name);
1795
1796 /* If current group wasn't in list, we prepend it (with a separator).
1797 * This can happen if the current group is an id with no matching
1798 * group in the groups file.
1799 */
1800 if (current_group_index < 0 && current_group_name != NULL((void*)0)) {
1801 if (groups != NULL((void*)0)) {
1802 /* add separator */
1803 gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), "-");
1804 }
1805
1806 gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), current_group_name);
1807 current_group_index = 0;
1808 }
1809 gtk_combo_box_set_active (combo_box, current_group_index);
1810
1811 g_free (current_group_name);
1812 g_list_free_full (groups, g_free);
1813}
1814
1815static gboolean
1816combo_box_row_separator_func (GtkTreeModel *model,
1817 GtkTreeIter *iter,
1818 gpointer data)
1819{
1820 gchar *text;
1821 gboolean ret;
1822
1823 gtk_tree_model_get (model, iter, 0, &text, -1);
1824
1825 if (text == NULL((void*)0)) {
1826 return FALSE(0);
1827 }
1828
1829 if (strcmp (text, "-") == 0) {
1830 ret = TRUE(!(0));
1831 } else {
1832 ret = FALSE(0);
1833 }
1834
1835 g_free (text);
1836 return ret;
1837}
1838
1839static GtkComboBox *
1840attach_combo_box (GtkGrid *grid,
1841 GtkWidget *sibling,
1842 gboolean two_columns)
1843{
1844 GtkWidget *combo_box;
1845
1846 if (!two_columns) {
1847 combo_box = gtk_combo_box_text_new ();
1848 } else {
1849 GtkTreeModel *model;
1850 GtkCellRenderer *renderer;
1851
1852 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING))((((GtkTreeModel*) (void *) ((gtk_list_store_new (2, ((GType)
((16) << (2))), ((GType) ((16) << (2)))))))))
;
1853 combo_box = gtk_combo_box_new_with_model (model);
1854 g_object_unref (G_OBJECT (model)((((GObject*) (void *) ((model))))));
1855
1856 renderer = gtk_cell_renderer_text_new ();
1857 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box)((((GtkCellLayout*) (void *) ((combo_box))))), renderer, TRUE(!(0)));
1858 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo_box)((((GtkCellLayout*) (void *) ((combo_box))))), renderer,
1859 "text", 0);
1860
1861 }
1862
1863 gtk_widget_set_halign (combo_box, GTK_ALIGN_START);
1864
1865 gtk_widget_show (combo_box);
1866
1867 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box))))),
1868 combo_box_row_separator_func,
1869 NULL((void*)0),
1870 NULL((void*)0));
1871
1872 gtk_grid_attach_next_to (grid, combo_box, sibling,
1873 GTK_POS_RIGHT, 1, 1);
1874
1875 return GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box)))));
1876}
1877
1878static GtkComboBox*
1879attach_group_combo_box (GtkGrid *grid,
1880 GtkWidget *sibling,
1881 CajaFile *file)
1882{
1883 GtkComboBox *combo_box;
1884
1885 combo_box = attach_combo_box (grid, sibling, FALSE(0));
1886
1887 synch_groups_combo_box (combo_box, file);
1888
1889 /* Connect to signal to update menu when file changes. */
1890 g_signal_connect_object (file, "changed",
1891 G_CALLBACK (synch_groups_combo_box)((GCallback) (synch_groups_combo_box)),
1892 combo_box, G_CONNECT_SWAPPED);
1893 g_signal_connect_data (combo_box, "changed",
1894 G_CALLBACK (changed_group_callback)((GCallback) (changed_group_callback)),
1895 caja_file_ref (file),
1896 (GClosureNotify)caja_file_unref, 0);
1897
1898 return combo_box;
1899}
1900
1901static void
1902owner_change_callback (CajaFile *file,
1903 GFile *result_location,
1904 GError *error,
1905 FMPropertiesWindow *window)
1906{
1907 char *owner;
1908
1909 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_322
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_322 = 1; else _g_boolean_var_322 = 0; _g_boolean_var_322
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1909, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1910 g_assert (window->details->owner_change_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_323
; if (window->details->owner_change_file == file) _g_boolean_var_323
= 1; else _g_boolean_var_323 = 0; _g_boolean_var_323; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1910, ((const char*) (__func__)), "window->details->owner_change_file == file"
); } while (0)
;
1911
1912 owner = window->details->owner_change_owner;
1913 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_324
; if (owner != ((void*)0)) _g_boolean_var_324 = 1; else _g_boolean_var_324
= 0; _g_boolean_var_324; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1913, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1914
1915 /* Report the error if it's an error. */
1916 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
1917 fm_report_error_setting_owner (file, error, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1918
1919 caja_file_unref (file);
1920 g_free (owner);
1921
1922 window->details->owner_change_file = NULL((void*)0);
1923 window->details->owner_change_owner = NULL((void*)0);
1924 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1925}
1926
1927static void
1928cancel_owner_change_callback (FMPropertiesWindow *window)
1929{
1930 CajaFile *file;
1931 char *owner;
1932
1933 file = window->details->owner_change_file;
1934 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_325
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_325
= 1; else _g_boolean_var_325 = 0; _g_boolean_var_325; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1934, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1935
1936 owner = window->details->owner_change_owner;
1937 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_326
; if (owner != ((void*)0)) _g_boolean_var_326 = 1; else _g_boolean_var_326
= 0; _g_boolean_var_326; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1937, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1938
1939 caja_file_cancel (file, (CajaFileOperationCallback) owner_change_callback, window);
1940
1941 caja_file_unref (file);
1942 g_free (owner);
1943
1944 window->details->owner_change_file = NULL((void*)0);
1945 window->details->owner_change_owner = NULL((void*)0);
1946 g_object_unref (window);
1947}
1948
1949static gboolean
1950schedule_owner_change_timeout (FMPropertiesWindow *window)
1951{
1952 CajaFile *file;
1953 char *owner;
1954
1955 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_327
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_327 = 1; else _g_boolean_var_327 = 0; _g_boolean_var_327
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1955, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1956
1957 file = window->details->owner_change_file;
1958 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_328
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_328
= 1; else _g_boolean_var_328 = 0; _g_boolean_var_328; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1958, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1959
1960 owner = window->details->owner_change_owner;
1961 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_329
; if (owner != ((void*)0)) _g_boolean_var_329 = 1; else _g_boolean_var_329
= 0; _g_boolean_var_329; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1961, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1962
1963 eel_timed_wait_start
1964 ((EelCancelCallback) cancel_owner_change_callback,
1965 window,
1966 _("Cancel Owner Change?")dcgettext (((void*)0), "Cancel Owner Change?", 5),
1967 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1968
1969 caja_file_set_owner
1970 (file, owner,
1971 (CajaFileOperationCallback) owner_change_callback, window);
1972
1973 window->details->owner_change_timeout = 0;
1974 return FALSE(0);
1975}
1976
1977static void
1978schedule_owner_change (FMPropertiesWindow *window,
1979 CajaFile *file,
1980 const char *owner)
1981{
1982 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_330
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_330 = 1; else _g_boolean_var_330 = 0; _g_boolean_var_330
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1982, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1983 g_assert (window->details->owner_change_owner == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_331
; if (window->details->owner_change_owner == ((void*)0)
) _g_boolean_var_331 = 1; else _g_boolean_var_331 = 0; _g_boolean_var_331
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1983, ((const char*) (__func__)), "window->details->owner_change_owner == NULL"
); } while (0)
;
1984 g_assert (window->details->owner_change_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_332
; if (window->details->owner_change_file == ((void*)0))
_g_boolean_var_332 = 1; else _g_boolean_var_332 = 0; _g_boolean_var_332
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1984, ((const char*) (__func__)), "window->details->owner_change_file == NULL"
); } while (0)
;
1985 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_333
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_333
= 1; else _g_boolean_var_333 = 0; _g_boolean_var_333; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1985, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1986
1987 window->details->owner_change_file = caja_file_ref (file);
1988 window->details->owner_change_owner = g_strdup (owner)g_strdup_inline (owner);
1989 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) ((window))))))) (g_object_ref
) (((((GObject*) (void *) ((window)))))))
;
1990 window->details->owner_change_timeout =
1991 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1992 (GSourceFunc) schedule_owner_change_timeout,
1993 window);
1994}
1995
1996static void
1997unschedule_or_cancel_owner_change (FMPropertiesWindow *window)
1998{
1999 CajaFile *file;
2000 char *owner;
2001
2002 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_334
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_334 = 1; else _g_boolean_var_334 = 0; _g_boolean_var_334
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2002, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2003
2004 file = window->details->owner_change_file;
2005 owner = window->details->owner_change_owner;
2006
2007 g_assert ((file == NULL && owner == NULL) ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_335
; if ((file == ((void*)0) && owner == ((void*)0)) || (
file != ((void*)0) && owner != ((void*)0))) _g_boolean_var_335
= 1; else _g_boolean_var_335 = 0; _g_boolean_var_335; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2008, ((const char*) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
2008 (file != NULL && owner != NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_335
; if ((file == ((void*)0) && owner == ((void*)0)) || (
file != ((void*)0) && owner != ((void*)0))) _g_boolean_var_335
= 1; else _g_boolean_var_335 = 0; _g_boolean_var_335; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2008, ((const char*) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
;
2009
2010 if (file != NULL((void*)0)) {
2011 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_336
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_336
= 1; else _g_boolean_var_336 = 0; _g_boolean_var_336; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2011, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2012
2013 if (window->details->owner_change_timeout == 0) {
2014 caja_file_cancel (file,
2015 (CajaFileOperationCallback) owner_change_callback, window);
2016 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
2017 }
2018
2019 caja_file_unref (file);
2020 g_free (owner);
2021
2022 window->details->owner_change_file = NULL((void*)0);
2023 window->details->owner_change_owner = NULL((void*)0);
2024 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
2025 }
2026
2027 if (window->details->owner_change_timeout > 0) {
2028 g_assert (file != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_337
; if (file != ((void*)0)) _g_boolean_var_337 = 1; else _g_boolean_var_337
= 0; _g_boolean_var_337; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2028, ((const char*
) (__func__)), "file != NULL"); } while (0)
;
2029 g_source_remove (window->details->owner_change_timeout);
2030 window->details->owner_change_timeout = 0;
2031 }
2032}
2033
2034static void
2035changed_owner_callback (GtkComboBox *combo_box, CajaFile* file)
2036{
2037 char *owner_text;
2038 char **name_array;
2039 char *new_owner;
2040 char *cur_owner;
2041
2042 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_338
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2042, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2043 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_339
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_339
= 1; else _g_boolean_var_339 = 0; _g_boolean_var_339; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2043, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2044
2045 owner_text = combo_box_get_active_entry (combo_box, 0);
2046 if (! owner_text)
2047 return;
2048 name_array = g_strsplit (owner_text, " - ", 2);
2049 new_owner = name_array[0];
2050 g_free (owner_text);
2051 cur_owner = caja_file_get_owner_name (file);
2052
2053 if (strcmp (new_owner, cur_owner) != 0) {
2054 FMPropertiesWindow *window;
2055
2056 /* Try to change file owner. If this fails, complain to user. */
2057 window = FM_PROPERTIES_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (combo_box), GTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) ((gtk_widget_get_ancestor (
((((GtkWidget*) (void *) ((combo_box))))), (gtk_window_get_type
())))))))
;
2058
2059 unschedule_or_cancel_owner_change (window);
2060 schedule_owner_change (window, file, new_owner);
2061 }
2062 g_strfreev (name_array);
2063 g_free (cur_owner);
2064}
2065
2066static void
2067synch_user_menu (GtkComboBox *combo_box, CajaFile *file)
2068{
2069 GList *users;
2070 GList *node;
2071 GtkTreeModel *model;
2072 GtkListStore *store;
2073 GtkTreeIter iter;
2074 char *user_name;
2075 char *owner_name;
2076 int owner_index;
2077 char **name_array;
2078
2079 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_340
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_340
= 1; else _g_boolean_var_340 = 0; _g_boolean_var_340; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2079, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2080 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_341
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_341
= 1; else _g_boolean_var_341 = 0; _g_boolean_var_341; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2080, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2081
2082 if (caja_file_is_gone (file)) {
2083 return;
2084 }
2085
2086 users = caja_get_user_names ();
2087
2088 model = gtk_combo_box_get_model (combo_box);
2089 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
2090 g_assert (GTK_IS_LIST_STORE (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_342
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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_342
= 1; else _g_boolean_var_342 = 0; _g_boolean_var_342; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2090, ((const char*) (__func__)), "GTK_IS_LIST_STORE (model)"
); } while (0)
;
2091
2092 if (!tree_model_entries_equal (model, 1, users)) {
2093 int user_index;
2094
2095 /* Clear the contents of ComboBox in a wacky way because there
2096 * is no function to clear all items and also no function to obtain
2097 * the number of items in a combobox.
2098 */
2099 gtk_list_store_clear (store);
2100
2101 for (node = users, user_index = 0; node != NULL((void*)0); node = node->next, ++user_index) {
2102 char *combo_text;
2103
2104 user_name = (char *)node->data;
2105
2106 name_array = g_strsplit (user_name, "\n", 2);
2107 if (name_array[1] != NULL((void*)0)) {
2108 combo_text = g_strdup_printf ("%s - %s", name_array[0], name_array[1]);
2109 } else {
2110 combo_text = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2111 }
2112
2113 gtk_list_store_append (store, &iter);
2114 gtk_list_store_set (store, &iter,
2115 0, combo_text,
2116 1, user_name,
2117 -1);
2118
2119 g_strfreev (name_array);
2120 g_free (combo_text);
2121 }
2122 }
2123
2124 owner_name = caja_file_get_string_attribute (file, "owner");
2125 owner_index = tree_model_get_entry_index (model, 0, owner_name);
2126
2127 /* If owner wasn't in list, we prepend it (with a separator).
2128 * This can happen if the owner is an id with no matching
2129 * identifier in the passwords file.
2130 */
2131 if (owner_index < 0 && owner_name != NULL((void*)0)) {
2132 if (users != NULL((void*)0)) {
2133 /* add separator */
2134 gtk_list_store_prepend (store, &iter);
2135 gtk_list_store_set (store, &iter,
2136 0, "-",
2137 1, NULL((void*)0),
2138 -1);
2139 }
2140
2141 name_array = g_strsplit (owner_name, " - ", 2);
2142 if (name_array[1] != NULL((void*)0)) {
2143 user_name = g_strdup_printf ("%s\n%s", name_array[0], name_array[1]);
2144 } else {
2145 user_name = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2146 }
2147 owner_index = 0;
2148
2149 gtk_list_store_prepend (store, &iter);
2150 gtk_list_store_set (store, &iter,
2151 0, owner_name,
2152 1, user_name,
2153 -1);
2154
2155 g_free (user_name);
2156 g_strfreev (name_array);
2157 }
2158
2159 gtk_combo_box_set_active (combo_box, owner_index);
2160
2161 g_free (owner_name);
2162 g_list_free_full (users, g_free);
2163}
2164
2165static GtkComboBox*
2166attach_owner_combo_box (GtkGrid *grid,
2167 GtkWidget *sibling,
2168 CajaFile *file)
2169{
2170 GtkComboBox *combo_box;
2171
2172 combo_box = attach_combo_box (grid, sibling, TRUE(!(0)));
2173
2174 synch_user_menu (combo_box, file);
2175
2176 /* Connect to signal to update menu when file changes. */
2177 g_signal_connect_object (file, "changed",
2178 G_CALLBACK (synch_user_menu)((GCallback) (synch_user_menu)),
2179 combo_box, G_CONNECT_SWAPPED);
2180 g_signal_connect_data (combo_box, "changed",
2181 G_CALLBACK (changed_owner_callback)((GCallback) (changed_owner_callback)),
2182 caja_file_ref (file),
2183 (GClosureNotify)caja_file_unref, 0);
2184
2185 return combo_box;
2186}
2187
2188static gboolean
2189file_has_prefix (CajaFile *file,
2190 GList *prefix_candidates)
2191{
2192 GList *p;
2193 GFile *location, *candidate_location;
2194
2195 location = caja_file_get_location (file);
2196
2197 for (p = prefix_candidates; p != NULL((void*)0); p = p->next) {
2198 if (file == p->data) {
2199 continue;
2200 }
2201
2202 candidate_location = caja_file_get_location (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
2203 if (g_file_has_prefix (location, candidate_location)) {
2204 g_object_unref (location);
2205 g_object_unref (candidate_location);
2206 return TRUE(!(0));
2207 }
2208 g_object_unref (candidate_location);
2209 }
2210
2211 g_object_unref (location);
2212
2213 return FALSE(0);
2214}
2215
2216static void
2217directory_contents_value_field_update (FMPropertiesWindow *window)
2218{
2219 CajaRequestStatus file_status, status;
2220 char *text, *temp;
2221 guint directory_count;
2222 guint file_count;
2223 guint total_count;
2224 guint unreadable_directory_count;
2225 goffset total_size;
2226 goffset total_size_on_disk;
2227 gboolean used_two_lines;
2228 GList *l;
2229 guint file_unreadable;
2230 goffset file_size;
2231 goffset file_size_on_disk;
2232 CajaFile *file = NULL((void*)0);
2233
2234 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_343
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_343 = 1; else _g_boolean_var_343 = 0; _g_boolean_var_343
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2234, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2235
2236 status = CAJA_REQUEST_DONE;
2237 file_status = CAJA_REQUEST_NOT_STARTED;
2238 total_count = window->details->total_count;
2239 total_size = window->details->total_size;
2240 total_size_on_disk = window->details->total_size_on_disk;
2241 unreadable_directory_count = FALSE(0);
2242
2243 for (l = window->details->target_files; l; l = l->next) {
2244 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
2245
2246 if (file_has_prefix (file, window->details->target_files)) {
2247 /* don't count nested files twice */
2248 continue;
2249 }
2250
2251 if (caja_file_is_directory (file)) {
2252 file_status = caja_file_get_deep_counts (file,
2253 &directory_count,
2254 &file_count,
2255 &file_unreadable,
2256 &file_size,
2257 &file_size_on_disk,
2258 TRUE(!(0)));
2259 total_count += (file_count + directory_count);
2260 total_size += file_size;
2261 total_size_on_disk += file_size_on_disk;
2262
2263 if (file_unreadable) {
2264 unreadable_directory_count = TRUE(!(0));
2265 }
2266
2267 if (file_status != CAJA_REQUEST_DONE) {
2268 status = file_status;
2269 }
2270 } else {
2271 ++total_count;
2272 total_size += caja_file_get_size (file);
2273 total_size_on_disk += caja_file_get_size_on_disk (file);
2274 }
2275 }
2276
2277 /* If we've already displayed the total once, don't do another visible
2278 * count-up if the deep_count happens to get invalidated.
2279 * But still display the new total, since it might have changed.
2280 */
2281 if (window->details->deep_count_finished &&
2282 status != CAJA_REQUEST_DONE) {
2283 return;
2284 }
2285
2286 text = NULL((void*)0);
2287 used_two_lines = FALSE(0);
2288
2289 if (total_count == 0) {
2290 switch (status) {
2291 case CAJA_REQUEST_DONE:
2292 if (unreadable_directory_count == 0) {
2293 text = g_strdup (_("nothing"))g_strdup_inline (dcgettext (((void*)0), "nothing", 5));
2294 } else {
2295 text = g_strdup (_("unreadable"))g_strdup_inline (dcgettext (((void*)0), "unreadable", 5));
2296 }
2297
2298 break;
2299 default:
2300 text = g_strdup ("...")g_strdup_inline ("...");
2301 }
2302 } else {
2303 char *size_str;
2304 char *size_on_disk_str;
2305
2306 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
2307 size_str = g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
2308 size_on_disk_str = g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
2309 } else {
2310 size_str = g_format_size (total_size);
2311 size_on_disk_str = g_format_size (total_size_on_disk);
2312 }
2313
2314 text = g_strdup_printf (ngettext("%'d item, with size %s (%s on disk)",dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
2315 "%'d items, totalling %s (%s on disk)",dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
2316 total_count)dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
,
2317 total_count, size_str, size_on_disk_str);
2318 g_free (size_str);
2319 g_free (size_on_disk_str);
2320
2321 if (unreadable_directory_count != 0) {
2322 temp = text;
2323 text = g_strconcat (temp, "\n",
2324 _("(some contents unreadable)")dcgettext (((void*)0), "(some contents unreadable)", 5),
2325 NULL((void*)0));
2326 g_free (temp);
2327 used_two_lines = TRUE(!(0));
2328 }
2329 }
2330
2331 gtk_label_set_text (window->details->directory_contents_value_field,
2332 text);
2333 g_free (text);
2334
2335 /* Also set the title field here, with a trailing carriage return &
2336 * space if the value field has two lines. This is a hack to get the
2337 * "Contents:" title to line up with the first line of the
2338 * 2-line value. Maybe there's a better way to do this, but I
2339 * couldn't think of one.
2340 */
2341 text = g_strdup (_("Contents:"))g_strdup_inline (dcgettext (((void*)0), "Contents:", 5));
2342 if (used_two_lines) {
2343 temp = text;
2344 text = g_strconcat (temp, "\n ", NULL((void*)0));
2345 g_free (temp);
2346 }
2347 gtk_label_set_text (window->details->directory_contents_title_field,
2348 text);
2349 g_free (text);
2350
2351 if (status == CAJA_REQUEST_DONE) {
2352 window->details->deep_count_finished = TRUE(!(0));
2353 }
2354}
2355
2356static gboolean
2357update_directory_contents_callback (gpointer data)
2358{
2359 FMPropertiesWindow *window;
2360
2361 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2362
2363 window->details->update_directory_contents_timeout_id = 0;
2364 directory_contents_value_field_update (window);
2365
2366 return FALSE(0);
2367}
2368
2369static void
2370schedule_directory_contents_update (FMPropertiesWindow *window)
2371{
2372 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_344
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_344 = 1; else _g_boolean_var_344 = 0; _g_boolean_var_344
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2372, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2373
2374 if (window->details->update_directory_contents_timeout_id == 0) {
2375 window->details->update_directory_contents_timeout_id
2376 = g_timeout_add (DIRECTORY_CONTENTS_UPDATE_INTERVAL200,
2377 update_directory_contents_callback,
2378 window);
2379 }
2380}
2381
2382static GtkLabel *
2383attach_directory_contents_value_field (FMPropertiesWindow *window,
2384 GtkGrid *grid,
2385 GtkWidget *sibling)
2386{
2387 GtkLabel *value_field;
2388 GList *l;
2389 CajaFile *file = NULL((void*)0);
2390
2391 value_field = attach_value_label (grid, sibling, "");
2392
2393 g_assert (window->details->directory_contents_value_field == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_345
; if (window->details->directory_contents_value_field ==
((void*)0)) _g_boolean_var_345 = 1; else _g_boolean_var_345 =
0; _g_boolean_var_345; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2393, ((const char*
) (__func__)), "window->details->directory_contents_value_field == NULL"
); } while (0)
;
2394 window->details->directory_contents_value_field = value_field;
2395
2396 gtk_label_set_line_wrap (value_field, TRUE(!(0)));
2397
2398 /* Fill in the initial value. */
2399 directory_contents_value_field_update (window);
2400
2401 for (l = window->details->target_files; l; l = l->next) {
2402 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
2403 caja_file_recompute_deep_counts (file);
2404
2405 g_signal_connect_object (file,
2406 "updated_deep_count_in_progress",
2407 G_CALLBACK (schedule_directory_contents_update)((GCallback) (schedule_directory_contents_update)),
2408 window, G_CONNECT_SWAPPED);
2409 }
2410
2411 return value_field;
2412}
2413
2414static GtkLabel *
2415attach_title_field (GtkGrid *grid,
2416 const char *title)
2417{
2418 return attach_label (grid, NULL((void*)0), title, FALSE(0), FALSE(0), TRUE(!(0)));
2419}
2420
2421
2422
2423#define INCONSISTENT_STATE_STRING"\xE2\x80\x92" \
2424 "\xE2\x80\x92"
2425
2426static void
2427append_title_value_pair (FMPropertiesWindow *window,
2428 GtkGrid *grid,
2429 const char *title,
2430 const char *file_attribute_name,
2431 const char *inconsistent_state,
2432 gboolean show_original)
2433{
2434 GtkLabel *title_label;
2435 GtkWidget *value;
2436
2437 title_label = attach_title_field (grid, title);
2438 value = attach_value_field (window, grid, GTK_WIDGET (title_label)((((GtkWidget*) (void *) ((title_label))))),
2439 file_attribute_name,
2440 inconsistent_state,
2441 show_original);
2442 gtk_label_set_mnemonic_widget (title_label, value);
2443}
2444
2445static void
2446append_title_and_ellipsizing_value (FMPropertiesWindow *window,
2447 GtkGrid *grid,
2448 const char *title,
2449 const char *file_attribute_name,
2450 const char *inconsistent_state,
2451 gboolean show_original)
2452{
2453 GtkLabel *title_label;
2454 GtkWidget *value;
2455
2456 title_label = attach_title_field (grid, title);
2457 value = attach_ellipsizing_value_field (window, grid,
2458 GTK_WIDGET (title_label)((((GtkWidget*) (void *) ((title_label))))),
2459 file_attribute_name,
2460 inconsistent_state,
2461 show_original);
2462 gtk_label_set_mnemonic_widget (title_label, value);
2463}
2464
2465static void
2466append_directory_contents_fields (FMPropertiesWindow *window,
2467 GtkGrid *grid)
2468{
2469 GtkLabel *title_field, *value_field;
2470 title_field = attach_title_field (grid, "");
2471 window->details->directory_contents_title_field = title_field;
2472 gtk_label_set_line_wrap (title_field, TRUE(!(0)));
2473
2474 value_field = attach_directory_contents_value_field
2475 (window, grid, GTK_WIDGET (title_field)((((GtkWidget*) (void *) ((title_field))))));
2476
2477 gtk_label_set_mnemonic_widget (title_field, GTK_WIDGET(value_field)((((GtkWidget*) (void *) ((value_field))))));
2478}
2479
2480static GtkWidget *
2481create_page_with_hbox (GtkNotebook *notebook,
2482 const char *title)
2483{
2484 GtkWidget *hbox;
2485
2486 g_assert (GTK_IS_NOTEBOOK (notebook))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_346
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((gtk_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; }))))) _g_boolean_var_346
= 1; else _g_boolean_var_346 = 0; _g_boolean_var_346; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2486, ((const char*) (__func__)), "GTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2487 g_assert (title != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_347
; if (title != ((void*)0)) _g_boolean_var_347 = 1; else _g_boolean_var_347
= 0; _g_boolean_var_347; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2487, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2488
2489 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2490 gtk_widget_show (hbox);
2491 gtk_container_set_border_width (GTK_CONTAINER (hbox)((((GtkContainer*) (void *) ((hbox))))), 12);
2492 gtk_box_set_spacing (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), 12);
2493 gtk_notebook_append_page (notebook, hbox, gtk_label_new (title));
2494
2495 return hbox;
2496}
2497
2498static GtkWidget *
2499create_page_with_vbox (GtkNotebook *notebook,
2500 const char *title)
2501{
2502 GtkWidget *vbox;
2503
2504 g_assert (GTK_IS_NOTEBOOK (notebook))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_348
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((gtk_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; }))))) _g_boolean_var_348
= 1; else _g_boolean_var_348 = 0; _g_boolean_var_348; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2504, ((const char*) (__func__)), "GTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2505 g_assert (title != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_349
; if (title != ((void*)0)) _g_boolean_var_349 = 1; else _g_boolean_var_349
= 0; _g_boolean_var_349; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2505, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2506
2507 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2508 gtk_widget_show (vbox);
2509
2510 gtk_container_set_border_width (GTK_CONTAINER (vbox)((((GtkContainer*) (void *) ((vbox))))), 12);
2511 gtk_notebook_append_page (notebook, vbox, gtk_label_new (title));
2512
2513 return vbox;
2514}
2515
2516static GtkWidget *
2517append_blank_row (GtkGrid *grid)
2518{
2519 return GTK_WIDGET (attach_title_field (grid, ""))((((GtkWidget*) (void *) ((attach_title_field (grid, ""))))));
2520}
2521
2522static void
2523append_blank_slim_row (GtkGrid *grid)
2524{
2525 GtkWidget *w;
2526 PangoAttribute *attribute;
2527 PangoAttrList *attr_list;
2528
2529 attr_list = pango_attr_list_new ();
2530 attribute = pango_attr_scale_new (0.30);
2531 pango_attr_list_insert (attr_list, attribute);
2532
2533 w = gtk_label_new (NULL((void*)0));
2534 gtk_label_set_attributes (GTK_LABEL (w)((((GtkLabel*) (void *) ((w))))), attr_list);
2535 gtk_widget_show (w);
2536
2537 pango_attr_list_unref (attr_list);
2538
2539 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), w);
2540}
2541
2542static GtkWidget *
2543create_grid_with_standard_properties (void)
2544{
2545 GtkWidget *grid;
2546
2547 grid = gtk_grid_new ();
2548 gtk_container_set_border_width (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), 6);
2549 gtk_grid_set_row_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), ROW_PAD6);
2550 gtk_grid_set_column_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), 12);
2551 gtk_orientable_set_orientation (GTK_ORIENTABLE (grid)((((GtkOrientable*) (void *) ((grid))))), GTK_ORIENTATION_VERTICAL);
2552 gtk_widget_show (grid);
2553
2554 return grid;
2555}
2556
2557static gboolean
2558is_merged_trash_directory (CajaFile *file)
2559{
2560 char *file_uri;
2561 gboolean result;
2562
2563 file_uri = caja_file_get_uri (file);
2564 result = strcmp (file_uri, "trash:///") == 0;
2565 g_free (file_uri);
2566
2567 return result;
2568}
2569
2570static gboolean
2571is_computer_directory (CajaFile *file)
2572{
2573 char *file_uri;
2574 gboolean result;
2575
2576 file_uri = caja_file_get_uri (file);
2577 result = strcmp (file_uri, "computer:///") == 0;
2578 g_free (file_uri);
2579
2580 return result;
2581}
2582
2583static gboolean
2584is_network_directory (CajaFile *file)
2585{
2586 char *file_uri;
2587 gboolean result;
2588
2589 file_uri = caja_file_get_uri (file);
2590 result = strcmp (file_uri, "network:///") == 0;
2591 g_free (file_uri);
2592
2593 return result;
2594}
2595
2596static gboolean
2597is_burn_directory (CajaFile *file)
2598{
2599 char *file_uri;
2600 gboolean result;
2601
2602 file_uri = caja_file_get_uri (file);
2603 result = strcmp (file_uri, "burn:///") == 0;
2604 g_free (file_uri);
2605
2606 return result;
2607}
2608
2609static gboolean
2610should_show_custom_icon_buttons (FMPropertiesWindow *window)
2611{
2612 if (is_multi_file_window (window)) {
2613 return FALSE(0);
2614 }
2615
2616 return TRUE(!(0));
2617}
2618
2619static gboolean
2620should_show_file_type (FMPropertiesWindow *window)
2621{
2622 if (!is_multi_file_window (window)
2623 && (is_merged_trash_directory (get_target_file (window)) ||
2624 is_computer_directory (get_target_file (window)) ||
2625 is_network_directory (get_target_file (window)) ||
2626 is_burn_directory (get_target_file (window)))) {
2627 return FALSE(0);
2628 }
2629
2630
2631 return TRUE(!(0));
2632}
2633
2634static gboolean
2635should_show_location_info (FMPropertiesWindow *window)
2636{
2637 if (!is_multi_file_window (window)
2638 && (is_merged_trash_directory (get_target_file (window)) ||
2639 is_computer_directory (get_target_file (window)) ||
2640 is_network_directory (get_target_file (window)) ||
2641 is_burn_directory (get_target_file (window)))) {
2642 return FALSE(0);
2643 }
2644
2645 return TRUE(!(0));
2646}
2647
2648static gboolean
2649should_show_accessed_date (FMPropertiesWindow *window)
2650{
2651 /* Accessed date for directory seems useless. If we some
2652 * day decide that it is useful, we should separately
2653 * consider whether it's useful for "trash:".
2654 */
2655 if (file_list_all_directories (window->details->target_files)
2656 || is_multi_file_window (window))
2657 {
2658 return FALSE(0);
2659 }
2660
2661 return TRUE(!(0));
2662}
2663
2664static gboolean
2665should_show_modified_date (FMPropertiesWindow *window)
2666{
2667 CajaFile *file;
2668
2669 if (is_multi_file_window (window))
2670 return FALSE(0);
2671
2672 file = get_original_file (window);
2673 if ((file != NULL((void*)0)) && caja_file_can_unmount (file))
2674 return FALSE(0);
2675
2676 return TRUE(!(0));
2677}
2678
2679static gboolean
2680should_show_link_target (FMPropertiesWindow *window)
2681{
2682 if (!is_multi_file_window (window)
2683 && caja_file_is_symbolic_link (get_target_file (window))) {
2684 return TRUE(!(0));
2685 }
2686
2687 return FALSE(0);
2688}
2689
2690static gboolean
2691should_show_free_space (FMPropertiesWindow *window)
2692{
2693
2694 if (!is_multi_file_window (window)
2695 && (is_merged_trash_directory (get_target_file (window)) ||
2696 is_computer_directory (get_target_file (window)) ||
2697 is_network_directory (get_target_file (window)) ||
2698 is_burn_directory (get_target_file (window)))) {
2699 return FALSE(0);
2700 }
2701
2702 if (file_list_all_directories (window->details->target_files)) {
2703 return TRUE(!(0));
2704 }
2705
2706 return FALSE(0);
2707}
2708
2709static gboolean
2710should_show_volume_usage (FMPropertiesWindow *window)
2711{
2712 CajaFile *file;
2713 gboolean success = FALSE(0);
2714
2715 if (is_multi_file_window (window)) {
2716 return FALSE(0);
2717 }
2718
2719 file = get_original_file (window);
2720
2721 if (file == NULL((void*)0)) {
2722 return FALSE(0);
2723 }
2724
2725 if (caja_file_can_unmount (file)) {
2726 return TRUE(!(0));
2727 }
2728
2729#ifdef TODO_GIO
2730 /* Look at is_mountpoint for activation uri */
2731#endif
2732 return success;
2733}
2734
2735static void
2736paint_used_legend (GtkWidget *widget,
2737 cairo_t *cr,
2738 gpointer data)
2739{
2740 FMPropertiesWindow *window;
2741 gint width, height;
2742 GtkAllocation allocation;
2743
2744 gtk_widget_get_allocation (widget, &allocation);
2745
2746 width = allocation.width;
2747 height = allocation.height;
2748
2749 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2750
2751 cairo_rectangle (cr,
2752 2,
2753 2,
2754 width - 4,
2755 height - 4);
2756
2757 gdk_cairo_set_source_rgba (cr, &window->details->used_color);
2758 cairo_fill_preserve (cr);
2759
2760 gdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2761 cairo_stroke (cr);
2762}
2763
2764static void
2765paint_free_legend (GtkWidget *widget,
2766 cairo_t *cr, gpointer data)
2767{
2768 FMPropertiesWindow *window;
2769 gint width, height;
2770 GtkAllocation allocation;
2771
2772 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2773 gtk_widget_get_allocation (widget, &allocation);
2774
2775 width = allocation.width;
2776 height = allocation.height;
2777
2778 cairo_rectangle (cr,
2779 2,
2780 2,
2781 width - 4,
2782 height - 4);
2783
2784 gdk_cairo_set_source_rgba (cr, &window->details->free_color);
2785 cairo_fill_preserve(cr);
2786
2787 gdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2788 cairo_stroke (cr);
2789}
2790
2791static void
2792paint_pie_chart (GtkWidget *widget,
2793 cairo_t *cr,
2794 gpointer data)
2795{
2796
2797 FMPropertiesWindow *window;
2798 gint width, height;
2799 double free, used;
2800 double angle1, angle2, split, xc, yc, radius;
2801 GtkAllocation allocation;
2802
2803 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2804 gtk_widget_get_allocation (widget, &allocation);
2805
2806 width = allocation.width;
2807 height = allocation.height;
2808
2809
2810 free = (double)window->details->volume_free / (double)window->details->volume_capacity;
2811 used = 1.0 - free;
2812
2813 angle1 = free * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2814 angle2 = used * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2815 split = (2 * G_PI3.1415926535897932384626433832795028841971693993751 - angle1) * .5;
2816 xc = width / 2;
2817 yc = height / 2;
2818
2819 if (width < height) {
2820 radius = width / 2 - 8;
2821 } else {
2822 radius = height / 2 - 8;
2823 }
2824
2825 if (angle1 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle1 != 0) {
2826 angle1 = angle1 + split;
2827 }
2828
2829 if (angle2 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle2 != 0) {
2830 angle2 = angle2 - split;
2831 }
2832
2833 if (used > 0) {
2834 if (free != 0) {
2835 cairo_move_to (cr,xc,yc);
2836 }
2837
2838 cairo_arc (cr, xc, yc, radius, angle1, angle2);
2839
2840 if (free != 0) {
2841 cairo_line_to (cr,xc,yc);
2842 }
2843
2844 gdk_cairo_set_source_rgba (cr, &window->details->used_color);
2845 cairo_fill_preserve (cr);
2846
2847 gdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2848
2849 cairo_stroke (cr);
2850 }
2851
2852 if (free > 0) {
2853 if (used != 0) {
2854 cairo_move_to (cr,xc,yc);
2855 }
2856
2857 cairo_arc_negative (cr, xc, yc, radius, angle1, angle2);
2858
2859 if (used != 0) {
2860 cairo_line_to (cr,xc,yc);
2861 }
2862
2863
2864 gdk_cairo_set_source_rgba (cr, &window->details->free_color);
2865 cairo_fill_preserve(cr);
2866
2867 gdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2868
2869 cairo_stroke (cr);
2870 }
2871}
2872
2873
2874/* Copied from gtk/gtkstyle.c */
2875
2876static void
2877rgb_to_hls (gdouble *r,
2878 gdouble *g,
2879 gdouble *b)
2880{
2881 gdouble min;
2882 gdouble max;
2883 gdouble red;
2884 gdouble green;
2885 gdouble blue;
2886 gdouble h, l, s;
2887 gdouble delta;
2888
2889 red = *r;
2890 green = *g;
2891 blue = *b;
2892
2893 if (red > green)
2894 {
2895 if (red > blue)
2896 max = red;
2897 else
2898 max = blue;
2899
2900 if (green < blue)
2901 min = green;
2902 else
2903 min = blue;
2904 }
2905 else
2906 {
2907 if (green > blue)
2908 max = green;
2909 else
2910 max = blue;
2911
2912 if (red < blue)
2913 min = red;
2914 else
2915 min = blue;
2916 }
2917
2918 l = (max + min) / 2;
2919 s = 0;
2920 h = 0;
2921
2922 if (max != min)
2923 {
2924 if (l <= 0.5)
2925 s = (max - min) / (max + min);
2926 else
2927 s = (max - min) / (2 - max - min);
2928
2929 delta = max -min;
2930 if (red == max)
2931 h = (green - blue) / delta;
2932 else if (green == max)
2933 h = 2 + (blue - red) / delta;
2934 else if (blue == max)
2935 h = 4 + (red - green) / delta;
2936
2937 h *= 60;
2938 if (h < 0.0)
2939 h += 360;
2940 }
2941
2942 *r = h;
2943 *g = l;
2944 *b = s;
2945}
2946
2947static void
2948hls_to_rgb (gdouble *h,
2949 gdouble *l,
2950 gdouble *s)
2951{
2952 gdouble hue;
2953 gdouble lightness;
2954 gdouble saturation;
2955 gdouble m1, m2;
2956 gdouble r, g, b;
2957
2958 lightness = *l;
2959 saturation = *s;
2960
2961 if (lightness <= 0.5)
2962 m2 = lightness * (1 + saturation);
2963 else
2964 m2 = lightness + saturation - lightness * saturation;
2965 m1 = 2 * lightness - m2;
2966
2967 if (saturation == 0)
2968 {
2969 *h = lightness;
2970 *l = lightness;
2971 *s = lightness;
2972 }
2973 else
2974 {
2975 hue = *h + 120;
2976 while (hue > 360)
2977 hue -= 360;
2978 while (hue < 0)
2979 hue += 360;
2980
2981 if (hue < 60)
2982 r = m1 + (m2 - m1) * hue / 60;
2983 else if (hue < 180)
2984 r = m2;
2985 else if (hue < 240)
2986 r = m1 + (m2 - m1) * (240 - hue) / 60;
2987 else
2988 r = m1;
2989
2990 hue = *h;
2991 while (hue > 360)
2992 hue -= 360;
2993 while (hue < 0)
2994 hue += 360;
2995
2996 if (hue < 60)
2997 g = m1 + (m2 - m1) * hue / 60;
2998 else if (hue < 180)
2999 g = m2;
3000 else if (hue < 240)
3001 g = m1 + (m2 - m1) * (240 - hue) / 60;
3002 else
3003 g = m1;
3004
3005 hue = *h - 120;
3006 while (hue > 360)
3007 hue -= 360;
3008 while (hue < 0)
3009 hue += 360;
3010
3011 if (hue < 60)
3012 b = m1 + (m2 - m1) * hue / 60;
3013 else if (hue < 180)
3014 b = m2;
3015 else if (hue < 240)
3016 b = m1 + (m2 - m1) * (240 - hue) / 60;
3017 else
3018 b = m1;
3019
3020 *h = r;
3021 *l = g;
3022 *s = b;
3023 }
3024}
3025static void
3026_pie_style_shade (GdkRGBA *a,
3027 GdkRGBA *b,
3028 gdouble k)
3029{
3030 gdouble red;
3031 gdouble green;
3032 gdouble blue;
3033
3034 red = a->red;
3035 green = a->green;
3036 blue = a->blue;
3037
3038 rgb_to_hls (&red, &green, &blue);
3039
3040 green *= k;
3041 if (green > 1.0)
3042 green = 1.0;
3043 else if (green < 0.0)
3044 green = 0.0;
3045
3046 blue *= k;
3047 if (blue > 1.0)
3048 blue = 1.0;
3049 else if (blue < 0.0)
3050 blue = 0.0;
3051
3052 hls_to_rgb (&red, &green, &blue);
3053
3054 b->red = red;
3055 b->green = green;
3056 b->blue = blue;
3057 b->alpha = a->alpha;
3058}
3059
3060
3061static GtkWidget*
3062create_pie_widget (FMPropertiesWindow *window)
3063{
3064 CajaFile *file;
3065 GtkGrid *grid;
3066 GtkStyleContext *style;
3067
3068 GtkWidget *pie_canvas;
3069 GtkWidget *used_canvas;
3070 GtkWidget *used_label;
3071 GtkWidget *free_canvas;
3072 GtkWidget *free_label;
3073 GtkWidget *capacity_label;
3074 GtkWidget *fstype_label;
3075 gchar *capacity;
3076 gchar *used;
3077 gchar *free;
3078 gchar *uri;
3079 gchar *concat;
3080 GFile *location;
3081 GFileInfo *info;
3082
3083 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
3084 capacity = g_format_size_full(window->details->volume_capacity, G_FORMAT_SIZE_IEC_UNITS);
3085 free = g_format_size_full(window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3086 used = g_format_size_full(window->details->volume_capacity - window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3087 }
3088 else {
3089 capacity = g_format_size(window->details->volume_capacity);
3090 free = g_format_size(window->details->volume_free);
3091 used = g_format_size(window->details->volume_capacity - window->details->volume_free);
3092 }
3093
3094 file = get_original_file (window);
3095
3096 uri = caja_file_get_activation_uri (file);
3097
3098 grid = GTK_GRID (gtk_grid_new ())((((GtkGrid*) (void *) ((gtk_grid_new ())))));
3099 gtk_container_set_border_width (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), 5);
3100 gtk_grid_set_column_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), 5);
3101 style = gtk_widget_get_style_context (GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid))))));
3102
3103 if (!gtk_style_context_lookup_color (style, "chart_rgba_1", &window->details->used_color)) {
3104
3105 window->details->used_color.red = USED_FILL_R0.988235294;
3106 window->details->used_color.green = USED_FILL_G0.91372549;
3107 window->details->used_color.blue = USED_FILL_B0.309803922;
3108 window->details->used_color.alpha = 1;
3109
3110 }
3111
3112
3113 if (!gtk_style_context_lookup_color (style, "chart_rgba_2", &window->details->free_color)) {
3114 window->details->free_color.red = FREE_FILL_R0.447058824;
3115 window->details->free_color.green = FREE_FILL_G0.623529412;
3116 window->details->free_color.blue = FREE_FILL_B0.811764706;
3117 window->details->free_color.alpha = 1;
3118
3119 }
3120
3121 _pie_style_shade (&window->details->used_color, &window->details->used_stroke_color, 0.7);
3122 _pie_style_shade (&window->details->free_color, &window->details->free_stroke_color, 0.7);
3123
3124 pie_canvas = gtk_drawing_area_new ();
3125 gtk_widget_set_size_request (pie_canvas, 200, 200);
3126
3127 used_canvas = gtk_drawing_area_new ();
3128
3129 gtk_widget_set_valign (used_canvas, GTK_ALIGN_CENTER);
3130 gtk_widget_set_halign (used_canvas, GTK_ALIGN_CENTER);
3131
3132 gtk_widget_set_size_request (used_canvas, 20, 20);
3133 /* Translators: "used" refers to the capacity of the filesystem */
3134 concat = g_strconcat (used, " ", _("used")dcgettext (((void*)0), "used", 5), NULL((void*)0));
3135 used_label = gtk_label_new (concat);
3136 g_free (concat);
3137
3138 free_canvas = gtk_drawing_area_new ();
3139
3140 gtk_widget_set_valign (free_canvas, GTK_ALIGN_CENTER);
3141 gtk_widget_set_halign (free_canvas, GTK_ALIGN_CENTER);
3142
3143 gtk_widget_set_size_request (free_canvas, 20, 20);
3144 /* Translators: "free" refers to the capacity of the filesystem */
3145 concat = g_strconcat (free, " ", _("free")dcgettext (((void*)0), "free", 5), NULL((void*)0));
3146 free_label = gtk_label_new (concat);
3147 g_free (concat);
3148
3149 concat = g_strconcat (_("Total capacity:")dcgettext (((void*)0), "Total capacity:", 5), " ", capacity, NULL((void*)0));
3150 capacity_label = gtk_label_new (concat);
3151 g_free (concat);
3152 fstype_label = gtk_label_new (NULL((void*)0));
3153
3154 location = g_file_new_for_uri (uri);
3155 info = g_file_query_filesystem_info (location, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3156 NULL((void*)0), NULL((void*)0));
3157 if (info) {
3158 const char *fs_type;
3159
3160 fs_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type");
3161
3162 if (fs_type != NULL((void*)0)) {
3163 concat = g_strconcat (_("Filesystem type:")dcgettext (((void*)0), "Filesystem type:", 5), " ", fs_type, NULL((void*)0));
3164 gtk_label_set_text (GTK_LABEL (fstype_label)((((GtkLabel*) (void *) ((fstype_label))))), concat);
3165 g_free (concat);
3166 }
3167
3168 g_object_unref (info);
3169 }
3170 g_object_unref (location);
3171
3172 g_free (uri);
3173 g_free (capacity);
3174 g_free (used);
3175 g_free (free);
3176
3177 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), pie_canvas,
3178 "height", 4,
3179 NULL((void*)0));
3180 gtk_grid_attach_next_to (grid, used_canvas, pie_canvas,
3181 GTK_POS_RIGHT, 1, 1);
3182 gtk_grid_attach_next_to (grid, used_label, used_canvas,
3183 GTK_POS_RIGHT, 1, 1);
3184
3185 gtk_grid_attach_next_to (grid, free_canvas, used_canvas,
3186 GTK_POS_BOTTOM, 1, 1);
3187 gtk_grid_attach_next_to (grid, free_label, free_canvas,
3188 GTK_POS_RIGHT, 1, 1);
3189
3190 gtk_grid_attach_next_to (grid, capacity_label, free_canvas,
3191 GTK_POS_BOTTOM, 2, 1);
3192 gtk_grid_attach_next_to (grid, fstype_label, capacity_label,
3193 GTK_POS_BOTTOM, 2, 1);
3194
3195 g_signal_connect (pie_canvas, "draw",g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
3196 G_CALLBACK (paint_pie_chart), window)g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
;
3197 g_signal_connect (used_canvas, "draw",g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
3198 G_CALLBACK (paint_used_legend), window)g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3199 g_signal_connect (free_canvas, "draw",g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
3200 G_CALLBACK (paint_free_legend), window)g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3201
3202 return GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid)))));
3203
3204}
3205
3206static GtkWidget*
3207create_volume_usage_widget (FMPropertiesWindow *window)
3208{
3209 GtkWidget *piewidget;
3210 gchar *uri;
3211 CajaFile *file;
3212 GFile *location;
3213 GFileInfo *info;
3214
3215 file = get_original_file (window);
3216
3217 uri = caja_file_get_activation_uri (file);
3218
3219 location = g_file_new_for_uri (uri);
3220 info = g_file_query_filesystem_info (location, "filesystem::*", NULL((void*)0), NULL((void*)0));
3221
3222 if (info) {
3223 window->details->volume_capacity = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE"filesystem::size");
3224 window->details->volume_free = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
3225
3226 g_object_unref (info);
3227 } else {
3228 window->details->volume_capacity = 0;
3229 window->details->volume_free = 0;
3230 }
3231
3232 g_object_unref (location);
3233
3234 piewidget = create_pie_widget (window);
3235
3236 gtk_widget_show_all (piewidget);
3237
3238 return piewidget;
3239}
3240
3241static void
3242create_basic_page (FMPropertiesWindow *window)
3243{
3244 GtkGrid *grid;
3245 GtkWidget *icon_pixmap_widget;
3246 GtkWidget *hbox, *vbox;
3247
3248 hbox = create_page_with_hbox (window->details->notebook, _("Basic")dcgettext (((void*)0), "Basic", 5));
3249
3250 /* Icon pixmap */
3251
3252 icon_pixmap_widget = create_image_widget (
3253 window, should_show_custom_icon_buttons (window));
3254
3255 gtk_widget_set_halign (icon_pixmap_widget, GTK_ALIGN_END);
3256 gtk_widget_set_valign (icon_pixmap_widget, GTK_ALIGN_START);
3257 gtk_widget_show (icon_pixmap_widget);
3258
3259 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), icon_pixmap_widget, FALSE(0), FALSE(0), 0);
3260
3261 window->details->icon_chooser = NULL((void*)0);
3262
3263 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3264
3265 gtk_widget_show (vbox);
3266 gtk_container_add (GTK_CONTAINER (hbox)((((GtkContainer*) (void *) ((hbox))))), vbox);
3267
3268 grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
3269 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid))))), FALSE(0), FALSE(0), 0);
3270 window->details->basic_grid = grid;
3271
3272 /* Name label. The text will be determined in update_name_field */
3273 window->details->name_label = attach_title_field (grid, NULL((void*)0));
3274
3275 /* Name field */
3276 window->details->name_field = NULL((void*)0);
3277 update_name_field (window);
3278
3279 /* Start with name field selected, if it's an entry. */
3280 if (CAJA_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (caja_entry_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; }))))
) {
3281 caja_entry_select_all (CAJA_ENTRY (window->details->name_field)((((CajaEntry*) (void *) ((window->details->name_field)
))))
);
3282 gtk_widget_grab_focus (GTK_WIDGET (window->details->name_field)((((GtkWidget*) (void *) ((window->details->name_field)
))))
);
3283 }
3284
3285 if (fm_ditem_page_should_show (window->details->target_files)) {
3286 GtkSizeGroup *label_size_group;
3287 GtkWidget *box;
3288
3289 label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3290 gtk_size_group_add_widget (label_size_group,
3291 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
);
3292 box = fm_ditem_page_make_box (label_size_group,
3293 window->details->target_files);
3294
3295 gtk_grid_attach_next_to (window->details->basic_grid, box,
3296 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
,
3297 GTK_POS_BOTTOM, 2, 1);
3298 }
3299
3300 if (should_show_file_type (window)) {
3301 append_title_value_pair (window,
3302 grid, _("Type:")dcgettext (((void*)0), "Type:", 5),
3303 "type",
3304 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3305 FALSE(0));
3306 }
3307
3308 if (should_show_link_target (window)) {
3309 append_title_and_ellipsizing_value (window, grid,
3310 _("Link target:")dcgettext (((void*)0), "Link target:", 5),
3311 "link_target",
3312 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3313 FALSE(0));
3314 }
3315
3316 if (is_multi_file_window (window) ||
3317 caja_file_is_directory (get_target_file (window))) {
3318 append_directory_contents_fields (window, grid);
3319 } else {
3320 append_title_value_pair (window, grid, _("Size:")dcgettext (((void*)0), "Size:", 5),
3321 "size_detail",
3322 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3323 FALSE(0));
3324 append_title_value_pair (window, grid, _("Size on Disk:")dcgettext (((void*)0), "Size on Disk:", 5),
3325 "size_on_disk_detail",
3326 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3327 FALSE(0));
3328 }
3329
3330 append_blank_row (grid);
3331
3332 if (should_show_location_info (window)) {
3333 append_title_and_ellipsizing_value (window, grid, _("Location:")dcgettext (((void*)0), "Location:", 5),
3334 "where",
3335 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3336 TRUE(!(0)));
3337
3338 append_title_and_ellipsizing_value (window, grid,
3339 _("Volume:")dcgettext (((void*)0), "Volume:", 5),
3340 "volume",
3341 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3342 FALSE(0));
3343 }
3344
3345 if (should_show_accessed_date (window)
3346 || should_show_modified_date (window))
3347 {
3348 append_blank_row (grid);
3349 }
3350
3351 if (should_show_accessed_date (window))
3352 {
3353 append_title_value_pair (window, grid, _("Accessed:")dcgettext (((void*)0), "Accessed:", 5),
3354 "date_accessed",
3355 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3356 FALSE(0));
3357 }
3358
3359 if (should_show_modified_date (window))
3360 {
3361 append_title_value_pair (window, grid, _("Modified:")dcgettext (((void*)0), "Modified:", 5),
3362 "date_modified",
3363 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3364 FALSE(0));
3365 append_title_value_pair (window, grid, _("Created:")dcgettext (((void*)0), "Created:", 5),
3366 "date_created",
3367 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3368 FALSE(0));
3369 }
3370
3371 if (should_show_free_space (window)) {
3372 append_blank_row (grid);
3373
3374 append_title_value_pair (window, grid, _("Free space:")dcgettext (((void*)0), "Free space:", 5),
3375 "free_space",
3376 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3377 FALSE(0));
3378 }
3379
3380 if (should_show_volume_usage (window)) {
3381 GtkWidget *volume_usage;
3382
3383 volume_usage = create_volume_usage_widget (window);
3384 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), volume_usage,
3385 "width", 2,
3386 NULL((void*)0));
3387 }
3388}
3389
3390static GHashTable *
3391get_initial_emblems (GList *files)
3392{
3393 GHashTable *ret;
3394 GList *l;
3395
3396 ret = g_hash_table_new_full (g_direct_hash,
3397 g_direct_equal,
3398 NULL((void*)0),
3399 (GDestroyNotify) eel_g_list_free_deep);
3400
3401 for (l = files; l != NULL((void*)0); l = l->next) {
3402 CajaFile *file;
3403 GList *keywords;
3404
3405 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3406
3407 keywords = caja_file_get_keywords (file);
3408 g_hash_table_insert (ret, file, keywords);
3409 }
3410
3411 return ret;
3412}
3413
3414static gboolean
3415files_has_directory (FMPropertiesWindow *window)
3416{
3417 GList *l;
3418
3419 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3420 CajaFile *file;
3421 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3422 if (caja_file_is_directory (file)) {
3423 return TRUE(!(0));
3424 }
3425
3426 }
3427
3428 return FALSE(0);
3429}
3430
3431static gboolean
3432files_has_changable_permissions_directory (FMPropertiesWindow *window)
3433{
3434 GList *l;
3435
3436 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3437 CajaFile *file;
3438 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3439 if (caja_file_is_directory (file) &&
3440 caja_file_can_get_permissions (file) &&
3441 caja_file_can_set_permissions (file)) {
3442 return TRUE(!(0));
3443 }
3444
3445 }
3446
3447 return FALSE(0);
3448}
3449
3450
3451static gboolean
3452files_has_file (FMPropertiesWindow *window)
3453{
3454 GList *l;
3455
3456 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3457 CajaFile *file;
3458 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3459 if (!caja_file_is_directory (file)) {
3460 return TRUE(!(0));
3461 }
3462
3463 }
3464
3465 return FALSE(0);
3466}
3467
3468
3469static void
3470create_emblems_page (FMPropertiesWindow *window)
3471{
3472 GtkWidget *emblems_table, *button, *scroller;
3473 GdkPixbuf *pixbuf;
3474 char *label;
3475 GList *icons, *l;
3476 CajaIconInfo *info;
3477 gint scale;
3478
3479 /* The emblems wrapped table */
3480 scroller = eel_scrolled_wrap_table_new (TRUE(!(0)), GTK_SHADOW_NONE, &emblems_table);
3481
3482 gtk_container_set_border_width (GTK_CONTAINER (emblems_table)((((GtkContainer*) (void *) ((emblems_table))))), 12);
3483
3484 /* stop GTK 3.22 builds from ballooning the properties dialog to full screen height */
3485 gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (scroller)((((GtkScrolledWindow*) (void *) ((scroller))))), 300);
3486
3487 gtk_widget_show (scroller);
3488
3489 gtk_notebook_append_page (window->details->notebook,
3490 scroller, gtk_label_new (_("Emblems")dcgettext (((void*)0), "Emblems", 5)));
3491
3492 icons = caja_emblem_list_available ();
3493 scale = gtk_widget_get_scale_factor (scroller);
3494
3495 window->details->initial_emblems = get_initial_emblems (window->details->original_files);
3496
3497 l = icons;
3498 while (l != NULL((void*)0)) {
3499 char *emblem_name;
3500
3501 emblem_name = l->data;
3502 l = l->next;
3503
3504 if (!caja_emblem_should_show_in_list (emblem_name)) {
3505 continue;
3506 }
3507
3508 info = caja_icon_info_lookup_from_name (emblem_name, CAJA_ICON_SIZE_SMALL32, scale);
3509 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (info, CAJA_ICON_SIZE_SMALL32);
3510
3511 if (pixbuf == NULL((void*)0)) {
3512 continue;
3513 }
3514
3515 label = g_strdup (caja_icon_info_get_display_name (info))g_strdup_inline (caja_icon_info_get_display_name (info));
3516 g_object_unref (info);
3517
3518 if (label == NULL((void*)0)) {
3519 label = caja_emblem_get_keyword_from_icon_name (emblem_name);
3520 }
3521
3522 button = eel_labeled_image_check_button_new (label, pixbuf);
3523 eel_labeled_image_set_fixed_image_height (EEL_LABELED_IMAGE (gtk_bin_get_child (GTK_BIN (button)))((((EelLabeledImage*) (void *) ((gtk_bin_get_child (((((GtkBin
*) (void *) ((button)))))))))))
, STANDARD_EMBLEM_HEIGHT52 * scale);
3524 eel_labeled_image_set_spacing (EEL_LABELED_IMAGE (gtk_bin_get_child (GTK_BIN (button)))((((EelLabeledImage*) (void *) ((gtk_bin_get_child (((((GtkBin
*) (void *) ((button)))))))))))
, EMBLEM_LABEL_SPACING2 * scale);
3525
3526 g_free (label);
3527 g_object_unref (pixbuf);
3528
3529 /* Attach parameters and signal handler. */
3530 g_object_set_data_full (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name",
3531 caja_emblem_get_keyword_from_icon_name (emblem_name), g_free);
3532
3533 window->details->emblem_buttons =
3534 g_list_append (window->details->emblem_buttons,
3535 button);
3536
3537 g_signal_connect_object (button, "toggled",
3538 G_CALLBACK (emblem_button_toggled)((GCallback) (emblem_button_toggled)),
3539 G_OBJECT (window)((((GObject*) (void *) ((window))))),
3540 0);
3541
3542 gtk_container_add (GTK_CONTAINER (emblems_table)((((GtkContainer*) (void *) ((emblems_table))))), button);
3543 }
3544 g_list_free_full (icons, g_free);
3545 gtk_widget_show_all (emblems_table);
3546}
3547
3548static void
3549start_long_operation (FMPropertiesWindow *window)
3550{
3551 if (window->details->long_operation_underway == 0) {
3552 /* start long operation */
3553 GdkDisplay *display;
3554 GdkCursor * cursor;
3555
3556 display = gtk_widget_get_display (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
3557 cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
3558 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))), cursor);
3559 g_object_unref (cursor);
3560 }
3561 window->details->long_operation_underway ++;
3562}
3563
3564static void
3565end_long_operation (FMPropertiesWindow *window)
3566{
3567 if (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))) != NULL((void*)0) &&
3568 window->details->long_operation_underway == 1) {
3569 /* finished !! */
3570 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))), NULL((void*)0));
3571 }
3572 window->details->long_operation_underway--;
3573}
3574
3575static void
3576permission_change_callback (CajaFile *file,
3577 GFile *res_loc,
3578 GError *error,
3579 gpointer callback_data)
3580{
3581 FMPropertiesWindow *window;
3582 g_assert (callback_data != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_350
; if (callback_data != ((void*)0)) _g_boolean_var_350 = 1; else
_g_boolean_var_350 = 0; _g_boolean_var_350; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 3582, ((const char*
) (__func__)), "callback_data != NULL"); } while (0)
;
3583
3584 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
3585 end_long_operation (window);
3586
3587 /* Report the error if it's an error. */
3588 fm_report_error_setting_permissions (file, error, NULL((void*)0));
3589
3590 g_object_unref (window);
3591}
3592
3593static void
3594update_permissions (FMPropertiesWindow *window,
3595 guint32 vfs_new_perm,
3596 guint32 vfs_mask,
3597 gboolean is_folder,
3598 gboolean apply_to_both_folder_and_dir,
3599 gboolean use_original)
3600{
3601 GList *l;
3602
3603 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3604 CajaFile *file;
3605 guint32 permissions;
3606
3607 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3608
3609 if (!caja_file_can_get_permissions (file)) {
3610 continue;
3611 }
3612
3613 if (!apply_to_both_folder_and_dir &&
3614 ((caja_file_is_directory (file) && !is_folder) ||
3615 (!caja_file_is_directory (file) && is_folder))) {
3616 continue;
3617 }
3618
3619 permissions = caja_file_get_permissions (file);
3620 if (use_original) {
3621 gpointer ptr;
3622 if (g_hash_table_lookup_extended (window->details->initial_permissions,
3623 file, NULL((void*)0), &ptr)) {
3624 permissions = (permissions & ~vfs_mask) | (GPOINTER_TO_INT (ptr)((gint) (glong) (ptr)) & vfs_mask);
3625 }
3626 } else {
3627 permissions = (permissions & ~vfs_mask) | vfs_new_perm;
3628 }
3629
3630 start_long_operation (window);
3631 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
3632 caja_file_set_permissions
3633 (file, permissions,
3634 permission_change_callback,
3635 window);
3636 }
3637}
3638
3639static gboolean
3640initial_permission_state_consistent (FMPropertiesWindow *window,
3641 guint32 mask,
3642 gboolean is_folder,
3643 gboolean both_folder_and_dir)
3644{
3645 GList *l;
3646 gboolean first;
3647 guint32 first_permissions;
3648
3649 first = TRUE(!(0));
3650 first_permissions = 0;
3651 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3652 CajaFile *file;
3653 guint32 permissions;
3654
3655 file = l->data;
3656
3657 if (!both_folder_and_dir &&
3658 ((caja_file_is_directory (file) && !is_folder) ||
3659 (!caja_file_is_directory (file) && is_folder))) {
3660 continue;
3661 }
3662
3663 permissions = GPOINTER_TO_INT (g_hash_table_lookup (window->details->initial_permissions,((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
3664 file))((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
;
3665
3666 if (first) {
3667 if ((permissions & mask) != mask &&
3668 (permissions & mask) != 0) {
3669 /* Not fully on or off -> inconsistent */
3670 return FALSE(0);
3671 }
3672
3673 first_permissions = permissions;
3674 first = FALSE(0);
3675
3676 } else if ((permissions & mask) != (first_permissions & mask)) {
3677 /* Not same permissions as first -> inconsistent */
3678 return FALSE(0);
3679 }
3680 }
3681 return TRUE(!(0));
3682}
3683
3684static void
3685permission_button_toggled (GtkToggleButton *button,
3686 FMPropertiesWindow *window)
3687{
3688 gboolean is_folder, is_special;
3689 guint32 permission_mask;
3690 gboolean inconsistent;
3691 gboolean on;
3692
3693 permission_mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
3694 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
3695 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
3696 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
3697 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
3698 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
3699
3700 if (gtk_toggle_button_get_active (button)
3701 && !gtk_toggle_button_get_inconsistent (button)) {
3702 /* Go to the initial state unless the initial state was
3703 consistent, or we support recursive apply */
3704 inconsistent = TRUE(!(0));
3705 on = TRUE(!(0));
3706
3707 if (!window->details->has_recursive_apply &&
3708 initial_permission_state_consistent (window, permission_mask, is_folder, is_special)) {
3709 inconsistent = FALSE(0);
3710 on = TRUE(!(0));
3711 }
3712 } else if (gtk_toggle_button_get_inconsistent (button)
3713 && !gtk_toggle_button_get_active (button)) {
3714 inconsistent = FALSE(0);
3715 on = TRUE(!(0));
3716 } else {
3717 inconsistent = FALSE(0);
3718 on = FALSE(0);
3719 }
3720
3721 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3722 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3723 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3724
3725 gtk_toggle_button_set_active (button, on);
3726 gtk_toggle_button_set_inconsistent (button, inconsistent);
3727
3728 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3729 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3730 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3731
3732 update_permissions (window,
3733 on?permission_mask:0,
3734 permission_mask,
3735 is_folder,
3736 is_special,
3737 inconsistent);
3738}
3739
3740static void
3741permission_button_update (FMPropertiesWindow *window,
3742 GtkToggleButton *button)
3743{
3744 GList *l;
3745 gboolean all_set;
3746 gboolean all_unset;
3747 gboolean all_cannot_set;
3748 gboolean is_folder, is_special;
3749 gboolean no_match;
3750 gboolean sensitive;
3751 guint32 button_permission;
3752
3753 if (gtk_toggle_button_get_inconsistent (button) &&
3754 window->details->has_recursive_apply) {
3755 /* Never change from an inconsistent state if we have dirs, even
3756 * if the current state is now consistent, because its a useful
3757 * state for recursive apply.
3758 */
3759 return;
3760 }
3761
3762 button_permission = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
3763 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
3764 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
3765 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
3766 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
3767 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
3768
3769 all_set = TRUE(!(0));
3770 all_unset = TRUE(!(0));
3771 all_cannot_set = TRUE(!(0));
3772 no_match = TRUE(!(0));
3773 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3774 CajaFile *file;
3775 guint32 file_permissions;
3776
3777 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3778
3779 if (!caja_file_can_get_permissions (file)) {
3780 continue;
3781 }
3782
3783 if (!is_special &&
3784 ((caja_file_is_directory (file) && !is_folder) ||
3785 (!caja_file_is_directory (file) && is_folder))) {
3786 continue;
3787 }
3788
3789 no_match = FALSE(0);
3790
3791 file_permissions = caja_file_get_permissions (file);
3792
3793 if ((file_permissions & button_permission) == button_permission) {
3794 all_unset = FALSE(0);
3795 } else if ((file_permissions & button_permission) == 0) {
3796 all_set = FALSE(0);
3797 } else {
3798 all_unset = FALSE(0);
3799 all_set = FALSE(0);
3800 }
3801
3802 if (caja_file_can_set_permissions (file)) {
3803 all_cannot_set = FALSE(0);
3804 }
3805 }
3806
3807 sensitive = !all_cannot_set;
3808 if (!is_folder) {
3809 /* Don't insitive files when we have recursive apply */
3810 sensitive |= window->details->has_recursive_apply;
3811 }
3812
3813
3814 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3815 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3816 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3817
3818 gtk_toggle_button_set_active (button, !all_unset);
3819 /* if actually inconsistent, or default value for file buttons
3820 if no files are selected. (useful for recursive apply) */
3821 gtk_toggle_button_set_inconsistent (button,
3822 (!all_unset && !all_set) ||
3823 (!is_folder && no_match));
3824 gtk_widget_set_sensitive (GTK_WIDGET (button)((((GtkWidget*) (void *) ((button))))), sensitive);
3825
3826 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3827 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3828 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3829}
3830
3831static void
3832set_up_permissions_checkbox (FMPropertiesWindow *window,
3833 GtkWidget *check_button,
3834 guint32 permission,
3835 gboolean is_folder)
3836{
3837 /* Load up the check_button with data we'll need when updating its state. */
3838 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "permission",
3839 GINT_TO_POINTER (permission)((gpointer) (glong) (permission)));
3840 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "properties_window",
3841 window);
3842 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "is-folder",
3843 GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
3844
3845 window->details->permission_buttons =
3846 g_list_prepend (window->details->permission_buttons,
3847 check_button);
3848
3849 g_signal_connect_object (check_button, "toggled",
3850 G_CALLBACK (permission_button_toggled)((GCallback) (permission_button_toggled)),
3851 window,
3852 0);
3853}
3854
3855static GtkWidget *
3856add_permissions_checkbox_with_label (FMPropertiesWindow *window,
3857 GtkGrid *grid,
3858 GtkWidget *sibling,
3859 const char *label,
3860 guint32 permission_to_check,
3861 GtkLabel *label_for,
3862 gboolean is_folder)
3863{
3864 GtkWidget *check_button;
3865 gboolean a11y_enabled;
3866
3867 check_button = gtk_check_button_new_with_mnemonic (label);
3868 gtk_widget_show (check_button);
3869 if (sibling) {
3870 gtk_grid_attach_next_to (grid, check_button, sibling,
3871 GTK_POS_RIGHT, 1, 1);
3872 } else {
3873 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), check_button);
3874 }
3875
3876 set_up_permissions_checkbox (window,
3877 check_button,
3878 permission_to_check,
3879 is_folder);
3880
3881 a11y_enabled = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (check_button))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(gtk_widget_get_accessible (check_button))); GType __t = ((gtk_accessible_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; }))))
;
3882 if (a11y_enabled && label_for != NULL((void*)0)) {
3883 eel_accessibility_set_up_label_widget_relation (GTK_WIDGET (label_for)((((GtkWidget*) (void *) ((label_for))))),
3884 check_button);
3885 }
3886
3887 return check_button;
3888}
3889
3890static GtkWidget *
3891add_permissions_checkbox (FMPropertiesWindow *window,
3892 GtkGrid *grid,
3893 GtkWidget *sibling,
3894 CheckboxType type,
3895 guint32 permission_to_check,
3896 GtkLabel *label_for,
3897 gboolean is_folder)
3898{
3899 const gchar *label;
3900
3901 if (type == PERMISSIONS_CHECKBOXES_READ) {
3902 label = _("_Read")dcgettext (((void*)0), "_Read", 5);
3903 } else if (type == PERMISSIONS_CHECKBOXES_WRITE) {
3904 label = _("_Write")dcgettext (((void*)0), "_Write", 5);
3905 } else {
3906 label = _("E_xecute")dcgettext (((void*)0), "E_xecute", 5);
3907 }
3908
3909 return add_permissions_checkbox_with_label (window, grid,
3910 sibling,
3911 label,
3912 permission_to_check,
3913 label_for,
3914 is_folder);
3915}
3916
3917enum {
3918 UNIX_PERM_SUID = S_ISUID04000,
3919 UNIX_PERM_SGID = S_ISGID02000,
3920 UNIX_PERM_STICKY = 01000, /* S_ISVTX not defined on all systems */
3921 UNIX_PERM_USER_READ = S_IRUSR0400,
3922 UNIX_PERM_USER_WRITE = S_IWUSR0200,
3923 UNIX_PERM_USER_EXEC = S_IXUSR0100,
3924 UNIX_PERM_USER_ALL = S_IRUSR0400 | S_IWUSR0200 | S_IXUSR0100,
3925 UNIX_PERM_GROUP_READ = S_IRGRP(0400 >> 3),
3926 UNIX_PERM_GROUP_WRITE = S_IWGRP(0200 >> 3),
3927 UNIX_PERM_GROUP_EXEC = S_IXGRP(0100 >> 3),
3928 UNIX_PERM_GROUP_ALL = S_IRGRP(0400 >> 3) | S_IWGRP(0200 >> 3) | S_IXGRP(0100 >> 3),
3929 UNIX_PERM_OTHER_READ = S_IROTH((0400 >> 3) >> 3),
3930 UNIX_PERM_OTHER_WRITE = S_IWOTH((0200 >> 3) >> 3),
3931 UNIX_PERM_OTHER_EXEC = S_IXOTH((0100 >> 3) >> 3),
3932 UNIX_PERM_OTHER_ALL = S_IROTH((0400 >> 3) >> 3) | S_IWOTH((0200 >> 3) >> 3) | S_IXOTH((0100 >> 3) >> 3)
3933};
3934
3935typedef enum {
3936 PERMISSION_READ = (1<<0),
3937 PERMISSION_WRITE = (1<<1),
3938 PERMISSION_EXEC = (1<<2)
3939} PermissionValue;
3940
3941typedef enum {
3942 PERMISSION_USER,
3943 PERMISSION_GROUP,
3944 PERMISSION_OTHER
3945} PermissionType;
3946
3947static guint32 vfs_perms[3][3] = {
3948 {UNIX_PERM_USER_READ, UNIX_PERM_USER_WRITE, UNIX_PERM_USER_EXEC},
3949 {UNIX_PERM_GROUP_READ, UNIX_PERM_GROUP_WRITE, UNIX_PERM_GROUP_EXEC},
3950 {UNIX_PERM_OTHER_READ, UNIX_PERM_OTHER_WRITE, UNIX_PERM_OTHER_EXEC},
3951};
3952
3953static guint32
3954permission_to_vfs (PermissionType type, PermissionValue perm)
3955{
3956 guint32 vfs_perm;
3957 g_assert (type >= 0 && type < 3)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_351
; if (type >= 0 && type < 3) _g_boolean_var_351
= 1; else _g_boolean_var_351 = 0; _g_boolean_var_351; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 3957, ((const char*) (__func__)), "type >= 0 && type < 3"
); } while (0)
;
3958
3959 vfs_perm = 0;
3960 if (perm & PERMISSION_READ) {
3961 vfs_perm |= vfs_perms[type][0];
3962 }
3963 if (perm & PERMISSION_WRITE) {
3964 vfs_perm |= vfs_perms[type][1];
3965 }
3966 if (perm & PERMISSION_EXEC) {
3967 vfs_perm |= vfs_perms[type][2];
3968 }
3969
3970 return vfs_perm;
3971}
3972
3973
3974static PermissionValue
3975permission_from_vfs (PermissionType type, guint32 vfs_perm)
3976{
3977 PermissionValue perm;
3978 g_assert (type >= 0 && type < 3)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_352
; if (type >= 0 && type < 3) _g_boolean_var_352
= 1; else _g_boolean_var_352 = 0; _g_boolean_var_352; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 3978, ((const char*) (__func__)), "type >= 0 && type < 3"
); } while (0)
;
3979
3980 perm = 0;
3981 if (vfs_perm & vfs_perms[type][0]) {
3982 perm |= PERMISSION_READ;
3983 }
3984 if (vfs_perm & vfs_perms[type][1]) {
3985 perm |= PERMISSION_WRITE;
3986 }
3987 if (vfs_perm & vfs_perms[type][2]) {
3988 perm |= PERMISSION_EXEC;
3989 }
3990
3991 return perm;
3992}
3993
3994static void
3995permission_combo_changed (GtkWidget *combo, FMPropertiesWindow *window)
3996{
3997 GtkTreeIter iter;
3998 GtkTreeModel *model;
3999 gboolean is_folder, use_original;
4000 PermissionType type;
4001 int new_perm, mask;
4002 guint32 vfs_new_perm, vfs_mask;
4003
4004 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4005 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4006
4007 if (is_folder) {
4008 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4009 } else {
4010 mask = PERMISSION_READ|PERMISSION_WRITE;
4011 }
4012
4013 vfs_mask = permission_to_vfs (type, mask);
4014
4015 model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))));
4016
4017 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4018 return;
4019 }
4020 gtk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
4021 vfs_new_perm = permission_to_vfs (type, new_perm);
4022
4023 update_permissions (window, vfs_new_perm, vfs_mask,
4024 is_folder, FALSE(0), use_original);
4025}
4026
4027static void
4028permission_combo_add_multiple_choice (GtkComboBox *combo, GtkTreeIter *iter)
4029{
4030 GtkTreeModel *model;
4031 GtkListStore *store;
4032 gboolean found;
4033
4034 model = gtk_combo_box_get_model (combo);
4035 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
4036
4037 found = FALSE(0);
4038 gtk_tree_model_get_iter_first (model, iter);
4039 do {
4040 gboolean multi;
4041 gtk_tree_model_get (model, iter, 2, &multi, -1);
4042
4043 if (multi) {
4044 found = TRUE(!(0));
4045 break;
4046 }
4047 } while (gtk_tree_model_iter_next (model, iter));
4048
4049 if (!found) {
4050 gtk_list_store_append (store, iter);
4051 gtk_list_store_set (store, iter, 0, "---", 1, 0, 2, TRUE(!(0)), -1);
4052 }
4053}
4054
4055static void
4056permission_combo_update (FMPropertiesWindow *window,
4057 GtkComboBox *combo)
4058{
4059 PermissionType type;
4060 PermissionValue perm, all_dir_perm, all_file_perm, all_perm;
4061 gboolean is_folder, no_files, no_dirs, all_file_same, all_dir_same, all_same;
4062 gboolean all_dir_cannot_set, all_file_cannot_set, sensitive;
4063 GtkTreeIter iter;
4064 int mask;
4065 GtkTreeModel *model;
4066 GtkListStore *store;
4067 GList *l;
4068 gboolean is_multi;
4069
4070 model = gtk_combo_box_get_model (combo);
4071
4072 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4073 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4074
4075 is_multi = FALSE(0);
4076 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4077 gtk_tree_model_get (model, &iter, 2, &is_multi, -1);
4078 }
4079
4080 if (is_multi && window->details->has_recursive_apply) {
4081 /* Never change from an inconsistent state if we have dirs, even
4082 * if the current state is now consistent, because its a useful
4083 * state for recursive apply.
4084 */
4085 return;
4086 }
4087
4088 no_files = TRUE(!(0));
4089 no_dirs = TRUE(!(0));
4090 all_dir_same = TRUE(!(0));
4091 all_file_same = TRUE(!(0));
4092 all_dir_perm = 0;
4093 all_file_perm = 0;
4094 all_dir_cannot_set = TRUE(!(0));
4095 all_file_cannot_set = TRUE(!(0));
4096
4097 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4098 CajaFile *file;
4099 guint32 file_permissions;
4100
4101 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4102
4103 if (!caja_file_can_get_permissions (file)) {
4104 continue;
4105 }
4106
4107 if (caja_file_is_directory (file)) {
4108 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4109 } else {
4110 mask = PERMISSION_READ|PERMISSION_WRITE;
4111 }
4112
4113 file_permissions = caja_file_get_permissions (file);
4114
4115 perm = permission_from_vfs (type, file_permissions) & mask;
4116
4117 if (caja_file_is_directory (file)) {
4118 if (no_dirs) {
4119 all_dir_perm = perm;
4120 no_dirs = FALSE(0);
4121 } else if (perm != all_dir_perm) {
4122 all_dir_same = FALSE(0);
4123 }
4124
4125 if (caja_file_can_set_permissions (file)) {
4126 all_dir_cannot_set = FALSE(0);
4127 }
4128 } else {
4129 if (no_files) {
4130 all_file_perm = perm;
4131 no_files = FALSE(0);
4132 } else if (perm != all_file_perm) {
4133 all_file_same = FALSE(0);
4134 }
4135
4136 if (caja_file_can_set_permissions (file)) {
4137 all_file_cannot_set = FALSE(0);
4138 }
4139 }
4140 }
4141
4142 if (is_folder) {
4143 all_same = all_dir_same;
4144 all_perm = all_dir_perm;
4145 } else {
4146 all_same = all_file_same && !no_files;
4147 all_perm = all_file_perm;
4148 }
4149
4150 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
4151 if (all_same) {
4152 gboolean found;
4153
4154 found = FALSE(0);
4155 gtk_tree_model_get_iter_first (model, &iter);
4156 do {
4157 int current_perm;
4158 gtk_tree_model_get (model, &iter, 1, &current_perm, -1);
4159
4160 if (current_perm == all_perm) {
4161 found = TRUE(!(0));
4162 break;
4163 }
4164 } while (gtk_tree_model_iter_next (model, &iter));
4165
4166 if (!found) {
4167 GString *str;
4168 str = g_string_new ("");
4169
4170 if (!(all_perm & PERMISSION_READ)) {
4171 /* Translators: this gets concatenated to "no read",
4172 * "no access", etc. (see following strings)
4173 */
4174 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_353; if (__val != ((void
*)0)) _g_boolean_var_353 = 1; else _g_boolean_var_353 = 0; _g_boolean_var_353
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4175 }
4176 if (is_folder) {
4177 g_string_append (str, _("list"))(__builtin_constant_p (dcgettext (((void*)0), "list", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "list"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_354; if (__val != ((void
*)0)) _g_boolean_var_354 = 1; else _g_boolean_var_354 = 0; _g_boolean_var_354
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "list", 5), (gssize) -1))
;
4178 } else {
4179 g_string_append (str, _("read"))(__builtin_constant_p (dcgettext (((void*)0), "read", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "read"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_355; if (__val != ((void
*)0)) _g_boolean_var_355 = 1; else _g_boolean_var_355 = 0; _g_boolean_var_355
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "read", 5), (gssize) -1))
;
4180 }
4181
4182 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_356; if (__val != ((void
*)0)) _g_boolean_var_356 = 1; else _g_boolean_var_356 = 0; _g_boolean_var_356
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
4183
4184 if (!(all_perm & PERMISSION_WRITE)) {
4185 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_357; if (__val != ((void
*)0)) _g_boolean_var_357 = 1; else _g_boolean_var_357 = 0; _g_boolean_var_357
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4186 }
4187 if (is_folder) {
4188 g_string_append (str, _("create/delete"))(__builtin_constant_p (dcgettext (((void*)0), "create/delete"
, 5)) ? __extension__ ({ const char * const __val = (dcgettext
(((void*)0), "create/delete", 5)); g_string_append_len_inline
(str, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_358
; if (__val != ((void*)0)) _g_boolean_var_358 = 1; else _g_boolean_var_358
= 0; _g_boolean_var_358; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, dcgettext (((void*)0), "create/delete", 5), (gssize) -
1))
;
4189 } else {
4190 g_string_append (str, _("write"))(__builtin_constant_p (dcgettext (((void*)0), "write", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "write"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_359; if (__val != ((void
*)0)) _g_boolean_var_359 = 1; else _g_boolean_var_359 = 0; _g_boolean_var_359
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "write", 5), (gssize) -1))
;
4191 }
4192
4193 if (is_folder) {
4194 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_360; if (__val != ((void
*)0)) _g_boolean_var_360 = 1; else _g_boolean_var_360 = 0; _g_boolean_var_360
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
4195
4196 if (!(all_perm & PERMISSION_EXEC)) {
4197 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_361; if (__val != ((void
*)0)) _g_boolean_var_361 = 1; else _g_boolean_var_361 = 0; _g_boolean_var_361
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4198 }
4199 g_string_append (str, _("access"))(__builtin_constant_p (dcgettext (((void*)0), "access", 5)) ?
__extension__ ({ const char * const __val = (dcgettext (((void
*)0), "access", 5)); g_string_append_len_inline (str, __val, (
__builtin_expect (__extension__ ({ int _g_boolean_var_362; if
(__val != ((void*)0)) _g_boolean_var_362 = 1; else _g_boolean_var_362
= 0; _g_boolean_var_362; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, dcgettext (((void*)0), "access", 5), (gssize) -1))
;
4200 }
4201
4202 gtk_list_store_append (store, &iter);
4203 gtk_list_store_set (store, &iter,
4204 0, str->str,
4205 1, all_perm, -1);
4206
4207 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
4208 }
4209 } else {
4210 permission_combo_add_multiple_choice (combo, &iter);
4211 }
4212
4213 g_signal_handlers_block_by_func (G_OBJECT (combo),g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4214 G_CALLBACK (permission_combo_changed),g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4215 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4216
4217 gtk_combo_box_set_active_iter (combo, &iter);
4218
4219 /* Also enable if no files found (for recursive
4220 file changes when only selecting folders) */
4221 if (is_folder) {
4222 sensitive = !all_dir_cannot_set;
4223 } else {
4224 sensitive = !all_file_cannot_set ||
4225 window->details->has_recursive_apply;
4226 }
4227 gtk_widget_set_sensitive (GTK_WIDGET (combo)((((GtkWidget*) (void *) ((combo))))), sensitive);
4228
4229 g_signal_handlers_unblock_by_func (G_OBJECT (combo),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4230 G_CALLBACK (permission_combo_changed),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4231 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4232
4233}
4234
4235static void
4236add_permissions_combo_box (FMPropertiesWindow *window, GtkGrid *grid,
4237 PermissionType type, gboolean is_folder,
4238 gboolean short_label)
4239{
4240 GtkWidget *combo;
4241 GtkLabel *label;
4242 GtkListStore *store;
4243 GtkCellRenderer *cell;
4244 GtkTreeIter iter;
4245
4246 if (short_label) {
4247 label = attach_title_field (grid, _("Access:")dcgettext (((void*)0), "Access:", 5));
4248 } else if (is_folder) {
4249 label = attach_title_field (grid, _("Folder access:")dcgettext (((void*)0), "Folder access:", 5));
4250 } else {
4251 label = attach_title_field (grid, _("File access:")dcgettext (((void*)0), "File access:", 5));
4252 }
4253
4254 store = gtk_list_store_new (3, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_INT((GType) ((6) << (2))), G_TYPE_BOOLEAN((GType) ((5) << (2))));
4255 combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))));
4256
4257 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) ((combo))))), "is-folder", GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
4258 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) ((combo))))), "permission-type", GINT_TO_POINTER (type)((gpointer) (glong) (type)));
4259
4260 if (is_folder) {
4261 if (type != PERMISSION_USER) {
4262 gtk_list_store_append (store, &iter);
4263 /* Translators: this is referred to the permissions
4264 * the user has in a directory.
4265 */
4266 gtk_list_store_set (store, &iter, 0, _("None")dcgettext (((void*)0), "None", 5), 1, 0, -1);
4267 }
4268 gtk_list_store_append (store, &iter);
4269 gtk_list_store_set (store, &iter, 0, _("List files only")dcgettext (((void*)0), "List files only", 5), 1, PERMISSION_READ, -1);
4270 gtk_list_store_append (store, &iter);
4271 gtk_list_store_set (store, &iter, 0, _("Access files")dcgettext (((void*)0), "Access files", 5), 1, PERMISSION_READ|PERMISSION_EXEC, -1);
4272 gtk_list_store_append (store, &iter);
4273 gtk_list_store_set (store, &iter, 0, _("Create and delete files")dcgettext (((void*)0), "Create and delete files", 5), 1, PERMISSION_READ|PERMISSION_EXEC|PERMISSION_WRITE, -1);
4274 } else {
4275 if (type != PERMISSION_USER) {
4276 gtk_list_store_append (store, &iter);
4277 gtk_list_store_set (store, &iter, 0, _("None")dcgettext (((void*)0), "None", 5), 1, 0, -1);
4278 }
4279 gtk_list_store_append (store, &iter);
4280 gtk_list_store_set (store, &iter, 0, _("Read-only")dcgettext (((void*)0), "Read-only", 5), 1, PERMISSION_READ, -1);
4281 gtk_list_store_append (store, &iter);
4282 gtk_list_store_set (store, &iter, 0, _("Read and write")dcgettext (((void*)0), "Read and write", 5), 1, PERMISSION_READ|PERMISSION_WRITE, -1);
4283 }
4284 if (window->details->has_recursive_apply) {
4285 permission_combo_add_multiple_choice (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
4286 }
4287
4288 g_object_unref (store);
4289
4290 window->details->permission_combos =
4291 g_list_prepend (window->details->permission_combos,
4292 combo);
4293
4294 g_signal_connect (combo, "changed", G_CALLBACK (permission_combo_changed), window)g_signal_connect_data ((combo), ("changed"), (((GCallback) (permission_combo_changed
))), (window), ((void*)0), (GConnectFlags) 0)
;
4295
4296 cell = gtk_cell_renderer_text_new ();
4297 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
4298 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell,
4299 "text", 0,
4300 NULL((void*)0));
4301
4302 gtk_label_set_mnemonic_widget (label, combo);
4303 gtk_widget_show (combo);
4304
4305 gtk_grid_attach_next_to (grid, combo, GTK_WIDGET (label)((((GtkWidget*) (void *) ((label))))),
4306 GTK_POS_RIGHT, 1, 1);
4307}
4308
4309
4310static GtkWidget *
4311append_special_execution_checkbox (FMPropertiesWindow *window,
4312 GtkGrid *grid,
4313 GtkWidget *sibling,
4314 const char *label_text,
4315 guint32 permission_to_check)
4316{
4317 GtkWidget *check_button;
4318
4319 check_button = gtk_check_button_new_with_mnemonic (label_text);
4320 gtk_widget_show (check_button);
4321
4322 if (sibling != NULL((void*)0)) {
4323 gtk_grid_attach_next_to (grid, check_button, sibling,
4324 GTK_POS_RIGHT, 1, 1);
4325 } else {
4326 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), check_button,
4327 "left-attach", 1,
4328 NULL((void*)0));
4329 }
4330
4331 set_up_permissions_checkbox (window,
4332 check_button,
4333 permission_to_check,
4334 FALSE(0));
4335 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "is-special",
4336 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4337
4338 return check_button;
4339}
4340
4341static void
4342append_special_execution_flags (FMPropertiesWindow *window, GtkGrid *grid)
4343{
4344 GtkWidget *title;
4345
4346 append_blank_slim_row (grid);
4347 title = GTK_WIDGET (attach_title_field (grid, _("Special flags:")))((((GtkWidget*) (void *) ((attach_title_field (grid, dcgettext
(((void*)0), "Special flags:", 5)))))))
;
4348
4349 append_special_execution_checkbox (window, grid, title, _("Set _user ID")dcgettext (((void*)0), "Set _user ID", 5), UNIX_PERM_SUID);
4350 append_special_execution_checkbox (window, grid, NULL((void*)0), _("Set gro_up ID")dcgettext (((void*)0), "Set gro_up ID", 5), UNIX_PERM_SGID);
4351 append_special_execution_checkbox (window, grid, NULL((void*)0), _("_Sticky")dcgettext (((void*)0), "_Sticky", 5), UNIX_PERM_STICKY);
4352}
4353
4354static gboolean
4355all_can_get_permissions (GList *file_list)
4356{
4357 GList *l;
4358 for (l = file_list; l != NULL((void*)0); l = l->next) {
4359 CajaFile *file;
4360
4361 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4362
4363 if (!caja_file_can_get_permissions (file)) {
4364 return FALSE(0);
4365 }
4366 }
4367
4368 return TRUE(!(0));
4369}
4370
4371static gboolean
4372all_can_set_permissions (GList *file_list)
4373{
4374 GList *l;
4375 for (l = file_list; l != NULL((void*)0); l = l->next) {
4376 CajaFile *file;
4377
4378 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4379
4380 if (!caja_file_can_set_permissions (file)) {
4381 return FALSE(0);
4382 }
4383 }
4384
4385 return TRUE(!(0));
4386}
4387
4388static GHashTable *
4389get_initial_permissions (GList *file_list)
4390{
4391 GHashTable *ret;
4392 GList *l;
4393
4394 ret = g_hash_table_new (g_direct_hash,
4395 g_direct_equal);
4396
4397 for (l = file_list; l != NULL((void*)0); l = l->next) {
4398 guint32 permissions;
4399 CajaFile *file;
4400
4401 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4402
4403 permissions = caja_file_get_permissions (file);
4404 g_hash_table_insert (ret, file,
4405 GINT_TO_POINTER (permissions)((gpointer) (glong) (permissions)));
4406 }
4407
4408 return ret;
4409}
4410
4411static void
4412create_simple_permissions (FMPropertiesWindow *window, GtkGrid *page_grid)
4413{
4414 gboolean has_file, has_directory;
4415 GtkLabel *group_label;
4416 GtkLabel *owner_label;
4417 GtkLabel *execute_label;
4418 GtkWidget *value;
4419
4420 has_file = files_has_file (window);
4421 has_directory = files_has_directory (window);
4422
4423 if (!is_multi_file_window (window) && caja_file_can_set_owner (get_target_file (window))) {
4424 GtkComboBox *owner_combo_box;
4425
4426 owner_label = attach_title_field (page_grid, _("_Owner:")dcgettext (((void*)0), "_Owner:", 5));
4427 /* Combo box in this case. */
4428 owner_combo_box = attach_owner_combo_box (page_grid,
4429 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4430 get_target_file (window));
4431 gtk_label_set_mnemonic_widget (owner_label,
4432 GTK_WIDGET (owner_combo_box)((((GtkWidget*) (void *) ((owner_combo_box))))));
4433 } else {
4434 owner_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4435 /* Static text in this case. */
4436 value = attach_value_field (window,
4437 page_grid, GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4438 "owner",
4439 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4440 FALSE(0));
4441 gtk_label_set_mnemonic_widget (owner_label, value);
4442 }
4443
4444 if (has_directory) {
4445 add_permissions_combo_box (window, page_grid,
4446 PERMISSION_USER, TRUE(!(0)), FALSE(0));
4447 }
4448 if (has_file || window->details->has_recursive_apply) {
4449 add_permissions_combo_box (window, page_grid,
4450 PERMISSION_USER, FALSE(0), !has_directory);
4451 }
4452
4453 append_blank_slim_row (page_grid);
4454
4455 if (!is_multi_file_window (window) && caja_file_can_set_group (get_target_file (window))) {
4456 GtkComboBox *group_combo_box;
4457
4458 group_label = attach_title_field (page_grid, _("_Group:")dcgettext (((void*)0), "_Group:", 5));
4459
4460 /* Combo box in this case. */
4461 group_combo_box = attach_group_combo_box (page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4462 get_target_file (window));
4463 gtk_label_set_mnemonic_widget (group_label,
4464 GTK_WIDGET (group_combo_box)((((GtkWidget*) (void *) ((group_combo_box))))));
4465 } else {
4466 group_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4467
4468 /* Static text in this case. */
4469 value = attach_value_field (window, page_grid,
4470 GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4471 "group",
4472 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4473 FALSE(0));
4474 gtk_label_set_mnemonic_widget (group_label, value);
4475 }
4476
4477 if (has_directory) {
4478 add_permissions_combo_box (window, page_grid,
4479 PERMISSION_GROUP, TRUE(!(0)),
4480 FALSE(0));
4481 }
4482 if (has_file || window->details->has_recursive_apply) {
4483 add_permissions_combo_box (window, page_grid,
4484 PERMISSION_GROUP, FALSE(0),
4485 !has_directory);
4486 }
4487
4488 append_blank_slim_row (page_grid);
4489
4490 group_label = attach_title_field (page_grid, _("Others")dcgettext (((void*)0), "Others", 5));
4491
4492 if (has_directory) {
4493 add_permissions_combo_box (window, page_grid,
4494 PERMISSION_OTHER, TRUE(!(0)),
4495 FALSE(0));
4496 }
4497 if (has_file || window->details->has_recursive_apply) {
4498 add_permissions_combo_box (window, page_grid,
4499 PERMISSION_OTHER, FALSE(0),
4500 !has_directory);
4501 }
4502
4503 append_blank_slim_row (page_grid);
4504
4505 execute_label = attach_title_field (page_grid, _("Execute:")dcgettext (((void*)0), "Execute:", 5));
4506 add_permissions_checkbox_with_label (window, page_grid,
4507 GTK_WIDGET (execute_label)((((GtkWidget*) (void *) ((execute_label))))),
4508 _("Allow _executing file as program")dcgettext (((void*)0), "Allow _executing file as program", 5),
4509 UNIX_PERM_USER_EXEC|UNIX_PERM_GROUP_EXEC|UNIX_PERM_OTHER_EXEC,
4510 execute_label, FALSE(0));
4511}
4512
4513static void
4514create_permission_checkboxes (FMPropertiesWindow *window,
4515 GtkGrid *page_grid,
4516 gboolean is_folder)
4517{
4518 GtkLabel *owner_perm_label;
4519 GtkLabel *group_perm_label;
4520 GtkLabel *other_perm_label;
4521 GtkGrid *check_button_grid;
4522 GtkWidget *w;
4523
4524 owner_perm_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4525 group_perm_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4526 other_perm_label = attach_title_field (page_grid, _("Others:")dcgettext (((void*)0), "Others:", 5));
4527
4528 check_button_grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
4529 gtk_widget_show (GTK_WIDGET (check_button_grid)((((GtkWidget*) (void *) ((check_button_grid))))));
4530
4531 gtk_grid_attach_next_to (page_grid, GTK_WIDGET (check_button_grid)((((GtkWidget*) (void *) ((check_button_grid))))),
4532 GTK_WIDGET (owner_perm_label)((((GtkWidget*) (void *) ((owner_perm_label))))),
4533 GTK_POS_RIGHT, 1, 3);
4534
4535 w = add_permissions_checkbox (window,
4536 check_button_grid,
4537 NULL((void*)0),
4538 PERMISSIONS_CHECKBOXES_READ,
4539 UNIX_PERM_USER_READ,
4540 owner_perm_label,
4541 is_folder);
4542
4543 w = add_permissions_checkbox (window,
4544 check_button_grid,
4545 w,
4546 PERMISSIONS_CHECKBOXES_WRITE,
4547 UNIX_PERM_USER_WRITE,
4548 owner_perm_label,
4549 is_folder);
4550
4551 w = add_permissions_checkbox (window,
Value stored to 'w' is never read
4552 check_button_grid,
4553 w,
4554 PERMISSIONS_CHECKBOXES_EXECUTE,
4555 UNIX_PERM_USER_EXEC,
4556 owner_perm_label,
4557 is_folder);
4558
4559 w = add_permissions_checkbox (window,
4560 check_button_grid,
4561 NULL((void*)0),
4562 PERMISSIONS_CHECKBOXES_READ,
4563 UNIX_PERM_GROUP_READ,
4564 group_perm_label,
4565 is_folder);
4566
4567 w = add_permissions_checkbox (window,
4568 check_button_grid,
4569 w,
4570 PERMISSIONS_CHECKBOXES_WRITE,
4571 UNIX_PERM_GROUP_WRITE,
4572 group_perm_label,
4573 is_folder);
4574
4575 w = add_permissions_checkbox (window,
4576 check_button_grid,
4577 w,
4578 PERMISSIONS_CHECKBOXES_EXECUTE,
4579 UNIX_PERM_GROUP_EXEC,
4580 group_perm_label,
4581 is_folder);
4582
4583 w = add_permissions_checkbox (window,
4584 check_button_grid,
4585 NULL((void*)0),
4586 PERMISSIONS_CHECKBOXES_READ,
4587 UNIX_PERM_OTHER_READ,
4588 other_perm_label,
4589 is_folder);
4590
4591 w = add_permissions_checkbox (window,
4592 check_button_grid,
4593 w,
4594 PERMISSIONS_CHECKBOXES_WRITE,
4595 UNIX_PERM_OTHER_WRITE,
4596 other_perm_label,
4597 is_folder);
4598
4599 add_permissions_checkbox (window,
4600 check_button_grid,
4601 w,
4602 PERMISSIONS_CHECKBOXES_EXECUTE,
4603 UNIX_PERM_OTHER_EXEC,
4604 other_perm_label,
4605 is_folder);
4606}
4607
4608static void
4609create_advanced_permissions (FMPropertiesWindow *window, GtkGrid *page_grid)
4610{
4611 GtkLabel *group_label;
4612 GtkLabel *owner_label;
4613 gboolean has_directory, has_file;
4614
4615 if (!is_multi_file_window (window) && caja_file_can_set_owner (get_target_file (window))) {
4616 GtkComboBox *owner_combo_box;
4617
4618 owner_label = attach_title_field (page_grid, _("_Owner:")dcgettext (((void*)0), "_Owner:", 5));
4619 /* Combo box in this case. */
4620 owner_combo_box = attach_owner_combo_box (page_grid,
4621 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4622 get_target_file (window));
4623 gtk_label_set_mnemonic_widget (owner_label,
4624 GTK_WIDGET (owner_combo_box)((((GtkWidget*) (void *) ((owner_combo_box))))));
4625 } else {
4626 GtkWidget *value;
4627 owner_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4628
4629 /* Static text in this case. */
4630 value = attach_value_field (window,
4631 page_grid,
4632 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4633 "owner",
4634 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4635 FALSE(0));
4636 gtk_label_set_mnemonic_widget (owner_label, value);
4637 }
4638
4639 if (!is_multi_file_window (window) && caja_file_can_set_group (get_target_file (window))) {
4640 GtkComboBox *group_combo_box;
4641
4642 group_label = attach_title_field (page_grid, _("_Group:")dcgettext (((void*)0), "_Group:", 5));
4643
4644 /* Combo box in this case. */
4645 group_combo_box = attach_group_combo_box (page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4646 get_target_file (window));
4647 gtk_label_set_mnemonic_widget (group_label,
4648 GTK_WIDGET (group_combo_box)((((GtkWidget*) (void *) ((group_combo_box))))));
4649 } else {
4650 group_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4651
4652 /* Static text in this case. */
4653 attach_value_field (window, page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4654 "group",
4655 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4656 FALSE(0));
4657 }
4658
4659 append_blank_slim_row (page_grid);
4660
4661 has_directory = files_has_directory (window);
4662 has_file = files_has_file (window);
4663
4664 if (has_directory) {
4665 if (has_file || window->details->has_recursive_apply) {
4666 attach_title_field (page_grid, _("Folder Permissions:")dcgettext (((void*)0), "Folder Permissions:", 5));
4667 }
4668 create_permission_checkboxes (window, page_grid, TRUE(!(0)));
4669 }
4670
4671 if (has_file || window->details->has_recursive_apply) {
4672 if (has_directory) {
4673 attach_title_field (page_grid, _("File Permissions:")dcgettext (((void*)0), "File Permissions:", 5));
4674 }
4675 create_permission_checkboxes (window, page_grid, FALSE(0));
4676 }
4677
4678 append_blank_slim_row (page_grid);
4679 append_special_execution_flags (window, page_grid);
4680
4681 append_title_value_pair
4682 (window, page_grid, _("Text view:")dcgettext (((void*)0), "Text view:", 5),
4683 "permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4684 FALSE(0));
4685}
4686
4687static void
4688set_recursive_permissions_done (gpointer callback_data)
4689{
4690 FMPropertiesWindow *window;
4691
4692 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
4693 end_long_operation (window);
4694
4695 g_object_unref (window);
4696}
4697
4698
4699static void
4700apply_recursive_clicked (GtkWidget *recursive_button,
4701 FMPropertiesWindow *window)
4702{
4703 guint32 file_permission, file_permission_mask;
4704 guint32 dir_permission, dir_permission_mask;
4705 guint32 vfs_mask, vfs_new_perm, p;
4706 gboolean active, is_folder, is_special, use_original;
4707 GList *l;
4708 GtkTreeModel *model;
4709 GtkTreeIter iter;
4710 PermissionType type;
4711 int new_perm, mask;
4712 GtkWidget *button = NULL((void*)0);
4713 GtkWidget *combo = NULL((void*)0);
4714
4715 file_permission = 0;
4716 file_permission_mask = 0;
4717 dir_permission = 0;
4718 dir_permission_mask = 0;
4719
4720 /* Advanced mode and execute checkbox: */
4721 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
4722 button = l->data;
4723
4724 if (gtk_toggle_button_get_inconsistent (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))))) {
4725 continue;
4726 }
4727
4728 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))));
4729 p = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
4730 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
4731 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
4732 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
4733 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
4734 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
4735
4736 if (is_folder || is_special) {
4737 dir_permission_mask |= p;
4738 if (active) {
4739 dir_permission |= p;
4740 }
4741 }
4742 if (!is_folder || is_special) {
4743 file_permission_mask |= p;
4744 if (active) {
4745 file_permission |= p;
4746 }
4747 }
4748 }
4749 /* Simple mode, minus exec checkbox */
4750 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
4751 combo = l->data;
4752
4753 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4754 continue;
4755 }
4756
4757 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4758 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
4759 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4760
4761 model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))));
4762 gtk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
4763 if (use_original) {
4764 continue;
4765 }
4766 vfs_new_perm = permission_to_vfs (type, new_perm);
4767
4768 if (is_folder) {
4769 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4770 } else {
4771 mask = PERMISSION_READ|PERMISSION_WRITE;
4772 }
4773 vfs_mask = permission_to_vfs (type, mask);
4774
4775 if (is_folder) {
4776 dir_permission_mask |= vfs_mask;
4777 dir_permission |= vfs_new_perm;
4778 } else {
4779 file_permission_mask |= vfs_mask;
4780 file_permission |= vfs_new_perm;
4781 }
4782 }
4783
4784 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4785 CajaFile *file;
4786
4787 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4788
4789 if (caja_file_is_directory (file) &&
4790 caja_file_can_set_permissions (file)) {
4791 char *uri;
4792
4793 uri = caja_file_get_uri (file);
4794 start_long_operation (window);
4795 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
4796 caja_file_set_permissions_recursive (uri,
4797 file_permission,
4798 file_permission_mask,
4799 dir_permission,
4800 dir_permission_mask,
4801 set_recursive_permissions_done,
4802 window);
4803 g_free (uri);
4804 }
4805 }
4806}
4807
4808static void
4809create_permissions_page (FMPropertiesWindow *window)
4810{
4811 GtkWidget *vbox;
4812 GList *file_list;
4813
4814 vbox = create_page_with_vbox (window->details->notebook,
4815 _("Permissions")dcgettext (((void*)0), "Permissions", 5));
4816
4817 file_list = window->details->original_files;
4818
4819 window->details->initial_permissions = NULL((void*)0);
4820
4821 if (all_can_get_permissions (file_list) && all_can_get_permissions (window->details->target_files)) {
4822 GtkGrid *page_grid;
4823
4824 window->details->initial_permissions = get_initial_permissions (window->details->target_files);
4825 window->details->has_recursive_apply = files_has_changable_permissions_directory (window);
4826
4827 if (!all_can_set_permissions (file_list)) {
4828 add_prompt_and_separator (
4829 vbox,
4830 _("You are not the owner, so you cannot change these permissions.")dcgettext (((void*)0), "You are not the owner, so you cannot change these permissions."
, 5)
);
4831 }
4832
4833 page_grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
4834
4835 gtk_widget_show (GTK_WIDGET (page_grid)((((GtkWidget*) (void *) ((page_grid))))));
4836 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))),
4837 GTK_WIDGET (page_grid)((((GtkWidget*) (void *) ((page_grid))))),
4838 TRUE(!(0)), TRUE(!(0)), 0);
4839
4840 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_ADVANCED_PERMISSIONS"show-advanced-permissions")) {
4841 create_advanced_permissions (window, page_grid);
4842 } else {
4843 create_simple_permissions (window, page_grid);
4844 }
4845
4846 append_blank_slim_row (page_grid);
4847
4848#ifdef HAVE_SELINUX1
4849 append_title_value_pair
4850 (window, page_grid, _("SELinux context:")dcgettext (((void*)0), "SELinux context:", 5),
4851 "selinux_context", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4852 FALSE(0));
4853#endif
4854 append_title_value_pair
4855 (window, page_grid, _("Last changed:")dcgettext (((void*)0), "Last changed:", 5),
4856 "date_permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4857 FALSE(0));
4858
4859 if (window->details->has_recursive_apply) {
4860 GtkWidget *button, *hbox;
4861
4862 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4863 gtk_widget_show (hbox);
4864 gtk_container_add_with_properties (GTK_CONTAINER (page_grid)((((GtkContainer*) (void *) ((page_grid))))), hbox,
4865 "width", 2,
4866 NULL((void*)0));
4867
4868 button = gtk_button_new_with_mnemonic (_("Apply Permissions to Enclosed Files")dcgettext (((void*)0), "Apply Permissions to Enclosed Files",
5)
);
4869 gtk_widget_show (button);
4870 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
4871 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4872 G_CALLBACK (apply_recursive_clicked),g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4873 window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
;
4874 }
4875 } else {
4876 char *prompt_text;
4877
4878 if (!is_multi_file_window (window)) {
4879 char *file_name;
4880
4881 file_name = caja_file_get_display_name (get_target_file (window));
4882 prompt_text = g_strdup_printf (_("The permissions of \"%s\" could not be determined.")dcgettext (((void*)0), "The permissions of \"%s\" could not be determined."
, 5)
, file_name);
4883 g_free (file_name);
4884 } else {
4885 prompt_text = g_strdup (_("The permissions of the selected file could not be determined."))g_strdup_inline (dcgettext (((void*)0), "The permissions of the selected file could not be determined."
, 5))
;
4886 }
4887
4888 add_prompt (vbox, prompt_text, TRUE(!(0)));
4889 g_free (prompt_text);
4890 }
4891}
4892
4893static void
4894append_extension_pages (FMPropertiesWindow *window)
4895{
4896 GList *providers;
4897 GList *module_providers;
4898 GList *p;
4899
4900 providers = caja_extensions_get_for_type (CAJA_TYPE_PROPERTY_PAGE_PROVIDER(caja_property_page_provider_get_type ()));
4901
4902 /* FIXME: we also need the property pages from two old modules that
4903 * are not registered as proper extensions. This is going to work
4904 * this way until some generic solution is introduced.
4905 */
4906 module_providers = caja_module_get_extensions_for_type (CAJA_TYPE_PROPERTY_PAGE_PROVIDER(caja_property_page_provider_get_type ()));
4907 for (p = module_providers; p != NULL((void*)0); p = p->next) {
4908 const gchar *type_name = G_OBJECT_TYPE_NAME (G_OBJECT (p->data))(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (((((GObject
*) (void *) ((p->data)))))))->g_class))->g_type)))))
;
4909 if (g_strcmp0 (type_name, "CajaNotesViewerProvider") == 0 ||
4910 g_strcmp0 (type_name, "CajaImagePropertiesPageProvider") == 0) {
4911 providers = g_list_prepend (providers, p->data);
4912 }
4913 }
4914
4915 for (p = providers; p != NULL((void*)0); p = p->next) {
4916 CajaPropertyPageProvider *provider;
4917 GList *pages;
4918 GList *l;
4919
4920 provider = CAJA_PROPERTY_PAGE_PROVIDER (p->data)((((CajaPropertyPageProvider*) (void *) ((p->data)))));
4921
4922 pages = caja_property_page_provider_get_pages
4923 (provider, window->details->original_files);
4924
4925 for (l = pages; l != NULL((void*)0); l = l->next) {
4926 CajaPropertyPage *page;
4927 GtkWidget *page_widget;
4928 GtkWidget *label;
4929
4930 page = CAJA_PROPERTY_PAGE (l->data)((((CajaPropertyPage*) (void *) ((l->data)))));
4931
4932 g_object_get (G_OBJECT (page)((((GObject*) (void *) ((page))))),
4933 "page", &page_widget, "label", &label,
4934 NULL((void*)0));
4935
4936 gtk_notebook_append_page (window->details->notebook,
4937 page_widget, label);
4938
4939 g_object_set_data (G_OBJECT (page_widget)((((GObject*) (void *) ((page_widget))))),
4940 "is-extension-page",
4941 page);
4942
4943 g_object_unref (page_widget);
4944 g_object_unref (label);
4945
4946 g_object_unref (page);
4947 }
4948
4949 g_list_free (pages);
4950 }
4951
4952 caja_module_extension_list_free (providers);
4953}
4954
4955static gboolean
4956should_show_emblems (FMPropertiesWindow *window)
4957{
4958 /* FIXME bugzilla.gnome.org 45643:
4959 * Emblems aren't displayed on the the desktop Trash icon, so
4960 * we shouldn't pretend that they work by showing them here.
4961 * When bug 5643 is fixed we can remove this case.
4962 */
4963 if (!is_multi_file_window (window)
4964 && is_merged_trash_directory (get_target_file (window))) {
4965 return FALSE(0);
4966 }
4967
4968 return TRUE(!(0));
4969}
4970
4971static gboolean
4972should_show_permissions (FMPropertiesWindow *window)
4973{
4974 CajaFile *file;
4975
4976 file = get_target_file (window);
4977
4978 /* Don't show permissions for Trash and Computer since they're not
4979 * really file system objects.
4980 */
4981 if (!is_multi_file_window (window)
4982 && (is_merged_trash_directory (file) ||
4983 is_computer_directory (file))) {
4984 return FALSE(0);
4985 }
4986
4987 return TRUE(!(0));
4988}
4989
4990static char *
4991get_pending_key (GList *file_list)
4992{
4993 GList *l;
4994 GList *uris;
4995 GString *key;
4996 char *ret;
4997
4998 uris = NULL((void*)0);
4999 for (l = file_list; l != NULL((void*)0); l = l->next) {
5000 uris = g_list_prepend (uris, caja_file_get_uri (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))))));
5001 }
5002 uris = g_list_sort (uris, (GCompareFunc)strcmp);
5003
5004 key = g_string_new ("");
5005 for (l = uris; l != NULL((void*)0); l = l->next) {
5006 g_string_append (key, l->data)(__builtin_constant_p (l->data) ? __extension__ ({ const char
* const __val = (l->data); g_string_append_len_inline (key
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_363
; if (__val != ((void*)0)) _g_boolean_var_363 = 1; else _g_boolean_var_363
= 0; _g_boolean_var_363; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(key, l->data, (gssize) -1))
;
5007 g_string_append (key, ";")(__builtin_constant_p (";") ? __extension__ ({ const char * const
__val = (";"); g_string_append_len_inline (key, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_364; if (__val != ((void
*)0)) _g_boolean_var_364 = 1; else _g_boolean_var_364 = 0; _g_boolean_var_364
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (key, ";", (gssize) -1)
)
;
5008 }
5009
5010 g_list_free_full (uris, g_free);
5011
5012 ret = key->str;
5013 g_string_free (key, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((key)
, ((0))) : g_string_free_and_steal (key)) : (g_string_free) (
(key), ((0))))
;
5014
5015 return ret;
5016}
5017
5018static StartupData *
5019startup_data_new (GList *original_files,
5020 GList *target_files,
5021 const char *pending_key,
5022 GtkWidget *parent_widget)
5023{
5024 StartupData *data;
5025 GList *l;
5026
5027 data = g_new0 (StartupData, 1)(StartupData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (StartupData); 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; }))
;
5028 data->original_files = caja_file_list_copy (original_files);
5029 data->target_files = caja_file_list_copy (target_files);
5030 data->parent_widget = parent_widget;
5031 data->pending_key = g_strdup (pending_key)g_strdup_inline (pending_key);
5032 data->pending_files = g_hash_table_new (g_direct_hash,
5033 g_direct_equal);
5034
5035 for (l = data->target_files; l != NULL((void*)0); l = l->next) {
5036 g_hash_table_insert (data->pending_files, l->data, l->data);
5037 }
5038
5039 return data;
5040}
5041
5042static void
5043startup_data_free (StartupData *data)
5044{
5045 caja_file_list_free (data->original_files);
5046 caja_file_list_free (data->target_files);
5047 g_hash_table_destroy (data->pending_files);
5048 g_free (data->pending_key);
5049 g_free (data);
5050}
5051
5052static void
5053file_changed_callback (CajaFile *file, gpointer user_data)
5054{
5055 FMPropertiesWindow *window = FM_PROPERTIES_WINDOW (user_data)((((FMPropertiesWindow*) (void *) ((user_data)))));
5056
5057 if (!g_list_find (window->details->changed_files, file)) {
5058 caja_file_ref (file);
5059 window->details->changed_files = g_list_prepend (window->details->changed_files, file);
5060
5061 schedule_files_update (window);
5062 }
5063}
5064
5065static gboolean
5066is_a_special_file (CajaFile *file)
5067{
5068 if (file == NULL((void*)0) ||
5069 CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
||
5070 is_merged_trash_directory (file) ||
5071 is_computer_directory (file)) {
5072 return TRUE(!(0));
5073 }
5074 return FALSE(0);
5075}
5076
5077static gboolean
5078should_show_open_with (FMPropertiesWindow *window)
5079{
5080 CajaFile *file;
5081
5082 /* Don't show open with tab for desktop special icons (trash, etc)
5083 * We don't get the open-with menu for these anyway.
5084 *
5085 * Also don't show it for folders. Changing the default app for folders
5086 * leads to all sort of hard to understand errors.
5087 */
5088
5089 if (is_multi_file_window (window)) {
5090 if (!file_list_attributes_identical (window->details->original_files,
5091 "mime_type")) {
5092 return FALSE(0);
5093 } else {
5094
5095 GList *l;
5096
5097 for (l = window->details->original_files; l; l = l->next) {
5098 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5099 if (caja_file_is_directory (file) ||
5100 is_a_special_file (file)) {
5101 return FALSE(0);
5102 }
5103 }
5104 }
5105 } else {
5106 file = get_original_file (window);
5107 if (caja_file_is_directory (file) ||
5108 is_a_special_file (file)) {
5109 return FALSE(0);
5110 }
5111 }
5112 return TRUE(!(0));
5113}
5114
5115static void
5116create_open_with_page (FMPropertiesWindow *window)
5117{
5118 GtkWidget *vbox;
5119 char *mime_type;
5120
5121 mime_type = caja_file_get_mime_type (get_target_file (window));
5122
5123 if (!is_multi_file_window (window)) {
5124 char *uri;
5125
5126 uri = caja_file_get_uri (get_target_file (window));
5127
5128 if (uri == NULL((void*)0)) {
5129 return;
5130 }
5131
5132 vbox = caja_mime_application_chooser_new (uri, mime_type);
5133
5134 g_free (uri);
5135 } else {
5136 GList *uris;
5137
5138 uris = window->details->original_files;
5139 if (uris == NULL((void*)0)) {
5140 return;
5141 }
5142 vbox = caja_mime_application_chooser_new_for_multiple_files (uris, mime_type);
5143 }
5144
5145 gtk_widget_show (vbox);
5146 g_free (mime_type);
5147
5148 gtk_notebook_append_page (window->details->notebook,
5149 vbox, gtk_label_new (_("Open With")dcgettext (((void*)0), "Open With", 5)));
5150}
5151
5152
5153static FMPropertiesWindow *
5154create_properties_window (StartupData *startup_data)
5155{
5156 FMPropertiesWindow *window;
5157 GList *l;
5158 GtkWidget *action_area;
5159
5160 window = FM_PROPERTIES_WINDOW (gtk_widget_new (fm_properties_window_get_type (), NULL))((((FMPropertiesWindow*) (void *) ((gtk_widget_new (fm_properties_window_get_type
(), ((void*)0)))))))
;
5161
5162 window->details->original_files = caja_file_list_copy (startup_data->original_files);
5163
5164 window->details->target_files = caja_file_list_copy (startup_data->target_files);
5165
5166 gtk_window_set_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
5167 gtk_widget_get_screen (startup_data->parent_widget));
5168
5169 gtk_window_set_type_hint (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), GDK_WINDOW_TYPE_HINT_DIALOG);
5170
5171 /* Set initial window title */
5172 update_properties_window_title (window);
5173
5174 /* Start monitoring the file attributes we display. Note that some
5175 * of the attributes are for the original file, and some for the
5176 * target files.
5177 */
5178
5179 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5180 CajaFile *file;
5181 CajaFileAttributes attributes;
5182
5183 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5184
5185 attributes =
5186 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
|
5187 CAJA_FILE_ATTRIBUTE_INFO |
5188 CAJA_FILE_ATTRIBUTE_LINK_INFO;
5189
5190 caja_file_monitor_add (file,
5191 &window->details->original_files,
5192 attributes);
5193 }
5194
5195 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5196 CajaFile *file;
5197 CajaFileAttributes attributes;
5198
5199 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5200
5201 attributes = 0;
5202 if (caja_file_is_directory (file)) {
5203 attributes |= CAJA_FILE_ATTRIBUTE_DEEP_COUNTS;
5204 }
5205
5206 attributes |= CAJA_FILE_ATTRIBUTE_INFO;
5207 caja_file_monitor_add (file, &window->details->target_files, attributes);
5208 }
5209
5210 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5211 g_signal_connect_object (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5212 "changed",
5213 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5214 G_OBJECT (window)((((GObject*) (void *) ((window))))),
5215 0);
5216 }
5217
5218 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5219 g_signal_connect_object (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5220 "changed",
5221 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5222 G_OBJECT (window)((((GObject*) (void *) ((window))))),
5223 0);
5224 }
5225
5226 /* Create the notebook tabs. */
5227 window->details->notebook = GTK_NOTEBOOK (gtk_notebook_new ())((((GtkNotebook*) (void *) ((gtk_notebook_new ())))));
5228
5229 gtk_widget_add_events (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
, GDK_SCROLL_MASK);
5230 g_signal_connect (window->details->notebook,g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5231 "scroll-event",g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5232 G_CALLBACK (eel_notebook_scroll_event_cb),g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5233 NULL)g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
;
5234
5235 gtk_widget_show (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
);
5236 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((window)))))))))))
,
5237 GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
,
5238 TRUE(!(0)), TRUE(!(0)), 0);
5239
5240 /* Create the pages. */
5241 create_basic_page (window);
5242
5243 if (should_show_emblems (window)) {
5244 create_emblems_page (window);
5245 }
5246
5247 if (should_show_permissions (window)) {
5248 create_permissions_page (window);
5249 }
5250
5251 if (should_show_open_with (window)) {
5252 create_open_with_page (window);
5253 }
5254
5255 /* append pages from available views */
5256 append_extension_pages (window);
5257
5258 eel_dialog_add_button (GTK_DIALOG (window)((((GtkDialog*) (void *) ((window))))),
5259 _("_Help")dcgettext (((void*)0), "_Help", 5),
5260 "help-browser",
5261 GTK_RESPONSE_HELP);
5262
5263 action_area = gtk_widget_get_parent (eel_dialog_add_button (GTK_DIALOG (window)((((GtkDialog*) (void *) ((window))))),
5264 _("_Close")dcgettext (((void*)0), "_Close", 5),
5265 "window-close",
5266 GTK_RESPONSE_CLOSE));
5267
5268 /* FIXME - HIGificiation, should be done inside GTK+ */
5269 gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkContainer*) (void *) ((gtk_dialog_get_content_area (((
((GtkDialog*) (void *) ((window)))))))))))
, 12);
5270 gtk_container_set_border_width (GTK_CONTAINER (action_area)((((GtkContainer*) (void *) ((action_area))))), 0);
5271 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((window)))))))))))
, 12);
5272
5273 /* Update from initial state */
5274 properties_window_update (window, NULL((void*)0));
5275
5276 return window;
5277}
5278
5279static GList *
5280get_target_file_list (GList *original_files)
5281{
5282 GList *ret;
5283 GList *l;
5284
5285 ret = NULL((void*)0);
5286
5287 for (l = original_files; l != NULL((void*)0); l = l->next) {
5288 CajaFile *target;
5289
5290 target = get_target_file_for_original_file (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))));
5291
5292 ret = g_list_prepend (ret, target);
5293 }
5294
5295 ret = g_list_reverse (ret);
5296
5297 return ret;
5298}
5299
5300static void
5301add_window (FMPropertiesWindow *window)
5302{
5303 if (!is_multi_file_window (window)) {
5304 g_hash_table_insert (windows,
5305 get_original_file (window),
5306 window);
5307 g_object_set_data (G_OBJECT (window)((((GObject*) (void *) ((window))))), "window_key",
5308 get_original_file (window));
5309 }
5310}
5311
5312static void
5313remove_window (FMPropertiesWindow *window)
5314{
5315 gpointer key;
5316
5317 key = g_object_get_data (G_OBJECT (window)((((GObject*) (void *) ((window))))), "window_key");
5318 if (key) {
5319 g_hash_table_remove (windows, key);
5320 }
5321}
5322
5323static GtkWindow *
5324get_existing_window (GList *file_list)
5325{
5326 if (!file_list->next) {
5327 return g_hash_table_lookup (windows, file_list->data);
5328 }
5329
5330 return NULL((void*)0);
5331}
5332
5333static void
5334cancel_create_properties_window_callback (gpointer callback_data)
5335{
5336 remove_pending ((StartupData *)callback_data, TRUE(!(0)), FALSE(0), TRUE(!(0)));
5337}
5338
5339static void
5340parent_widget_destroyed_callback (GtkWidget *widget, gpointer callback_data)
5341{
5342 g_assert (widget == ((StartupData *)callback_data)->parent_widget)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_365
; if (widget == ((StartupData *)callback_data)->parent_widget
) _g_boolean_var_365 = 1; else _g_boolean_var_365 = 0; _g_boolean_var_365
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5342, ((const char*) (__func__)), "widget == ((StartupData *)callback_data)->parent_widget"
); } while (0)
;
5343
5344 remove_pending ((StartupData *)callback_data, TRUE(!(0)), TRUE(!(0)), FALSE(0));
5345}
5346
5347static void
5348cancel_call_when_ready_callback (gpointer key,
5349 gpointer value,
5350 gpointer user_data)
5351{
5352 caja_file_cancel_call_when_ready
5353 (CAJA_FILE (key)((((CajaFile*) (void *) ((key))))),
5354 is_directory_ready_callback,
5355 user_data);
5356}
5357
5358static void
5359remove_pending (StartupData *startup_data,
5360 gboolean cancel_call_when_ready,
5361 gboolean cancel_timed_wait,
5362 gboolean cancel_destroy_handler)
5363{
5364 if (cancel_call_when_ready) {
5365 g_hash_table_foreach (startup_data->pending_files,
5366 cancel_call_when_ready_callback,
5367 startup_data);
5368
5369 }
5370 if (cancel_timed_wait) {
5371 eel_timed_wait_stop
5372 (cancel_create_properties_window_callback, startup_data);
5373 }
5374 if (cancel_destroy_handler) {
5375 g_signal_handlers_disconnect_by_func (startup_data->parent_widget,g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5376 G_CALLBACK (parent_widget_destroyed_callback),g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5377 startup_data)g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
;
5378 }
5379
5380 g_hash_table_remove (pending_lists, startup_data->pending_key);
5381
5382 startup_data_free (startup_data);
5383}
5384
5385static void
5386is_directory_ready_callback (CajaFile *file,
5387 gpointer data)
5388{
5389 StartupData *startup_data;
5390
5391 startup_data = data;
5392
5393 g_hash_table_remove (startup_data->pending_files, file);
5394
5395 if (g_hash_table_size (startup_data->pending_files) == 0) {
5396 FMPropertiesWindow *new_window;
5397
5398 new_window = create_properties_window (startup_data);
5399
5400 add_window (new_window);
5401
5402 remove_pending (startup_data, FALSE(0), TRUE(!(0)), TRUE(!(0)));
5403
5404 gtk_window_present (GTK_WINDOW (new_window)((((GtkWindow*) (void *) ((new_window))))));
5405 }
5406}
5407
5408
5409void
5410fm_properties_window_present (GList *original_files,
5411 GtkWidget *parent_widget)
5412{
5413 GList *l, *next;
5414 GtkWidget *parent_window;
5415 StartupData *startup_data;
5416 GList *target_files;
5417 GtkWindow *existing_window;
5418 char *pending_key;
5419
5420 g_return_if_fail (original_files != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_366
; if (original_files != ((void*)0)) _g_boolean_var_366 = 1; else
_g_boolean_var_366 = 0; _g_boolean_var_366; }), 1))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "original_files != NULL"); return; } } while (0)
;
5421 g_return_if_fail (GTK_IS_WIDGET (parent_widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_367
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent_widget)); GType __t = ((gtk_widget_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_367 = 1; else _g_boolean_var_367 = 0; _g_boolean_var_367
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "GTK_IS_WIDGET (parent_widget)")
; return; } } while (0)
;
5422
5423 /* Create the hash tables first time through. */
5424 if (windows == NULL((void*)0)) {
5425 windows = eel_g_hash_table_new_free_at_exit
5426 (NULL((void*)0), NULL((void*)0), "property windows");
5427 }
5428
5429 if (pending_lists == NULL((void*)0)) {
5430 pending_lists = eel_g_hash_table_new_free_at_exit
5431 (g_str_hash, g_str_equal, "pending property window files");
5432 }
5433
5434 /* Look to see if there's already a window for this file. */
5435 existing_window = get_existing_window (original_files);
5436 if (existing_window != NULL((void*)0)) {
5437 gtk_window_set_screen (existing_window,
5438 gtk_widget_get_screen (parent_widget));
5439 gtk_window_present (existing_window);
5440 return;
5441 }
5442
5443
5444 pending_key = get_pending_key (original_files);
5445
5446 /* Look to see if we're already waiting for a window for this file. */
5447 if (g_hash_table_lookup (pending_lists, pending_key) != NULL((void*)0)) {
5448 return;
5449 }
5450
5451 target_files = get_target_file_list (original_files);
5452
5453 startup_data = startup_data_new (original_files,
5454 target_files,
5455 pending_key,
5456 parent_widget);
5457
5458 caja_file_list_free (target_files);
5459 g_free(pending_key);
5460
5461 /* Wait until we can tell whether it's a directory before showing, since
5462 * some one-time layout decisions depend on that info.
5463 */
5464
5465 g_hash_table_insert (pending_lists, startup_data->pending_key, startup_data->pending_key);
5466 g_signal_connect (parent_widget, "destroy",g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
5467 G_CALLBACK (parent_widget_destroyed_callback), startup_data)g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
;
5468
5469 parent_window = gtk_widget_get_ancestor (parent_widget, GTK_TYPE_WINDOW(gtk_window_get_type ()));
5470
5471 eel_timed_wait_start
5472 (cancel_create_properties_window_callback,
5473 startup_data,
5474 _("Creating Properties window.")dcgettext (((void*)0), "Creating Properties window.", 5),
5475 parent_window == NULL((void*)0) ? NULL((void*)0) : GTK_WINDOW (parent_window)((((GtkWindow*) (void *) ((parent_window))))));
5476
5477
5478 for (l = startup_data->target_files; l != NULL((void*)0); l = next) {
5479 next = l->next;
5480 caja_file_call_when_ready
5481 (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5482 CAJA_FILE_ATTRIBUTE_INFO,
5483 is_directory_ready_callback,
5484 startup_data);
5485 }
5486}
5487
5488static void
5489real_response (GtkDialog *dialog,
5490 int response)
5491{
5492 GError *error = NULL((void*)0);
5493
5494 switch (response) {
5495 case GTK_RESPONSE_HELP:
5496 gtk_show_uri_on_window (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))),
5497 "help:mate-user-guide/goscaja-51",
5498 gtk_get_current_event_time (),
5499 &error);
5500 if (error != NULL((void*)0)) {
5501 eel_show_error_dialog (_("There was an error displaying help.")dcgettext (((void*)0), "There was an error displaying help.",
5)
, error->message,
5502 GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))));
5503 g_error_free (error);
5504 }
5505 break;
5506
5507 case GTK_RESPONSE_NONE:
5508 case GTK_RESPONSE_CLOSE:
5509 case GTK_RESPONSE_DELETE_EVENT:
5510 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
5511 break;
5512
5513 default:
5514 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5514, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5515 break;
5516 }
5517}
5518
5519static void
5520real_destroy (GtkWidget *object)
5521{
5522 FMPropertiesWindow *window;
5523 GList *l;
5524
5525 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) ((object)))));
5526
5527 remove_window (window);
5528
5529 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5530 caja_file_monitor_remove (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))), &window->details->original_files);
5531 }
5532 caja_file_list_free (window->details->original_files);
5533 window->details->original_files = NULL((void*)0);
5534
5535 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5536 caja_file_monitor_remove (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))), &window->details->target_files);
5537 }
5538 caja_file_list_free (window->details->target_files);
5539 window->details->target_files = NULL((void*)0);
5540
5541 caja_file_list_free (window->details->changed_files);
5542 window->details->changed_files = NULL((void*)0);
5543
5544 window->details->name_field = NULL((void*)0);
5545
5546 g_list_free (window->details->emblem_buttons);
5547 window->details->emblem_buttons = NULL((void*)0);
5548
5549 if (window->details->initial_emblems) {
5550 g_hash_table_destroy (window->details->initial_emblems);
5551 window->details->initial_emblems = NULL((void*)0);
5552 }
5553
5554 g_list_free (window->details->permission_buttons);
5555 window->details->permission_buttons = NULL((void*)0);
5556
5557 g_list_free (window->details->permission_combos);
5558 window->details->permission_combos = NULL((void*)0);
5559
5560 if (window->details->initial_permissions) {
5561 g_hash_table_destroy (window->details->initial_permissions);
5562 window->details->initial_permissions = NULL((void*)0);
5563 }
5564
5565 g_list_free (window->details->value_fields);
5566 window->details->value_fields = NULL((void*)0);
5567
5568 if (window->details->update_directory_contents_timeout_id != 0) {
5569 g_source_remove (window->details->update_directory_contents_timeout_id);
5570 window->details->update_directory_contents_timeout_id = 0;
5571 }
5572
5573 if (window->details->update_files_timeout_id != 0) {
5574 g_source_remove (window->details->update_files_timeout_id);
5575 window->details->update_files_timeout_id = 0;
5576 }
5577
5578 GTK_WIDGET_CLASS (fm_properties_window_parent_class)((((GtkWidgetClass*) (void *) ((fm_properties_window_parent_class
)))))
->destroy (object);
5579}
5580
5581static void
5582real_finalize (GObject *object)
5583{
5584 FMPropertiesWindow *window;
5585
5586 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) ((object)))));
5587
5588 g_list_free_full (window->details->mime_list, g_free);
5589
5590 g_free (window->details->pending_name);
5591
5592 G_OBJECT_CLASS (fm_properties_window_parent_class)((((GObjectClass*) (void *) ((fm_properties_window_parent_class
)))))
->finalize (object);
5593}
5594
5595/* converts
5596 * file://foo/foobar/foofoo/bar
5597 * to
5598 * foofoo/bar
5599 * if
5600 * file://foo/foobar
5601 * is the parent
5602 *
5603 * It does not resolve any symlinks.
5604 * */
5605static char *
5606make_relative_uri_from_full (const char *uri,
5607 const char *base_uri)
5608{
5609 g_assert (uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_368
; if (uri != ((void*)0)) _g_boolean_var_368 = 1; else _g_boolean_var_368
= 0; _g_boolean_var_368; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5609, ((const char*
) (__func__)), "uri != NULL"); } while (0)
;
5610 g_assert (base_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_369
; if (base_uri != ((void*)0)) _g_boolean_var_369 = 1; else _g_boolean_var_369
= 0; _g_boolean_var_369; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5610, ((const char*
) (__func__)), "base_uri != NULL"); } while (0)
;
5611
5612 if (g_str_has_prefix (uri, base_uri)(__builtin_constant_p (base_uri)? __extension__ ({ const char
* const __str = (uri); const char * const __prefix = (base_uri
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_370; if (__str == ((void*)0) || __prefix
== ((void*)0)) _g_boolean_var_370 = 1; else _g_boolean_var_370
= 0; _g_boolean_var_370; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (uri, base_uri) )
) {
5613 uri += strlen (base_uri);
5614 if (*uri != '/') {
5615 return NULL((void*)0);
5616 }
5617
5618 while (*uri == '/') {
5619 uri++;
5620 }
5621
5622 if (*uri != '\0') {
5623 return g_strdup (uri)g_strdup_inline (uri);
5624 }
5625 }
5626
5627 return NULL((void*)0);
5628}
5629
5630/* icon selection callback to set the image of the file object to the selected file */
5631static void
5632set_icon (const char* icon_uri, FMPropertiesWindow *properties_window)
5633{
5634 char *icon_path;
5635
5636 g_assert (icon_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_371
; if (icon_uri != ((void*)0)) _g_boolean_var_371 = 1; else _g_boolean_var_371
= 0; _g_boolean_var_371; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5636, ((const char*
) (__func__)), "icon_uri != NULL"); } while (0)
;
5637 g_assert (FM_IS_PROPERTIES_WINDOW (properties_window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_372
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((properties_window)); GType __t = (fm_properties_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_372 = 1; else _g_boolean_var_372 =
0; _g_boolean_var_372; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5637, ((const char*
) (__func__)), "FM_IS_PROPERTIES_WINDOW (properties_window)")
; } while (0)
;
5638
5639 icon_path = g_filename_from_uri (icon_uri, NULL((void*)0), NULL((void*)0));
5640 /* we don't allow remote URIs */
5641 if (icon_path != NULL((void*)0)) {
5642 GList *l;
5643 CajaFile *file = NULL((void*)0);
5644
5645 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
5646 char *file_uri;
5647
5648 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5649
5650 file_uri = caja_file_get_uri (file);
5651
5652 if (caja_file_is_mime_type (file, "application/x-desktop")) {
5653 if (caja_link_local_set_icon (file_uri, icon_path)) {
5654 caja_file_invalidate_attributes (file,
5655 CAJA_FILE_ATTRIBUTE_INFO |
5656 CAJA_FILE_ATTRIBUTE_LINK_INFO);
5657 }
5658 } else {
5659 char *real_icon_uri;
5660
5661 real_icon_uri = make_relative_uri_from_full (icon_uri, file_uri);
5662
5663 if (real_icon_uri == NULL((void*)0)) {
5664 real_icon_uri = g_strdup (icon_uri)g_strdup_inline (icon_uri);
5665 }
5666
5667 caja_file_set_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0), real_icon_uri);
5668 caja_file_set_metadata (file, CAJA_METADATA_KEY_ICON_SCALE"icon-scale", NULL((void*)0), NULL((void*)0));
5669
5670 g_free (real_icon_uri);
5671 }
5672
5673 g_free (file_uri);
5674 }
5675
5676 g_free (icon_path);
5677 }
5678}
5679
5680static void
5681update_preview_callback (GtkFileChooser *icon_chooser,
5682 FMPropertiesWindow *window)
5683{
5684 GdkPixbuf *pixbuf, *scaled_pixbuf;
5685 char *filename;
5686
5687 pixbuf = NULL((void*)0);
5688
5689 filename = gtk_file_chooser_get_filename (icon_chooser);
5690 if (filename != NULL((void*)0)) {
5691 pixbuf = gdk_pixbuf_new_from_file (filename, NULL((void*)0));
5692 }
5693
5694 if (pixbuf != NULL((void*)0)) {
5695 GtkWidget *preview_widget;
5696
5697 preview_widget = gtk_file_chooser_get_preview_widget (icon_chooser);
5698 gtk_file_chooser_set_preview_widget_active (icon_chooser, TRUE(!(0)));
5699
5700 if (gdk_pixbuf_get_width (pixbuf) > PREVIEW_IMAGE_WIDTH96) {
5701 double scale;
5702
5703 scale = (double)gdk_pixbuf_get_height (pixbuf) /
5704 gdk_pixbuf_get_width (pixbuf);
5705
5706 scaled_pixbuf = gdk_pixbuf_scale_simple
5707 (pixbuf,
5708 PREVIEW_IMAGE_WIDTH96,
5709 scale * PREVIEW_IMAGE_WIDTH96,
5710 GDK_INTERP_HYPER);
5711 g_object_unref (pixbuf);
5712 pixbuf = scaled_pixbuf;
5713 }
5714
5715 gtk_image_set_from_pixbuf (GTK_IMAGE (preview_widget)((((GtkImage*) (void *) ((preview_widget))))), pixbuf);
5716 } else {
5717 gtk_file_chooser_set_preview_widget_active (icon_chooser, FALSE(0));
5718 }
5719
5720 g_free (filename);
5721
5722 if (pixbuf != NULL((void*)0)) {
5723 g_object_unref (pixbuf);
5724 }
5725}
5726
5727static void
5728custom_icon_file_chooser_response_cb (GtkDialog *dialog,
5729 gint response,
5730 FMPropertiesWindow *window)
5731{
5732 char *uri;
5733
5734 switch (response) {
5735 case GTK_RESPONSE_NO:
5736 reset_icon (window);
5737 break;
5738
5739 case GTK_RESPONSE_OK:
5740 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))));
5741 set_icon (uri, window);
5742 g_free (uri);
5743 break;
5744
5745 default:
5746 break;
5747 }
5748
5749 gtk_widget_hide (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
5750}
5751
5752static void
5753select_image_button_callback (GtkWidget *widget,
5754 FMPropertiesWindow *window)
5755{
5756 GtkWidget *dialog;
5757 GList *l;
5758 CajaFile *file;
5759 char *image_path;
5760 gboolean revert_is_sensitive;
5761
5762 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_373
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_373 = 1; else _g_boolean_var_373 = 0; _g_boolean_var_373
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5762, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
5763
5764 dialog = window->details->icon_chooser;
5765
5766 if (dialog == NULL((void*)0)) {
5767 GtkWidget *preview;
5768 GtkFileFilter *filter;
5769
5770 dialog = eel_file_chooser_dialog_new (_("Select Custom Icon")dcgettext (((void*)0), "Select Custom Icon", 5), GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
5771 GTK_FILE_CHOOSER_ACTION_OPEN,
5772 "document-revert", GTK_RESPONSE_NO,
5773 "process-stop", GTK_RESPONSE_CANCEL,
5774 "document-open", GTK_RESPONSE_OK,
5775 NULL((void*)0));
5776 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), ICONDIR"/usr/local/share/icons", NULL((void*)0));
5777 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), PIXMAPDIR"/usr/local/share/pixmaps", NULL((void*)0));
5778 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
5779
5780 filter = gtk_file_filter_new ();
5781 gtk_file_filter_add_pixbuf_formats (filter);
5782 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), filter);
5783
5784 preview = gtk_image_new ();
5785 gtk_widget_set_size_request (preview, PREVIEW_IMAGE_WIDTH96, -1);
5786 gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), preview);
5787 gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), FALSE(0));
5788 gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), FALSE(0));
5789
5790 g_signal_connect (dialog, "update-preview",g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
5791 G_CALLBACK (update_preview_callback), window)g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
5792
5793 window->details->icon_chooser = dialog;
5794
5795 g_object_add_weak_pointer (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))),
5796 (gpointer *) &window->details->icon_chooser);
5797 }
5798
5799 /* it's likely that the user wants to pick an icon that is inside a local directory */
5800 if (g_list_length (window->details->original_files) == 1) {
5801 file = CAJA_FILE (window->details->original_files->data)((((CajaFile*) (void *) ((window->details->original_files
->data)))))
;
5802
5803 if (caja_file_is_directory (file)) {
5804 char *uri;
5805
5806 uri = caja_file_get_uri (file);
5807
5808 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
5809 if (image_path != NULL((void*)0)) {
5810 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), image_path);
5811 g_free (image_path);
5812 }
5813
5814 g_free (uri);
5815 }
5816 }
5817
5818 revert_is_sensitive = FALSE(0);
5819 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5820 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5821 image_path = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
5822 revert_is_sensitive = (image_path != NULL((void*)0));
5823 g_free (image_path);
5824
5825 if (revert_is_sensitive) {
5826 break;
5827 }
5828 }
5829 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_NO, revert_is_sensitive);
5830
5831 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
5832 G_CALLBACK (custom_icon_file_chooser_response_cb), window)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
;
5833 gtk_widget_show (dialog);
5834}
5835
5836static void
5837fm_properties_window_class_init (FMPropertiesWindowClass *class)
5838{
5839 GtkBindingSet *binding_set;
5840
5841 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = real_finalize;
5842
5843 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->destroy = real_destroy;
5844
5845 GTK_DIALOG_CLASS (class)((((GtkDialogClass*) (void *) ((class)))))->response = real_response;
5846
5847 binding_set = gtk_binding_set_by_class (class);
5848 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape0xff1b, 0,
5849 "close", 0);
5850}
5851
5852static void
5853fm_properties_window_init (FMPropertiesWindow *window)
5854{
5855 window->details = fm_properties_window_get_instance_private (window);
5856}
diff --git a/2024-07-29-023715-6438-1/report-891289.html b/2024-07-29-023715-6438-1/report-891289.html new file mode 100644 index 000000000..7e4f0ef85 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-891289.html @@ -0,0 +1,1542 @@ + + + +/rootdir/libcaja-extension/tmp-introspect70zjnr57/Caja-2.0.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-extension/tmp-introspect70zjnr57/Caja-2.0.c
Warning:line 799, column 27
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'error')
+ +

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 Caja-2.0.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 -fdebug-compilation-dir=/rootdir/libcaja-extension -fcoverage-compilation-dir=/rootdir/libcaja-extension -resource-dir /usr/bin/../lib/clang/18 -D WITH_GZFILEOP -D WITH_GZFILEOP -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/freetype2 -I /usr/include/cairo -I /usr/include/atk-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/gio-unix-2.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /rootdir -I /rootdir -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/freetype2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/gio-unix-2.0 -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-deprecated-declarations -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c /rootdir/libcaja-extension/tmp-introspect70zjnr57/Caja-2.0.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* This file is generated, do not edit */
2
3#undef GLIB_VERSION_MIN_REQUIRED((((2) << 16 | (80) << 8)))
4#undef GLIB_VERSION_MAX_ALLOWED((((2) << 16 | (80) << 8)))
5
6#include <glib.h>
7#include <string.h>
8#include <stdlib.h>
9
10/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
11 * GObject introspection: Dump introspection data
12 *
13 * Copyright (C) 2008 Colin Walters <walters@verbum.org>
14 *
15 * SPDX-License-Identifier: LGPL-2.1-or-later
16 *
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2 of the License, or (at your option) any later version.
21 *
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with this library; if not, write to the
29 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 * Boston, MA 02111-1307, USA.
31 */
32
33/* This file is both compiled into libgirepository.so, and installed
34 * on the filesystem. But for the dumper, we want to avoid linking
35 * to libgirepository; see
36 * https://bugzilla.gnome.org/show_bug.cgi?id=630342
37 */
38#ifdef G_IREPOSITORY_COMPILATION
39#include "config.h"
40#include "girepository.h"
41#endif
42
43#include <glib.h>
44#include <glib-object.h>
45#include <gmodule.h>
46
47#include <stdlib.h>
48#include <stdio.h>
49#include <string.h>
50
51/* Analogue of g_output_stream_write_all(). */
52static gboolean
53write_all (FILE *out,
54 const void *buffer,
55 gsize count,
56 gsize *bytes_written,
57 GError **error)
58{
59 size_t ret;
60
61 ret = fwrite (buffer, 1, count, out);
62
63 if (bytes_written != NULL((void*)0))
64 *bytes_written = ret;
65
66 if (ret < count)
67 {
68 g_set_error (error, G_FILE_ERRORg_file_error_quark (), G_FILE_ERROR_FAILED,
69 "Failed to write to file");
70 return FALSE(0);
71 }
72
73 return TRUE(!(0));
74}
75
76/* Analogue of g_data_input_stream_read_line(). */
77static char *
78read_line (FILE *input,
79 size_t *len_out)
80{
81 GByteArray *buffer = g_byte_array_new ();
82 const guint8 nul = '\0';
83
84 while (TRUE(!(0)))
85 {
86 size_t ret;
87 guint8 byte;
88
89 ret = fread (&byte, 1, 1, input);
90 if (ret == 0)
91 break;
92
93 if (byte == '\n')
94 break;
95
96 g_byte_array_append (buffer, &byte, 1);
97 }
98
99 g_byte_array_append (buffer, &nul, 1);
100
101 if (len_out != NULL((void*)0))
102 *len_out = buffer->len - 1; /* don’t include terminating nul */
103
104 return (char *) g_byte_array_free (buffer, FALSE(0));
105}
106
107static void
108escaped_printf (FILE *out, const char *fmt, ...) G_GNUC_PRINTF (2, 3)__attribute__((__format__ (__printf__, 2, 3)));
109
110static void
111escaped_printf (FILE *out, const char *fmt, ...)
112{
113 char *str;
114 va_list args;
115 gsize written;
116 GError *error = NULL((void*)0);
117
118 va_start (args, fmt)__builtin_va_start(args, fmt);
119
120 str = g_markup_vprintf_escaped (fmt, args);
121 if (!write_all (out, str, strlen (str), &written, &error))
122 {
123 g_critical ("failed to write to iochannel: %s", error->message);
124 g_clear_error (&error);
125 }
126 g_free (str);
127
128 va_end (args)__builtin_va_end(args);
129}
130
131static void
132goutput_write (FILE *out, const char *str)
133{
134 gsize written;
135 GError *error = NULL((void*)0);
136 if (!write_all (out, str, strlen (str), &written, &error))
137 {
138 g_critical ("failed to write to iochannel: %s", error->message);
139 g_clear_error (&error);
140 }
141}
142
143typedef GType (*GetTypeFunc)(void);
144typedef GQuark (*ErrorQuarkFunc)(void);
145
146static GType
147invoke_get_type (GModule *self, const char *symbol, GError **error)
148{
149 GetTypeFunc sym;
150 GType ret;
151
152 if (!g_module_symbol (self, symbol, (void**)&sym))
153 {
154 g_set_error (error,
155 G_FILE_ERRORg_file_error_quark (),
156 G_FILE_ERROR_FAILED,
157 "Failed to find symbol '%s'", symbol);
158 return G_TYPE_INVALID((GType) ((0) << (2)));
159 }
160
161 ret = sym ();
162 if (ret == G_TYPE_INVALID((GType) ((0) << (2))))
163 {
164 g_set_error (error,
165 G_FILE_ERRORg_file_error_quark (),
166 G_FILE_ERROR_FAILED,
167 "Function '%s' returned G_TYPE_INVALID", symbol);
168 }
169 return ret;
170}
171
172static GQuark
173invoke_error_quark (GModule *self, const char *symbol, GError **error)
174{
175 ErrorQuarkFunc sym;
176
177 if (!g_module_symbol (self, symbol, (void**)&sym))
178 {
179 g_set_error (error,
180 G_FILE_ERRORg_file_error_quark (),
181 G_FILE_ERROR_FAILED,
182 "Failed to find symbol '%s'", symbol);
183 return G_TYPE_INVALID((GType) ((0) << (2)));
184 }
185
186 return sym ();
187}
188
189static char *
190value_transform_to_string (const GValue *value)
191{
192 GValue tmp = G_VALUE_INIT{ 0, { { 0 } } };
193 char *s = NULL((void*)0);
194
195 g_value_init (&tmp, G_TYPE_STRING((GType) ((16) << (2))));
196
197 if (g_value_transform (value, &tmp))
198 {
199 const char *str = g_value_get_string (&tmp);
200
201 if (str != NULL((void*)0))
202 s = g_strescape (str, NULL((void*)0));
203 }
204
205 g_value_unset (&tmp);
206
207 return s;
208}
209
210/* A simpler version of g_strdup_value_contents(), but with stable
211 * output and less complex semantics
212 */
213static char *
214value_to_string (const GValue *value)
215{
216 if (value == NULL((void*)0))
217 return NULL((void*)0);
218
219 if (G_VALUE_HOLDS_STRING (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((GType) ((16) << (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
; }))))
)
220 {
221 const char *s = g_value_get_string (value);
222
223 if (s == NULL((void*)0))
224 return g_strdup ("NULL")g_strdup_inline ("NULL");
225
226 return g_strescape (s, NULL((void*)0));
227 }
228 else
229 {
230 GType value_type = G_VALUE_TYPE (value)(((GValue*) (value))->g_type);
231
232 switch (G_TYPE_FUNDAMENTAL (value_type)(g_type_fundamental (value_type)))
233 {
234 case G_TYPE_BOXED((GType) ((18) << (2))):
235 if (g_value_get_boxed (value) == NULL((void*)0))
236 return NULL((void*)0);
237 else
238 return value_transform_to_string (value);
239 break;
240
241 case G_TYPE_OBJECT((GType) ((20) << (2))):
242 if (g_value_get_object (value) == NULL((void*)0))
243 return NULL((void*)0);
244 else
245 return value_transform_to_string (value);
246 break;
247
248 case G_TYPE_POINTER((GType) ((17) << (2))):
249 return NULL((void*)0);
250
251 default:
252 return value_transform_to_string (value);
253 }
254 }
255
256 return NULL((void*)0);
257}
258
259static void
260dump_properties (GType type, FILE *out)
261{
262 guint i;
263 guint n_properties = 0;
264 GParamSpec **props;
265
266 if (G_TYPE_FUNDAMENTAL (type)(g_type_fundamental (type)) == G_TYPE_OBJECT((GType) ((20) << (2))))
267 {
268 GObjectClass *klass;
269 klass = g_type_class_ref (type);
270 props = g_object_class_list_properties (klass, &n_properties);
271 }
272 else
273 {
274 void *klass;
275 klass = g_type_default_interface_ref (type);
276 props = g_object_interface_list_properties (klass, &n_properties);
277 }
278
279 for (i = 0; i < n_properties; i++)
280 {
281 GParamSpec *prop;
282
283 prop = props[i];
284 if (prop->owner_type != type)
285 continue;
286
287 const GValue *v = g_param_spec_get_default_value (prop);
288 char *default_value = value_to_string (v);
289
290 if (v != NULL((void*)0) && default_value != NULL((void*)0))
291 {
292 escaped_printf (out, " <property name=\"%s\" type=\"%s\" flags=\"%d\" default-value=\"%s\"/>\n",
293 prop->name,
294 g_type_name (prop->value_type),
295 prop->flags,
296 default_value);
297 }
298 else
299 {
300 escaped_printf (out, " <property name=\"%s\" type=\"%s\" flags=\"%d\"/>\n",
301 prop->name,
302 g_type_name (prop->value_type),
303 prop->flags);
304 }
305
306 g_free (default_value);
307 }
308
309 g_free (props);
310}
311
312static void
313dump_signals (GType type, FILE *out)
314{
315 guint i;
316 guint n_sigs;
317 guint *sig_ids;
318
319 sig_ids = g_signal_list_ids (type, &n_sigs);
320 for (i = 0; i < n_sigs; i++)
321 {
322 guint sigid;
323 GSignalQuery query;
324 guint j;
325
326 sigid = sig_ids[i];
327 g_signal_query (sigid, &query);
328
329 escaped_printf (out, " <signal name=\"%s\" return=\"%s\"",
330 query.signal_name, g_type_name (query.return_type));
331
332 if (query.signal_flags & G_SIGNAL_RUN_FIRST)
333 escaped_printf (out, " when=\"first\"");
334 else if (query.signal_flags & G_SIGNAL_RUN_LAST)
335 escaped_printf (out, " when=\"last\"");
336 else if (query.signal_flags & G_SIGNAL_RUN_CLEANUP)
337 escaped_printf (out, " when=\"cleanup\"");
338 else if (query.signal_flags & G_SIGNAL_MUST_COLLECT)
339 escaped_printf (out, " when=\"must-collect\"");
340 if (query.signal_flags & G_SIGNAL_NO_RECURSE)
341 escaped_printf (out, " no-recurse=\"1\"");
342
343 if (query.signal_flags & G_SIGNAL_DETAILED)
344 escaped_printf (out, " detailed=\"1\"");
345
346 if (query.signal_flags & G_SIGNAL_ACTION)
347 escaped_printf (out, " action=\"1\"");
348
349 if (query.signal_flags & G_SIGNAL_NO_HOOKS)
350 escaped_printf (out, " no-hooks=\"1\"");
351
352 goutput_write (out, ">\n");
353
354 for (j = 0; j < query.n_params; j++)
355 {
356 escaped_printf (out, " <param type=\"%s\"/>\n",
357 g_type_name (query.param_types[j]));
358 }
359 goutput_write (out, " </signal>\n");
360 }
361 g_free (sig_ids);
362}
363
364static void
365dump_object_type (GType type, const char *symbol, FILE *out)
366{
367 guint n_interfaces;
368 guint i;
369 GType *interfaces;
370
371 escaped_printf (out, " <class name=\"%s\" get-type=\"%s\"",
372 g_type_name (type), symbol);
373 if (type != G_TYPE_OBJECT((GType) ((20) << (2))))
374 {
375 GString *parent_str;
376 GType parent;
377 gboolean first = TRUE(!(0));
378
379 parent = g_type_parent (type);
380 parent_str = g_string_new ("");
381 while (parent != G_TYPE_INVALID((GType) ((0) << (2))))
382 {
383 if (first)
384 first = FALSE(0);
385 else
386 g_string_append_c (parent_str, ',')g_string_append_c_inline (parent_str, ',');
387 g_string_append (parent_str, g_type_name (parent))(__builtin_constant_p (g_type_name (parent)) ? __extension__ (
{ const char * const __val = (g_type_name (parent)); g_string_append_len_inline
(parent_str, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (__val != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
parent_str, g_type_name (parent), (gssize) -1))
;
388 parent = g_type_parent (parent);
389 }
390
391 escaped_printf (out, " parents=\"%s\"", parent_str->str);
392
393 g_string_free (parent_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(parent_str), ((!(0)))) : g_string_free_and_steal (parent_str
)) : (g_string_free) ((parent_str), ((!(0)))))
;
394 }
395
396 if (G_TYPE_IS_ABSTRACT (type)(g_type_test_flags ((type), G_TYPE_FLAG_ABSTRACT)))
397 escaped_printf (out, " abstract=\"1\"");
398
399 if (G_TYPE_IS_FINAL (type)(g_type_test_flags ((type), G_TYPE_FLAG_FINAL)))
400 escaped_printf (out, " final=\"1\"");
401
402 goutput_write (out, ">\n");
403
404 interfaces = g_type_interfaces (type, &n_interfaces);
405 for (i = 0; i < n_interfaces; i++)
406 {
407 GType itype = interfaces[i];
408 escaped_printf (out, " <implements name=\"%s\"/>\n",
409 g_type_name (itype));
410 }
411 g_free (interfaces);
412
413 dump_properties (type, out);
414 dump_signals (type, out);
415 goutput_write (out, " </class>\n");
416}
417
418static void
419dump_interface_type (GType type, const char *symbol, FILE *out)
420{
421 guint n_interfaces;
422 guint i;
423 GType *interfaces;
424
425 escaped_printf (out, " <interface name=\"%s\" get-type=\"%s\">\n",
426 g_type_name (type), symbol);
427
428 interfaces = g_type_interface_prerequisites (type, &n_interfaces);
429 for (i = 0; i < n_interfaces; i++)
430 {
431 GType itype = interfaces[i];
432 if (itype == G_TYPE_OBJECT((GType) ((20) << (2))))
433 {
434 /* Treat this as implicit for now; in theory GInterfaces are
435 * supported on things like GstMiniObject, but right now
436 * the introspection system only supports GObject.
437 * http://bugzilla.gnome.org/show_bug.cgi?id=559706
438 */
439 continue;
440 }
441 escaped_printf (out, " <prerequisite name=\"%s\"/>\n",
442 g_type_name (itype));
443 }
444 g_free (interfaces);
445
446 dump_properties (type, out);
447 dump_signals (type, out);
448 goutput_write (out, " </interface>\n");
449}
450
451static void
452dump_boxed_type (GType type, const char *symbol, FILE *out)
453{
454 escaped_printf (out, " <boxed name=\"%s\" get-type=\"%s\"/>\n",
455 g_type_name (type), symbol);
456}
457
458static void
459dump_flags_type (GType type, const char *symbol, FILE *out)
460{
461 guint i;
462 GFlagsClass *klass;
463
464 klass = g_type_class_ref (type);
465 escaped_printf (out, " <flags name=\"%s\" get-type=\"%s\">\n",
466 g_type_name (type), symbol);
467
468 for (i = 0; i < klass->n_values; i++)
469 {
470 GFlagsValue *value = &(klass->values[i]);
471
472 escaped_printf (out, " <member name=\"%s\" nick=\"%s\" value=\"%u\"/>\n",
473 value->value_name, value->value_nick, value->value);
474 }
475 goutput_write (out, " </flags>\n");
476}
477
478static void
479dump_enum_type (GType type, const char *symbol, FILE *out)
480{
481 guint i;
482 GEnumClass *klass;
483
484 klass = g_type_class_ref (type);
485 escaped_printf (out, " <enum name=\"%s\" get-type=\"%s\">\n",
486 g_type_name (type), symbol);
487
488 for (i = 0; i < klass->n_values; i++)
489 {
490 GEnumValue *value = &(klass->values[i]);
491
492 escaped_printf (out, " <member name=\"%s\" nick=\"%s\" value=\"%d\"/>\n",
493 value->value_name, value->value_nick, value->value);
494 }
495 goutput_write (out, " </enum>");
496}
497
498static void
499dump_fundamental_type (GType type, const char *symbol, FILE *out)
500{
501 guint n_interfaces;
502 guint i;
503 GType *interfaces;
504 GString *parent_str;
505 GType parent;
506 gboolean first = TRUE(!(0));
507
508
509 escaped_printf (out, " <fundamental name=\"%s\" get-type=\"%s\"",
510 g_type_name (type), symbol);
511
512 if (G_TYPE_IS_ABSTRACT (type)(g_type_test_flags ((type), G_TYPE_FLAG_ABSTRACT)))
513 escaped_printf (out, " abstract=\"1\"");
514
515 if (G_TYPE_IS_FINAL (type)(g_type_test_flags ((type), G_TYPE_FLAG_FINAL)))
516 escaped_printf (out, " final=\"1\"");
517
518 if (G_TYPE_IS_INSTANTIATABLE (type)(g_type_test_flags ((type), G_TYPE_FLAG_INSTANTIATABLE)))
519 escaped_printf (out, " instantiatable=\"1\"");
520
521 parent = g_type_parent (type);
522 parent_str = g_string_new ("");
523 while (parent != G_TYPE_INVALID((GType) ((0) << (2))))
524 {
525 if (first)
526 first = FALSE(0);
527 else
528 g_string_append_c (parent_str, ',')g_string_append_c_inline (parent_str, ',');
529 if (!g_type_name (parent))
530 break;
531 g_string_append (parent_str, g_type_name (parent))(__builtin_constant_p (g_type_name (parent)) ? __extension__ (
{ const char * const __val = (g_type_name (parent)); g_string_append_len_inline
(parent_str, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (__val != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
parent_str, g_type_name (parent), (gssize) -1))
;
532 parent = g_type_parent (parent);
533 }
534
535 if (parent_str->len > 0)
536 escaped_printf (out, " parents=\"%s\"", parent_str->str);
537 g_string_free (parent_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(parent_str), ((!(0)))) : g_string_free_and_steal (parent_str
)) : (g_string_free) ((parent_str), ((!(0)))))
;
538
539 goutput_write (out, ">\n");
540
541 interfaces = g_type_interfaces (type, &n_interfaces);
542 for (i = 0; i < n_interfaces; i++)
543 {
544 GType itype = interfaces[i];
545 escaped_printf (out, " <implements name=\"%s\"/>\n",
546 g_type_name (itype));
547 }
548 g_free (interfaces);
549 goutput_write (out, " </fundamental>\n");
550}
551
552static void
553dump_type (GType type, const char *symbol, FILE *out)
554{
555 /* XXX: We need to ensure that global ancillary structures like
556 * GParamSpecPool are initialized before we use the GType and
557 * GObject reflection API to poke at things like properties and
558 * signals; we cannot rely on GObject being instantiated at this
559 * point.
560 */
561 GObjectClass *gobject_class = g_type_class_ref (G_TYPE_OBJECT((GType) ((20) << (2))));
562
563 switch (g_type_fundamental (type))
564 {
565 case G_TYPE_OBJECT((GType) ((20) << (2))):
566 dump_object_type (type, symbol, out);
567 break;
568 case G_TYPE_INTERFACE((GType) ((2) << (2))):
569 dump_interface_type (type, symbol, out);
570 break;
571 case G_TYPE_BOXED((GType) ((18) << (2))):
572 dump_boxed_type (type, symbol, out);
573 break;
574 case G_TYPE_FLAGS((GType) ((13) << (2))):
575 dump_flags_type (type, symbol, out);
576 break;
577 case G_TYPE_ENUM((GType) ((12) << (2))):
578 dump_enum_type (type, symbol, out);
579 break;
580 case G_TYPE_POINTER((GType) ((17) << (2))):
581 /* GValue, etc. Just skip them. */
582 break;
583 default:
584 dump_fundamental_type (type, symbol, out);
585 break;
586 }
587
588 g_type_class_unref ((GTypeClass *) gobject_class);
589}
590
591static void
592dump_error_quark (GQuark quark, const char *symbol, FILE *out)
593{
594 escaped_printf (out, " <error-quark function=\"%s\" domain=\"%s\"/>\n",
595 symbol, g_quark_to_string (quark));
596}
597
598/**
599 * g_irepository_dump:
600 * @input_filename: (type filename): Input filename (for example `input.txt`)
601 * @output_filename: (type filename): Output filename (for example `output.xml`)
602 * @error: a %GError
603 *
604 * Dump the introspection data from the types specified in @input_filename to
605 * @output_filename.
606 *
607 * The input file should be a
608 * UTF-8 Unix-line-ending text file, with each line containing either
609 * `get-type:` followed by the name of a [type@GObject.Type] `_get_type`
610 * function, or `error-quark:` followed by the name of an error quark function.
611 * No extra whitespace is allowed.
612 *
613 * This function will overwrite the contents of the output file.
614 *
615 * Returns: true on success, false on error
616 * Since: 2.80
617 */
618#ifndef G_IREPOSITORY_COMPILATION
619static gboolean
620dump_irepository (const char *arg,
621 GError **error) G_GNUC_UNUSED__attribute__ ((__unused__));
622static gboolean
623dump_irepository (const char *arg,
624 GError **error)
625#else
626gboolean
627g_irepository_dump (const char *arg,
628 GError **error)
629#endif
630{
631 GHashTable *output_types;
632 FILE *input;
633 FILE *output;
634 GModule *self;
635 gboolean caught_error = FALSE(0);
636
637 char **args = g_strsplit (arg, ",", 2);
638 if (args == NULL((void*)0))
7
Assuming 'args' is equal to NULL
8
Taking true branch
639 return FALSE(0);
9
Returning without writing to '*error'
640
641 const char *input_filename = args[0];
642 const char *output_filename = args[1];
643
644 self = g_module_open (NULL((void*)0), 0);
645 if (!self)
646 {
647 g_set_error (error,
648 G_FILE_ERRORg_file_error_quark (),
649 G_FILE_ERROR_FAILED,
650 "failed to open self: %s",
651 g_module_error ());
652 g_strfreev (args);
653 return FALSE(0);
654 }
655
656 input = fopen (input_filename, "rb");
657 if (input == NULL((void*)0))
658 {
659 int saved_errno = errno(*__errno_location ());
660 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
661 "Failed to open ‘%s’: %s", input_filename, g_strerror (saved_errno));
662
663 g_module_close (self);
664 g_strfreev (args);
665
666 return FALSE(0);
667 }
668
669 output = fopen (output_filename, "wb");
670 if (output == NULL((void*)0))
671 {
672 int saved_errno = errno(*__errno_location ());
673 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
674 "Failed to open ‘%s’: %s", output_filename, g_strerror (saved_errno));
675
676 fclose (input);
677 g_module_close (self);
678 g_strfreev (args);
679
680 return FALSE(0);
681 }
682
683 goutput_write (output, "<?xml version=\"1.0\"?>\n");
684 goutput_write (output, "<dump>\n");
685
686 output_types = g_hash_table_new (NULL((void*)0), NULL((void*)0));
687
688 while (TRUE(!(0)))
689 {
690 gsize len;
691 char *line = read_line (input, &len);
692 const char *function;
693
694 if (line == NULL((void*)0) || *line == '\0')
695 {
696 g_free (line);
697 break;
698 }
699
700 g_strchomp (line);
701
702 if (strncmp (line, "get-type:", strlen ("get-type:")) == 0)
703 {
704 GType type;
705
706 function = line + strlen ("get-type:");
707
708 type = invoke_get_type (self, function, error);
709
710 if (type == G_TYPE_INVALID((GType) ((0) << (2))))
711 {
712 g_printerr ("Invalid GType function: '%s'\n", function);
713 caught_error = TRUE(!(0));
714 g_free (line);
715 break;
716 }
717
718 if (g_hash_table_lookup (output_types, (gpointer) type))
719 goto next;
720 g_hash_table_insert (output_types, (gpointer) type, (gpointer) type);
721
722 dump_type (type, function, output);
723 }
724 else if (strncmp (line, "error-quark:", strlen ("error-quark:")) == 0)
725 {
726 GQuark quark;
727 function = line + strlen ("error-quark:");
728 quark = invoke_error_quark (self, function, error);
729
730 if (quark == 0)
731 {
732 g_printerr ("Invalid error quark function: '%s'\n", function);
733 caught_error = TRUE(!(0));
734 g_free (line);
735 break;
736 }
737
738 dump_error_quark (quark, function, output);
739 }
740
741
742 next:
743 g_free (line);
744 }
745
746 g_hash_table_destroy (output_types);
747
748 goutput_write (output, "</dump>\n");
749
750 {
751 /* Avoid overwriting an earlier set error */
752 if (fclose (input) != 0 && !caught_error)
753 {
754 int saved_errno = errno(*__errno_location ());
755
756 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
757 "Error closing input file ‘%s’: %s", input_filename,
758 g_strerror (saved_errno));
759 caught_error = TRUE(!(0));
760 }
761
762 if (fclose (output) != 0 && !caught_error)
763 {
764 int saved_errno = errno(*__errno_location ());
765
766 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
767 "Error closing output file ‘%s’: %s", output_filename,
768 g_strerror (saved_errno));
769 caught_error = TRUE(!(0));
770 }
771 }
772
773 g_strfreev (args);
774
775 return !caught_error;
776}
777
778
779int
780main(int argc, char **argv)
781{
782 GError *error = NULL((void*)0);
1
'error' initialized to a null pointer value
783 const char *introspect_dump_prefix = "--introspect-dump=";
784
785#if !GLIB_CHECK_VERSION(2,35,0)(2 > (2) || (2 == (2) && 80 > (35)) || (2 == (2
) && 80 == (35) && 3 >= (0)))
786 g_type_init ();
787#endif
788
789
790
791 if (argc != 2 || !g_str_has_prefix (argv[1], introspect_dump_prefix)(__builtin_constant_p (introspect_dump_prefix)? __extension__
({ const char * const __str = (argv[1]); const char * const __prefix
= (introspect_dump_prefix); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_18; if (__str == ((void
*)0) || __prefix == ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (argv[1], introspect_dump_prefix
) )
)
2
Assuming 'argc' is equal to 2
3
'?' condition is false
4
Assuming the condition is false
5
Taking false branch
792 {
793 g_printerr ("Usage: %s --introspect-dump=input,output", argv[0]);
794 exit (1);
795 }
796
797 if (!dump_irepository (argv[1] + strlen(introspect_dump_prefix), &error))
6
Calling 'dump_irepository'
10
Returning from 'dump_irepository'
11
Taking true branch
798 {
799 g_printerr ("%s\n", error->message);
12
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'error')
800 exit (1);
801 }
802 exit (0);
803}
804extern GType caja_operation_result_get_type(void);
805extern GType caja_column_get_type(void);
806extern GType caja_column_provider_get_type(void);
807extern GType caja_file_info_get_type(void);
808extern GType caja_widget_view_provider_get_type(void);
809extern GType caja_info_provider_get_type(void);
810extern GType caja_location_widget_provider_get_type(void);
811extern GType caja_menu_get_type(void);
812extern GType caja_menu_item_get_type(void);
813extern GType caja_menu_provider_get_type(void);
814extern GType caja_property_page_get_type(void);
815extern GType caja_property_page_provider_get_type(void);
816extern GType caja_configurable_get_type(void);
817G_MODULE_EXPORT__attribute__((visibility("default"))) GType (*GI_GET_TYPE_FUNCS_[])(void) = {
818 caja_operation_result_get_type,
819 caja_column_get_type,
820 caja_column_provider_get_type,
821 caja_file_info_get_type,
822 caja_widget_view_provider_get_type,
823 caja_info_provider_get_type,
824 caja_location_widget_provider_get_type,
825 caja_menu_get_type,
826 caja_menu_item_get_type,
827 caja_menu_provider_get_type,
828 caja_property_page_get_type,
829 caja_property_page_provider_get_type,
830 caja_configurable_get_type
831};
diff --git a/2024-07-29-023715-6438-1/report-895168.html b/2024-07-29-023715-6438-1/report-895168.html new file mode 100644 index 000000000..ba02085fd --- /dev/null +++ b/2024-07-29-023715-6438-1/report-895168.html @@ -0,0 +1,980 @@ + + + +test-eel-image-table.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test/test-eel-image-table.c
Warning:line 188, column 9
This statement is never executed
+ +

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 test-eel-image-table.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 -fdebug-compilation-dir=/rootdir/test -fcoverage-compilation-dir=/rootdir/test -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D VERSION="1.26.4" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local//locale" -D PIXBUFDIR="/usr/local/share/pixmaps" -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c test-eel-image-table.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <stdlib.h>
2#include <gtk/gtk.h>
3
4#include <eel/eel-image-table.h>
5
6#include "test.h"
7
8static const char pixbuf_name[] = PIXBUFDIR"/usr/local/share/pixmaps" "/mate-logo-white.svg";
9
10static const char *names[] =
11{
12 "Tomaso Albinoni",
13 "Isaac Albéniz",
14 "Georges Bizet",
15 "Luigi Boccherini",
16 "Alexander Borodin",
17 "Johannes Brahms",
18 "Max Bruch",
19 "Anton Bruckner",
20 "Frédéric Chopin",
21 "Aaron Copland",
22 "John Corigliano",
23 "Claude Debussy",
24 "Léo Delibes",
25 "Antonín Dvorák",
26 "Edward Elgar",
27 "Manuel de Falla",
28 "George Gershwin",
29 "Alexander Glazunov",
30 "Mikhail Glinka",
31 "Enrique Granados",
32 "Edvard Grieg",
33 "Joseph Haydn",
34 "Scott Joplin",
35 "Franz Liszt",
36 "Gustav Mahler",
37 "Igor Markevitch",
38 "Felix Mendelssohn",
39 "Modest Mussorgsky",
40 "Sergei Prokofiev",
41 "Giacomo Puccini",
42 "Maurice Ravel",
43 "Ottorino Respighi",
44 "Joaquin Rodrigo",
45 "Gioachino Rossini",
46 "Domenico Scarlatti",
47 "Franz Schubert",
48 "Robert Schumann",
49 "Jean Sibelius",
50 "Bedrich Smetana",
51 "Johann Strauss",
52 "Igor Stravinsky",
53 "Giuseppe Verdi",
54 "Antonio Vivaldi",
55 "Richard Wagner",
56};
57
58static GtkWidget *
59labeled_image_new (const char *text,
60 const char *icon_name)
61{
62 GtkWidget *image;
63 GdkPixbuf *pixbuf = NULL((void*)0);
64
65 if (icon_name) {
66 float sizes[] = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
67 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0 };
68 pixbuf = test_pixbuf_new_named (icon_name, sizes[random () % G_N_ELEMENTS (sizes)(sizeof (sizes) / sizeof ((sizes)[0]))]);
69 }
70
71 image = eel_labeled_image_new (text, pixbuf);
72
73 eel_gdk_pixbuf_unref_if_not_null (pixbuf);
74
75 return image;
76}
77
78
79static void
80image_table_child_enter_callback (GtkWidget *image_table,
81 GtkWidget *item,
82 gpointer callback_data)
83{
84#if 0
85 char *text;
86
87 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_20 = 1; else _g_boolean_var_20 = 0; _g_boolean_var_20
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
88 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_21
= 1; else _g_boolean_var_21 = 0; _g_boolean_var_21; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
89
90 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
91
92 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
93#endif
94}
95
96static void
97image_table_child_leave_callback (GtkWidget *image_table,
98 GtkWidget *item,
99 gpointer callback_data)
100{
101#if 0
102 char *text;
103
104 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
105 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_23
= 1; else _g_boolean_var_23 = 0; _g_boolean_var_23; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
106
107 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
108
109 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
110#endif
111}
112
113static void
114image_table_child_pressed_callback (GtkWidget *image_table,
115 GtkWidget *item,
116 gpointer callback_data)
117{
118 char *text;
119
120 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_24 = 1; else _g_boolean_var_24 = 0; _g_boolean_var_24
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
121 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_25
= 1; else _g_boolean_var_25 = 0; _g_boolean_var_25; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
122
123 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
124
125 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
126}
127
128static void
129image_table_child_released_callback (GtkWidget *image_table,
130 GtkWidget *item,
131 gpointer callback_data)
132{
133 char *text;
134
135 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_26 = 1; else _g_boolean_var_26 = 0; _g_boolean_var_26
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
136 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_27
= 1; else _g_boolean_var_27 = 0; _g_boolean_var_27; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
137
138 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
139
140 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
141}
142
143static void
144image_table_child_clicked_callback (GtkWidget *image_table,
145 GtkWidget *item,
146 gpointer callback_data)
147{
148 char *text;
149
150 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_28
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_28 = 1; else _g_boolean_var_28 = 0; _g_boolean_var_28
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
151 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_29
= 1; else _g_boolean_var_29 = 0; _g_boolean_var_29; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
152
153 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
154
155 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
156}
157
158static int
159foo_timeout (gpointer callback_data)
160{
161 static int recursion_count = 0;
162 g_return_val_if_fail (GTK_IS_WINDOW (callback_data), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = ((gtk_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_30 = 1; else _g_boolean_var_30 = 0; _g_boolean_var_30
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "GTK_IS_WINDOW (callback_data)")
; return ((0)); } } while (0)
;
163
164 recursion_count++;
165
166 g_print ("%s(%d)\n", G_STRFUNC((const char*) (__func__)), recursion_count);
167 gtk_widget_queue_resize (GTK_WIDGET (callback_data)((((GtkWidget*) (void *) ((callback_data))))));
168
169 recursion_count--;
170
171 return FALSE(0);
172}
173
174static void
175image_table_size_allocate (GtkWidget *image_table,
176 GtkAllocation *allocation,
177 gpointer callback_data)
178{
179 static int recursion_count = 0;
180 GtkAllocation w_allocation;
181
182 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
183 g_return_if_fail (allocation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if (allocation != ((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__)), "allocation != NULL"
); return; } } while (0)
;
184 g_return_if_fail (GTK_IS_WINDOW (callback_data))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = ((gtk_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_33 = 1; else _g_boolean_var_33 = 0; _g_boolean_var_33
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "GTK_IS_WINDOW (callback_data)")
; return; } } while (0)
;
185
186 recursion_count++;
187
188 if (0) g_timeout_add (0, foo_timeout, callback_data);
This statement is never executed
189
190 /*gtk_widget_queue_resize (GTK_WIDGET (callback_data));*/
191
192 gtk_widget_get_allocation (GTK_WIDGET (image_table)((((GtkWidget*) (void *) ((image_table))))), &w_allocation);
193 if (0) gtk_widget_size_allocate (GTK_WIDGET (image_table)((((GtkWidget*) (void *) ((image_table))))),
194 &w_allocation);
195
196 g_print ("%s(%d)\n", G_STRFUNC((const char*) (__func__)), recursion_count);
197
198 recursion_count--;
199}
200
201static GtkWidget *
202image_table_new_scrolled (void)
203{
204 GtkWidget *scrolled;
205 GtkWidget *viewport;
206 GtkWidget *window;
207 GtkWidget *image_table;
208 int i;
209
210 window = test_window_new ("Image Table Test", 10);
211
212 gtk_window_set_default_size (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), 400, 300);
213
214 /* Scrolled window */
215 scrolled = gtk_scrolled_window_new (NULL((void*)0), NULL((void*)0));
216 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
217 GTK_POLICY_NEVER,
218 GTK_POLICY_AUTOMATIC);
219 gtk_container_add (GTK_CONTAINER (window)((((GtkContainer*) (void *) ((window))))), scrolled);
220
221 /* Viewport */
222 viewport = gtk_viewport_new (NULL((void*)0), NULL((void*)0));
223 gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport)((((GtkViewport*) (void *) ((viewport))))), GTK_SHADOW_OUT);
224 gtk_container_add (GTK_CONTAINER (scrolled)((((GtkContainer*) (void *) ((scrolled))))), viewport);
225
226 image_table = eel_image_table_new (FALSE(0));
227
228 if (0) g_signal_connect (image_table,g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
229 "size_allocate",g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
230 G_CALLBACK (image_table_size_allocate),g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
231 window)g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
;
232
233 eel_wrap_table_set_x_justification (EEL_WRAP_TABLE (image_table)((((EelWrapTable*) (void *) ((image_table))))),
234 EEL_JUSTIFICATION_MIDDLE);
235 eel_wrap_table_set_y_justification (EEL_WRAP_TABLE (image_table)((((EelWrapTable*) (void *) ((image_table))))),
236 EEL_JUSTIFICATION_END);
237
238 gtk_container_add (GTK_CONTAINER (viewport)((((GtkContainer*) (void *) ((viewport))))), image_table);
239
240 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
241 "child_enter",g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
242 G_CALLBACK (image_table_child_enter_callback),g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
243 NULL)g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
;
244
245 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
246 "child_leave",g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
247 G_CALLBACK (image_table_child_leave_callback),g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
248 NULL)g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
;
249
250 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
251 "child_pressed",g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
252 G_CALLBACK (image_table_child_pressed_callback),g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
253 NULL)g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
;
254
255 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
256 "child_released",g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
257 G_CALLBACK (image_table_child_released_callback),g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
258 NULL)g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
;
259
260 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
261 "child_clicked",g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
262 G_CALLBACK (image_table_child_clicked_callback),g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
263 NULL)g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
;
264
265 for (i = 0; i < 100; i++) {
266 char *text;
267 GtkWidget *image;
268
269 text = g_strdup_printf ("%s %d",
270 names[random () % G_N_ELEMENTS (names)(sizeof (names) / sizeof ((names)[0]))],
271 i);
272 image = labeled_image_new (text, pixbuf_name);
273 g_free (text);
274
275 gtk_container_add (GTK_CONTAINER (image_table)((((GtkContainer*) (void *) ((image_table))))), image);
276 gtk_widget_show (image);
277 }
278
279 gtk_widget_show (viewport);
280 gtk_widget_show (scrolled);
281 gtk_widget_show (image_table);
282
283 return window;
284}
285
286int
287main (int argc, char* argv[])
288{
289 GtkWidget *window = NULL((void*)0);
290
291 test_init (&argc, &argv);
292
293 window = image_table_new_scrolled ();
294
295 gtk_widget_show (window);
296
297 gtk_main ();
298
299 return 0;
300}
diff --git a/2024-07-29-023715-6438-1/report-89a2be.html b/2024-07-29-023715-6438-1/report-89a2be.html new file mode 100644 index 000000000..96300630b --- /dev/null +++ b/2024-07-29-023715-6438-1/report-89a2be.html @@ -0,0 +1,9582 @@ + + + +caja-file.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file.c
Warning:line 3926, column 12
This statement is never executed
+ +

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 caja-file.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-file.c: Caja file model.
4
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <grp.h>
27#include <gtk/gtk.h>
28#include <glib/gi18n.h>
29#include <glib/gstdio.h>
30#include <gio/gio.h>
31#include <glib.h>
32#include <libxml/parser.h>
33#include <pwd.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <sys/time.h>
37#include <time.h>
38#include <unistd.h>
39#include <sys/stat.h>
40
41#include <eel/eel-debug.h>
42#include <eel/eel-glib-extensions.h>
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-vfs-extensions.h>
45#include <eel/eel-gtk-macros.h>
46#include <eel/eel-string.h>
47
48#include <libcaja-extension/caja-file-info.h>
49#include <libcaja-extension/caja-extension-private.h>
50#include <libcaja-private/caja-extensions.h>
51
52#include "caja-file.h"
53#include "caja-directory-notify.h"
54#include "caja-directory-private.h"
55#include "caja-signaller.h"
56#include "caja-desktop-directory.h"
57#include "caja-desktop-directory-file.h"
58#include "caja-desktop-icon-file.h"
59#include "caja-file-attributes.h"
60#include "caja-file-private.h"
61#include "caja-file-operations.h"
62#include "caja-file-utilities.h"
63#include "caja-global-preferences.h"
64#include "caja-lib-self-check-functions.h"
65#include "caja-link.h"
66#include "caja-metadata.h"
67#include "caja-module.h"
68#include "caja-search-directory.h"
69#include "caja-search-directory-file.h"
70#include "caja-thumbnails.h"
71#include "caja-ui-utilities.h"
72#include "caja-vfs-file.h"
73#include "caja-saved-search-file.h"
74
75#ifdef HAVE_SELINUX1
76#include <selinux/selinux.h>
77#endif
78
79#define ICON_NAME_THUMBNAIL_LOADING"image-loading" "image-loading"
80
81#undef CAJA_FILE_DEBUG_REF
82#undef CAJA_FILE_DEBUG_REF_VALGRIND
83
84#ifdef CAJA_FILE_DEBUG_REF_VALGRIND
85#include <valgrind/valgrind.h>
86#define DEBUG_REF_PRINTFprintf VALGRIND_PRINTF_BACKTRACE
87#else
88#define DEBUG_REF_PRINTFprintf printf
89#endif
90
91/* Files that start with these characters sort after files that don't. */
92#define SORT_LAST_CHAR1'.' '.'
93#define SORT_LAST_CHAR2'#' '#'
94
95#define METADATA_ID_IS_LIST_MASK(1U<<31) (1U<<31)
96
97#define SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3 3
98#define SORT_BY_EXTENSION_MAX_SEGMENTS3 3
99
100typedef enum {
101 SHOW_HIDDEN = 1 << 0,
102 SHOW_BACKUP = 1 << 1,
103} FilterOptions;
104
105typedef void (* ModifyListFunction) (GList **list, CajaFile *file);
106
107enum {
108 CHANGED,
109 UPDATED_DEEP_COUNT_IN_PROGRESS,
110 LAST_SIGNAL
111};
112
113static int date_format_pref;
114
115static guint signals[LAST_SIGNAL] = { 0 };
116
117static GHashTable *symbolic_links;
118
119static GQuark attribute_name_q,
120 attribute_size_q,
121 attribute_size_on_disk_q,
122 attribute_type_q,
123 attribute_creation_date_q,
124 attribute_date_created_q,
125 attribute_modification_date_q,
126 attribute_date_modified_q,
127 attribute_accessed_date_q,
128 attribute_date_accessed_q,
129 attribute_emblems_q,
130 attribute_extension_q,
131 attribute_mime_type_q,
132 attribute_size_detail_q,
133 attribute_size_on_disk_detail_q,
134 attribute_deep_size_q,
135 attribute_deep_size_on_disk_q,
136 attribute_deep_file_count_q,
137 attribute_deep_directory_count_q,
138 attribute_deep_total_count_q,
139 attribute_date_changed_q,
140 attribute_trashed_on_q,
141 attribute_trash_orig_path_q,
142 attribute_date_permissions_q,
143 attribute_permissions_q,
144 attribute_selinux_context_q,
145 attribute_octal_permissions_q,
146 attribute_owner_q,
147 attribute_group_q,
148 attribute_uri_q,
149 attribute_where_q,
150 attribute_link_target_q,
151 attribute_volume_q,
152 attribute_free_space_q;
153
154static void caja_file_info_iface_init (CajaFileInfoIface *iface);
155static char * caja_file_get_owner_as_string (CajaFile *file,
156 gboolean include_real_name);
157static char * caja_file_get_type_as_string (CajaFile *file);
158static gboolean update_info_and_name (CajaFile *file,
159 GFileInfo *info);
160static const char * caja_file_peek_display_name (CajaFile *file);
161static const char * caja_file_peek_display_name_collation_key (CajaFile *file);
162static void file_mount_unmounted (GMount *mount, gpointer data);
163static void metadata_hash_free (GHashTable *hash);
164
165G_DEFINE_TYPE_WITH_CODE (CajaFile, caja_file, G_TYPE_OBJECT,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
166 G_ADD_PRIVATE (CajaFile)static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
167 G_IMPLEMENT_INTERFACE (CAJA_TYPE_FILE_INFO,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
168 caja_file_info_iface_init))static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
169
170static void
171caja_file_init (CajaFile *file)
172{
173 file->details = caja_file_get_instance_private (file);
174
175 caja_file_clear_info (file);
176 caja_file_invalidate_extension_info_internal (file);
177}
178
179static GObject*
180caja_file_constructor (GType type,
181 guint n_construct_properties,
182 GObjectConstructParam *construct_params)
183{
184 GObject *object;
185 CajaFile *file;
186
187 object = (* G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->constructor) (type,
188 n_construct_properties,
189 construct_params);
190
191 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
192
193 /* Set to default type after full construction */
194 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type != G_FILE_TYPE_UNKNOWN) {
195 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
196 }
197
198 return object;
199}
200
201gboolean
202caja_file_set_display_name (CajaFile *file,
203 const char *display_name,
204 const char *edit_name,
205 gboolean custom)
206{
207 gboolean changed;
208
209 if (custom && display_name == NULL((void*)0)) {
210 /* We're re-setting a custom display name, invalidate it if
211 we already set it so that the old one is re-read */
212 if (file->details->got_custom_display_name) {
213 file->details->got_custom_display_name = FALSE(0);
214 caja_file_invalidate_attributes (file,
215 CAJA_FILE_ATTRIBUTE_INFO);
216 }
217 return FALSE(0);
218 }
219
220 if (display_name == NULL((void*)0) || *display_name == 0) {
221 return FALSE(0);
222 }
223
224 if (!custom && file->details->got_custom_display_name) {
225 return FALSE(0);
226 }
227
228 if (edit_name == NULL((void*)0)) {
229 edit_name = display_name;
230 }
231
232 changed = FALSE(0);
233
234 if (eel_strcmp (file->details->display_name, display_name) != 0) {
235 changed = TRUE(!(0));
236
237 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
238
239 if (eel_strcmp (file->details->name, display_name) == 0) {
240 file->details->display_name = g_ref_string_acquire (file->details->name);
241 } else {
242 file->details->display_name = g_ref_string_new (display_name);
243 }
244
245 g_free (file->details->display_name_collation_key);
246 file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
247 }
248
249 if (eel_strcmp (file->details->edit_name, edit_name) != 0) {
250 changed = TRUE(!(0));
251
252 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
253 if (eel_strcmp (file->details->display_name, edit_name) == 0) {
254 file->details->edit_name = g_ref_string_acquire (file->details->display_name);
255 } else {
256 file->details->edit_name = g_ref_string_new (edit_name);
257 }
258 }
259
260 file->details->got_custom_display_name = custom;
261 return changed;
262}
263
264static void
265caja_file_clear_display_name (CajaFile *file)
266{
267 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
268 file->details->display_name = NULL((void*)0);
269 g_free (file->details->display_name_collation_key);
270 file->details->display_name_collation_key = NULL((void*)0);
271 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
272 file->details->edit_name = NULL((void*)0);
273}
274
275static gboolean
276foreach_metadata_free (gpointer key,
277 gpointer value,
278 gpointer user_data)
279{
280 guint id;
281
282 id = GPOINTER_TO_UINT (key)((guint) (gulong) (key));
283
284 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
285 g_strfreev ((char **)value);
286 } else {
287 g_free ((char *)value);
288 }
289 return TRUE(!(0));
290}
291
292
293static void
294metadata_hash_free (GHashTable *hash)
295{
296 g_hash_table_foreach_remove (hash,
297 foreach_metadata_free,
298 NULL((void*)0));
299 g_hash_table_destroy (hash);
300}
301
302static gboolean
303metadata_hash_equal (GHashTable *hash1,
304 GHashTable *hash2)
305{
306 GHashTableIter iter;
307 gpointer key1, value1, value2;
308 guint id;
309
310 if (hash1 == NULL((void*)0) && hash2 == NULL((void*)0)) {
311 return TRUE(!(0));
312 }
313
314 if (hash1 == NULL((void*)0) || hash2 == NULL((void*)0)) {
315 return FALSE(0);
316 }
317
318 if (g_hash_table_size (hash1) !=
319 g_hash_table_size (hash2)) {
320 return FALSE(0);
321 }
322
323 g_hash_table_iter_init (&iter, hash1);
324 while (g_hash_table_iter_next (&iter, &key1, &value1)) {
325 value2 = g_hash_table_lookup (hash2, key1);
326 if (value2 == NULL((void*)0)) {
327 return FALSE(0);
328 }
329 id = GPOINTER_TO_UINT (key1)((guint) (gulong) (key1));
330 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
331 if (!eel_g_strv_equal ((char **)value1, (char **)value2)) {
332 return FALSE(0);
333 }
334 } else {
335 if (strcmp ((char *)value1, (char *)value2) != 0) {
336 return FALSE(0);
337 }
338 }
339 }
340
341 return TRUE(!(0));
342}
343
344static void
345clear_metadata (CajaFile *file)
346{
347 if (file->details->metadata) {
348 metadata_hash_free (file->details->metadata);
349 file->details->metadata = NULL((void*)0);
350 }
351}
352
353static GHashTable *
354get_metadata_from_info (GFileInfo *info)
355{
356 GHashTable *metadata;
357 char **attrs;
358 guint id;
359 int i;
360 GFileAttributeType type;
361 gpointer value;
362
363 attrs = g_file_info_list_attributes (info, "metadata");
364
365 metadata = g_hash_table_new (NULL((void*)0), NULL((void*)0));
366
367 for (i = 0; attrs[i] != NULL((void*)0); i++) {
368 id = caja_metadata_get_id (attrs[i] + strlen ("metadata::"));
369 if (id == 0) {
370 continue;
371 }
372
373 if (!g_file_info_get_attribute_data (info, attrs[i],
374 &type, &value, NULL((void*)0))) {
375 continue;
376 }
377
378 if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
379 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
380 g_strdup ((char *)value)g_strdup_inline ((char *)value));
381 } else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) {
382 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
383 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
384 g_strdupv ((char **)value));
385 }
386 }
387
388 g_strfreev (attrs);
389
390 return metadata;
391}
392
393gboolean
394caja_file_update_metadata_from_info (CajaFile *file,
395 GFileInfo *info)
396{
397 gboolean changed = FALSE(0);
398
399 if (g_file_info_has_namespace (info, "metadata")) {
400 GHashTable *metadata;
401
402 metadata = get_metadata_from_info (info);
403 if (!metadata_hash_equal (metadata,
404 file->details->metadata)) {
405 changed = TRUE(!(0));
406 clear_metadata (file);
407 file->details->metadata = metadata;
408 } else {
409 metadata_hash_free (metadata);
410 }
411 } else if (file->details->metadata) {
412 changed = TRUE(!(0));
413 clear_metadata (file);
414 }
415 return changed;
416}
417
418void
419caja_file_clear_info (CajaFile *file)
420{
421 file->details->got_file_info = FALSE(0);
422 if (file->details->get_info_error) {
423 g_error_free (file->details->get_info_error);
424 file->details->get_info_error = NULL((void*)0);
425 }
426 /* Reset to default type, which might be other than unknown for
427 special kinds of files like the desktop or a search directory */
428 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
429
430 if (!file->details->got_custom_display_name) {
431 caja_file_clear_display_name (file);
432 }
433
434 if (!file->details->got_custom_activation_uri &&
435 file->details->activation_uri != NULL((void*)0)) {
436 g_free (file->details->activation_uri);
437 file->details->activation_uri = NULL((void*)0);
438 }
439
440 if (file->details->icon != NULL((void*)0)) {
441 g_object_unref (file->details->icon);
442 file->details->icon = NULL((void*)0);
443 }
444
445 g_free (file->details->thumbnail_path);
446 file->details->thumbnail_path = NULL((void*)0);
447 file->details->thumbnailing_failed = FALSE(0);
448
449 file->details->is_launcher = FALSE(0);
450 file->details->is_foreign_link = FALSE(0);
451 file->details->is_trusted_link = FALSE(0);
452 file->details->is_symlink = FALSE(0);
453 file->details->is_hidden = FALSE(0);
454 file->details->is_backup = FALSE(0);
455 file->details->is_mountpoint = FALSE(0);
456 file->details->uid = -1;
457 file->details->gid = -1;
458 file->details->can_read = TRUE(!(0));
459 file->details->can_write = TRUE(!(0));
460 file->details->can_execute = TRUE(!(0));
461 file->details->can_delete = TRUE(!(0));
462 file->details->can_trash = TRUE(!(0));
463 file->details->can_rename = TRUE(!(0));
464 file->details->can_mount = FALSE(0);
465 file->details->can_unmount = FALSE(0);
466 file->details->can_eject = FALSE(0);
467 file->details->can_start = FALSE(0);
468 file->details->can_start_degraded = FALSE(0);
469 file->details->can_stop = FALSE(0);
470 file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
471 file->details->can_poll_for_media = FALSE(0);
472 file->details->is_media_check_automatic = FALSE(0);
473 file->details->has_permissions = FALSE(0);
474 file->details->permissions = 0;
475 file->details->size = -1;
476 file->details->size_on_disk = -1;
477 file->details->sort_order = 0;
478 file->details->mtime = 0;
479 file->details->atime = 0;
480 file->details->ctime = 0;
481 file->details->btime = 0;
482 file->details->trash_time = 0;
483 g_free (file->details->symlink_name);
484 file->details->symlink_name = NULL((void*)0);
485 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
486 file->details->mime_type = NULL((void*)0);
487 g_free (file->details->selinux_context);
488 file->details->selinux_context = NULL((void*)0);
489 g_free (file->details->description);
490 file->details->description = NULL((void*)0);
491 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
492 file->details->owner = NULL((void*)0);
493 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
494 file->details->owner_real = NULL((void*)0);
495 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
496 file->details->group = NULL((void*)0);
497
498 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
499 file->details->filesystem_id = NULL((void*)0);
500
501 clear_metadata (file);
502}
503
504static CajaFile *
505caja_file_new_from_filename (CajaDirectory *directory,
506 const char *filename,
507 gboolean self_owned)
508{
509 CajaFile *file;
510
511 g_assert (CAJA_IS_DIRECTORY (directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_695
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_695
= 1; else _g_boolean_var_695 = 0; _g_boolean_var_695; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 511, ((const char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"
); } while (0)
;
512 g_assert (filename != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_696
; if (filename != ((void*)0)) _g_boolean_var_696 = 1; else _g_boolean_var_696
= 0; _g_boolean_var_696; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 512, ((const char*) (__func__)
), "filename != NULL"); } while (0)
;
513 g_assert (filename[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_697
; if (filename[0] != '\0') _g_boolean_var_697 = 1; else _g_boolean_var_697
= 0; _g_boolean_var_697; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 513, ((const char*) (__func__)
), "filename[0] != '\\0'"); } while (0)
;
514
515 if (CAJA_IS_DESKTOP_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_desktop_directory_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; }
))))
) {
516 if (self_owned) {
517 file = CAJA_FILE (g_object_new (CAJA_TYPE_DESKTOP_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_desktop_directory_file_get_type
(), ((void*)0)))))))
;
518 } else {
519 /* This doesn't normally happen, unless the user somehow types in a uri
520 * that references a file like this. (See #349840) */
521 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
522 }
523 } else if (CAJA_IS_SEARCH_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_search_directory_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; }
))))
) {
524 if (self_owned) {
525 file = CAJA_FILE (g_object_new (CAJA_TYPE_SEARCH_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_search_directory_file_get_type
(), ((void*)0)))))))
;
526 } else {
527 /* This doesn't normally happen, unless the user somehow types in a uri
528 * that references a file like this. (See #349840) */
529 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
530 }
531 } else if (g_str_has_suffix (filename, CAJA_SAVED_SEARCH_EXTENSION)(__builtin_constant_p (".savedSearch")? __extension__ ({ const
char * const __str = (filename); const char * const __suffix
= (".savedSearch"); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_698; if (__str == ((void
*)0) || __suffix == ((void*)0)) _g_boolean_var_698 = 1; else _g_boolean_var_698
= 0; _g_boolean_var_698; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".savedSearch") )
) {
532 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
533 } else {
534 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
535 }
536
537 file->details->directory = caja_directory_ref (directory);
538
539 file->details->name = g_ref_string_new (filename);
540
541#ifdef CAJA_FILE_DEBUG_REF
542 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
543#endif
544
545 return file;
546}
547
548static void
549modify_link_hash_table (CajaFile *file,
550 ModifyListFunction modify_function)
551{
552 char *target_uri;
553 gboolean found;
554 gpointer original_key;
555 GList **list_ptr;
556
557 /* Check if there is a symlink name. If none, we are OK. */
558 if (file->details->symlink_name == NULL((void*)0) || !caja_file_is_symbolic_link (file)) {
559 return;
560 }
561
562 /* Create the hash table first time through. */
563 if (symbolic_links == NULL((void*)0)) {
564 symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
565 }
566
567 target_uri = caja_file_get_symbolic_link_target_uri (file);
568
569 /* Find the old contents of the hash table. */
570 found = g_hash_table_lookup_extended
571 (symbolic_links, target_uri,
572 &original_key, (gpointer *)&list_ptr);
573 if (!found) {
574 list_ptr = g_new0 (GList *, 1)(GList * *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (GList *); 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
; }))
;
575 original_key = g_strdup (target_uri)g_strdup_inline (target_uri);
576 g_hash_table_insert (symbolic_links, original_key, list_ptr);
577 }
578 (* modify_function) (list_ptr, file);
579 if (*list_ptr == NULL((void*)0)) {
580 g_hash_table_remove (symbolic_links, target_uri);
581 g_free (list_ptr);
582 g_free (original_key);
583 }
584 g_free (target_uri);
585}
586
587static void
588symbolic_link_weak_notify (gpointer data,
589 GObject *where_the_object_was)
590{
591 GList **list = data;
592 /* This really shouldn't happen, but we're seeing some strange things in
593 bug #358172 where the symlink hashtable isn't correctly updated. */
594 *list = g_list_remove (*list, where_the_object_was);
595}
596
597static void
598add_to_link_hash_table_list (GList **list, CajaFile *file)
599{
600 if (g_list_find (*list, file) != NULL((void*)0)) {
601 g_warning ("Adding file to symlink_table multiple times. "
602 "Please add feedback of what you were doing at https://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
603 return;
604 }
605 g_object_weak_ref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
606 *list = g_list_prepend (*list, file);
607}
608
609static void
610add_to_link_hash_table (CajaFile *file)
611{
612 modify_link_hash_table (file, add_to_link_hash_table_list);
613}
614
615static void
616remove_from_link_hash_table_list (GList **list, CajaFile *file)
617{
618 if (g_list_find (*list, file) != NULL((void*)0)) {
619 g_object_weak_unref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
620 *list = g_list_remove (*list, file);
621 }
622}
623
624static void
625remove_from_link_hash_table (CajaFile *file)
626{
627 modify_link_hash_table (file, remove_from_link_hash_table_list);
628}
629
630CajaFile *
631caja_file_new_from_info (CajaDirectory *directory,
632 GFileInfo *info)
633{
634 CajaFile *file;
635 const char *mime_type;
636
637 g_return_val_if_fail (CAJA_IS_DIRECTORY (directory), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_699
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_699
= 1; else _g_boolean_var_699 = 0; _g_boolean_var_699; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"); return
(((void*)0)); } } while (0)
;
638 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_700
; if (info != ((void*)0)) _g_boolean_var_700 = 1; else _g_boolean_var_700
= 0; _g_boolean_var_700; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "info != NULL"); return
(((void*)0)); } } while (0)
;
639
640 mime_type = g_file_info_get_content_type (info);
641 if (mime_type &&
642 strcmp (mime_type, CAJA_SAVED_SEARCH_MIMETYPE"application/x-mate-saved-search") == 0) {
643 g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
644 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
645 } else {
646 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
647 }
648
649 file->details->directory = caja_directory_ref (directory);
650
651 update_info_and_name (file, info);
652
653#ifdef CAJA_FILE_DEBUG_REF
654 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
655#endif
656
657 return file;
658}
659
660static CajaFile *
661caja_file_get_internal (GFile *location, gboolean create)
662{
663 gboolean self_owned;
664 CajaDirectory *directory;
665 CajaFile *file;
666 GFile *parent;
667 char *basename;
668
669 g_assert (location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_701
; if (location != ((void*)0)) _g_boolean_var_701 = 1; else _g_boolean_var_701
= 0; _g_boolean_var_701; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 669, ((const char*) (__func__)
), "location != NULL"); } while (0)
;
670
671 parent = g_file_get_parent (location);
672
673 self_owned = FALSE(0);
674 if (parent == NULL((void*)0)) {
675 self_owned = TRUE(!(0));
676 parent = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
677 }
678
679 /* Get object that represents the directory. */
680 directory = caja_directory_get_internal (parent, create);
681
682 g_object_unref (parent);
683
684 /* Get the name for the file. */
685 if (self_owned && directory != NULL((void*)0)) {
686 basename = caja_directory_get_name_for_self_as_new_file (directory);
687 } else {
688 basename = g_file_get_basename (location);
689 }
690 /* Check to see if it's a file that's already known. */
691 if (directory == NULL((void*)0)) {
692 file = NULL((void*)0);
693 } else if (self_owned) {
694 file = directory->details->as_file;
695 } else {
696 file = caja_directory_find_file_by_name (directory, basename);
697 }
698
699 /* Ref or create the file. */
700 if (file != NULL((void*)0)) {
701 caja_file_ref (file);
702 } else if (create && directory != NULL((void*)0)) {
703 file = caja_file_new_from_filename (directory, basename, self_owned);
704 if (self_owned) {
705 g_assert (directory->details->as_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_702
; if (directory->details->as_file == ((void*)0)) _g_boolean_var_702
= 1; else _g_boolean_var_702 = 0; _g_boolean_var_702; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 705, ((const char*) (__func__)), "directory->details->as_file == NULL"
); } while (0)
;
706 directory->details->as_file = file;
707 } else {
708 caja_directory_add_file (directory, file);
709 }
710 }
711
712 g_free (basename);
713 caja_directory_unref (directory);
714
715 return file;
716}
717
718CajaFile *
719caja_file_get (GFile *location)
720{
721 return caja_file_get_internal (location, TRUE(!(0)));
722}
723
724CajaFile *
725caja_file_get_existing (GFile *location)
726{
727 return caja_file_get_internal (location, FALSE(0));
728}
729
730CajaFile *
731caja_file_get_existing_by_uri (const char *uri)
732{
733 GFile *location;
734 CajaFile *file;
735
736 location = g_file_new_for_uri (uri);
737 file = caja_file_get_internal (location, FALSE(0));
738 g_object_unref (location);
739
740 return file;
741}
742
743CajaFile *
744caja_file_get_by_uri (const char *uri)
745{
746 GFile *location;
747 CajaFile *file;
748
749 location = g_file_new_for_uri (uri);
750 file = caja_file_get_internal (location, TRUE(!(0)));
751 g_object_unref (location);
752
753 return file;
754}
755
756gboolean
757caja_file_is_self_owned (CajaFile *file)
758{
759 return file->details->directory->details->as_file == file;
760}
761
762static void
763finalize (GObject *object)
764{
765 CajaDirectory *directory;
766 CajaFile *file;
767
768 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
769
770 g_assert (file->details->operations_in_progress == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_703
; if (file->details->operations_in_progress == ((void*)
0)) _g_boolean_var_703 = 1; else _g_boolean_var_703 = 0; _g_boolean_var_703
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 770, ((const char*) (__func__)), "file->details->operations_in_progress == NULL"
); } while (0)
;
771
772 if (file->details->is_thumbnailing) {
773 char *uri;
774
775 uri = caja_file_get_uri (file);
776 caja_thumbnail_remove_from_queue (uri);
777 g_free (uri);
778 }
779
780 caja_async_destroying_file (file);
781
782 remove_from_link_hash_table (file);
783
784 directory = file->details->directory;
785
786 if (caja_file_is_self_owned (file)) {
787 directory->details->as_file = NULL((void*)0);
788 } else {
789 if (!file->details->is_gone) {
790 caja_directory_remove_file (directory, file);
791 }
792 }
793
794 if (file->details->get_info_error) {
795 g_error_free (file->details->get_info_error);
796 }
797
798 caja_directory_unref (directory);
799 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
800 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
801 g_free (file->details->display_name_collation_key);
802 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
803 if (file->details->icon) {
804 g_object_unref (file->details->icon);
805 }
806 g_free (file->details->thumbnail_path);
807 g_free (file->details->symlink_name);
808 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
809 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
810 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
811 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
812 g_free (file->details->selinux_context);
813 g_free (file->details->description);
814 g_free (file->details->top_left_text);
815 g_free (file->details->custom_icon);
816 g_free (file->details->activation_uri);
817 g_free (file->details->compare_by_emblem_cache);
818
819 if (file->details->thumbnail) {
820 g_object_unref (file->details->thumbnail);
821 }
822 if (file->details->mount) {
823 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
824 g_object_unref (file->details->mount);
825 }
826
827 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
828
829 g_list_free_full (file->details->mime_list, g_free);
830 g_list_free_full (file->details->pending_extension_emblems, g_free);
831 g_list_free_full (file->details->extension_emblems, g_free);
832 g_list_free_full (file->details->pending_info_providers, g_object_unref);
833
834 if (file->details->pending_extension_attributes) {
835 g_hash_table_destroy (file->details->pending_extension_attributes);
836 }
837
838 if (file->details->extension_attributes) {
839 g_hash_table_destroy (file->details->extension_attributes);
840 }
841
842 if (file->details->metadata) {
843 metadata_hash_free (file->details->metadata);
844 }
845
846 G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->finalize (object);
847}
848
849CajaFile *
850caja_file_ref (CajaFile *file)
851{
852 if (file == NULL((void*)0)) {
853 return NULL((void*)0);
854 }
855 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_704
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_704
= 1; else _g_boolean_var_704 = 0; _g_boolean_var_704; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
856
857#ifdef CAJA_FILE_DEBUG_REF
858 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
859#endif
860
861 return g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
862}
863
864void
865caja_file_unref (CajaFile *file)
866{
867 if (file == NULL((void*)0)) {
868 return;
869 }
870
871 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_705
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_705
= 1; else _g_boolean_var_705 = 0; _g_boolean_var_705; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
872
873#ifdef CAJA_FILE_DEBUG_REF
874 DEBUG_REF_PRINTFprintf("%10p unref'd", file);
875#endif
876
877 g_object_unref (file);
878}
879
880/**
881 * caja_file_get_parent_uri_for_display:
882 *
883 * Get the uri for the parent directory.
884 *
885 * @file: The file in question.
886 *
887 * Return value: A string representing the parent's location,
888 * formatted for user display (including stripping "file://").
889 * If the parent is NULL, returns the empty string.
890 */
891char *
892caja_file_get_parent_uri_for_display (CajaFile *file)
893{
894 GFile *parent;
895 char *result;
896
897 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_706
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_706
= 1; else _g_boolean_var_706 = 0; _g_boolean_var_706; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 897, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
898
899 parent = caja_file_get_parent_location (file);
900 if (parent) {
901 result = g_file_get_parse_name (parent);
902 g_object_unref (parent);
903 } else {
904 result = g_strdup ("")g_strdup_inline ("");
905 }
906
907 return result;
908}
909
910/**
911 * caja_file_get_parent_uri:
912 *
913 * Get the uri for the parent directory.
914 *
915 * @file: The file in question.
916 *
917 * Return value: A string for the parent's location, in "raw URI" form.
918 * Use caja_file_get_parent_uri_for_display instead if the
919 * result is to be displayed on-screen.
920 * If the parent is NULL, returns the empty string.
921 */
922char *
923caja_file_get_parent_uri (CajaFile *file)
924{
925 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_707
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_707
= 1; else _g_boolean_var_707 = 0; _g_boolean_var_707; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 925, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
926
927 if (caja_file_is_self_owned (file)) {
928 /* Callers expect an empty string, not a NULL. */
929 return g_strdup ("")g_strdup_inline ("");
930 }
931
932 return caja_directory_get_uri (file->details->directory);
933}
934
935GFile *
936caja_file_get_parent_location (CajaFile *file)
937{
938 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_708
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_708
= 1; else _g_boolean_var_708 = 0; _g_boolean_var_708; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 938, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
939
940 if (caja_file_is_self_owned (file)) {
941 /* Callers expect an empty string, not a NULL. */
942 return NULL((void*)0);
943 }
944
945 return caja_directory_get_location (file->details->directory);
946}
947
948CajaFile *
949caja_file_get_parent (CajaFile *file)
950{
951 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_709
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_709
= 1; else _g_boolean_var_709 = 0; _g_boolean_var_709; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 951, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
952
953 if (caja_file_is_self_owned (file)) {
954 return NULL((void*)0);
955 }
956
957 return caja_directory_get_corresponding_file (file->details->directory);
958}
959
960/**
961 * caja_file_can_read:
962 *
963 * Check whether the user is allowed to read the contents of this file.
964 *
965 * @file: The file to check.
966 *
967 * Return value: FALSE if the user is definitely not allowed to read
968 * the contents of the file. If the user has read permission, or
969 * the code can't tell whether the user has read permission,
970 * returns TRUE (so failures must always be handled).
971 */
972gboolean
973caja_file_can_read (CajaFile *file)
974{
975 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_710
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_710
= 1; else _g_boolean_var_710 = 0; _g_boolean_var_710; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
976
977 return file->details->can_read;
978}
979
980/**
981 * caja_file_can_write:
982 *
983 * Check whether the user is allowed to write to this file.
984 *
985 * @file: The file to check.
986 *
987 * Return value: FALSE if the user is definitely not allowed to write
988 * to the file. If the user has write permission, or
989 * the code can't tell whether the user has write permission,
990 * returns TRUE (so failures must always be handled).
991 */
992gboolean
993caja_file_can_write (CajaFile *file)
994{
995 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_711
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_711
= 1; else _g_boolean_var_711 = 0; _g_boolean_var_711; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
996
997 return file->details->can_write;
998}
999
1000/**
1001 * caja_file_can_execute:
1002 *
1003 * Check whether the user is allowed to execute this file.
1004 *
1005 * @file: The file to check.
1006 *
1007 * Return value: FALSE if the user is definitely not allowed to execute
1008 * the file. If the user has execute permission, or
1009 * the code can't tell whether the user has execute permission,
1010 * returns TRUE (so failures must always be handled).
1011 */
1012gboolean
1013caja_file_can_execute (CajaFile *file)
1014{
1015 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_712
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_712
= 1; else _g_boolean_var_712 = 0; _g_boolean_var_712; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1016
1017 return file->details->can_execute;
1018}
1019
1020gboolean
1021caja_file_can_mount (CajaFile *file)
1022{
1023 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_713
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_713
= 1; else _g_boolean_var_713 = 0; _g_boolean_var_713; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1024
1025 return file->details->can_mount;
1026}
1027
1028gboolean
1029caja_file_can_unmount (CajaFile *file)
1030{
1031 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_714
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_714
= 1; else _g_boolean_var_714 = 0; _g_boolean_var_714; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1032
1033 return file->details->can_unmount ||
1034 (file->details->mount != NULL((void*)0) &&
1035 g_mount_can_unmount (file->details->mount));
1036}
1037
1038gboolean
1039caja_file_can_eject (CajaFile *file)
1040{
1041 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_715
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_715
= 1; else _g_boolean_var_715 = 0; _g_boolean_var_715; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1042
1043 return file->details->can_eject ||
1044 (file->details->mount != NULL((void*)0) &&
1045 g_mount_can_eject (file->details->mount));
1046}
1047
1048gboolean
1049caja_file_can_start (CajaFile *file)
1050{
1051 gboolean ret;
1052 GDrive *drive;
1053
1054 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_716
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_716
= 1; else _g_boolean_var_716 = 0; _g_boolean_var_716; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1055
1056 ret = FALSE(0);
1057
1058 if (file->details->can_start) {
1059 ret = TRUE(!(0));
1060 goto out;
1061 }
1062
1063 if (file->details->mount != NULL((void*)0)) {
1064 drive = g_mount_get_drive (file->details->mount);
1065 if (drive != NULL((void*)0)) {
1066 ret = g_drive_can_start (drive);
1067 g_object_unref (drive);
1068 }
1069 }
1070
1071 out:
1072 return ret;
1073}
1074
1075gboolean
1076caja_file_can_start_degraded (CajaFile *file)
1077{
1078 gboolean ret;
1079 GDrive *drive;
1080
1081 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_717
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_717
= 1; else _g_boolean_var_717 = 0; _g_boolean_var_717; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1082
1083 ret = FALSE(0);
1084
1085 if (file->details->can_start_degraded) {
1086 ret = TRUE(!(0));
1087 goto out;
1088 }
1089
1090 if (file->details->mount != NULL((void*)0)) {
1091 drive = g_mount_get_drive (file->details->mount);
1092 if (drive != NULL((void*)0)) {
1093 ret = g_drive_can_start_degraded (drive);
1094 g_object_unref (drive);
1095 }
1096 }
1097
1098 out:
1099 return ret;
1100}
1101
1102gboolean
1103caja_file_can_poll_for_media (CajaFile *file)
1104{
1105 gboolean ret;
1106 GDrive *drive;
1107
1108 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_718
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_718
= 1; else _g_boolean_var_718 = 0; _g_boolean_var_718; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1109
1110 ret = FALSE(0);
1111
1112 if (file->details->can_poll_for_media) {
1113 ret = TRUE(!(0));
1114 goto out;
1115 }
1116
1117 if (file->details->mount != NULL((void*)0)) {
1118 drive = g_mount_get_drive (file->details->mount);
1119 if (drive != NULL((void*)0)) {
1120 ret = g_drive_can_poll_for_media (drive);
1121 g_object_unref (drive);
1122 }
1123 }
1124
1125 out:
1126 return ret;
1127}
1128
1129gboolean
1130caja_file_is_media_check_automatic (CajaFile *file)
1131{
1132 gboolean ret;
1133 GDrive *drive;
1134
1135 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_719
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_719
= 1; else _g_boolean_var_719 = 0; _g_boolean_var_719; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1136
1137 ret = FALSE(0);
1138
1139 if (file->details->is_media_check_automatic) {
1140 ret = TRUE(!(0));
1141 goto out;
1142 }
1143
1144 if (file->details->mount != NULL((void*)0)) {
1145 drive = g_mount_get_drive (file->details->mount);
1146 if (drive != NULL((void*)0)) {
1147 ret = g_drive_is_media_check_automatic (drive);
1148 g_object_unref (drive);
1149 }
1150 }
1151
1152 out:
1153 return ret;
1154}
1155
1156
1157gboolean
1158caja_file_can_stop (CajaFile *file)
1159{
1160 gboolean ret;
1161 GDrive *drive;
1162
1163 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_720
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_720
= 1; else _g_boolean_var_720 = 0; _g_boolean_var_720; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1164
1165 ret = FALSE(0);
1166
1167 if (file->details->can_stop) {
1168 ret = TRUE(!(0));
1169 goto out;
1170 }
1171
1172 if (file->details->mount != NULL((void*)0)) {
1173 drive = g_mount_get_drive (file->details->mount);
1174 if (drive != NULL((void*)0)) {
1175 ret = g_drive_can_stop (drive);
1176 g_object_unref (drive);
1177 }
1178 }
1179
1180 out:
1181 return ret;
1182}
1183
1184GDriveStartStopType
1185caja_file_get_start_stop_type (CajaFile *file)
1186{
1187 GDriveStartStopType ret;
1188 GDrive *drive;
1189
1190 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_721
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_721
= 1; else _g_boolean_var_721 = 0; _g_boolean_var_721; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1191
1192 ret = G_DRIVE_START_STOP_TYPE_UNKNOWN;
1193
1194 ret = file->details->start_stop_type;
1195 if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1196 goto out;
1197
1198 if (file->details->mount != NULL((void*)0)) {
1199 drive = g_mount_get_drive (file->details->mount);
1200 if (drive != NULL((void*)0)) {
1201 ret = g_drive_get_start_stop_type (drive);
1202 g_object_unref (drive);
1203 }
1204 }
1205
1206 out:
1207 return ret;
1208}
1209
1210void
1211caja_file_mount (CajaFile *file,
1212 GMountOperation *mount_op,
1213 GCancellable *cancellable,
1214 CajaFileOperationCallback callback,
1215 gpointer callback_data)
1216{
1217 GError *error;
1218
1219 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount == NULL((void*)0)) {
1220 if (callback) {
1221 error = NULL((void*)0);
1222 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1223 _("This file cannot be mounted")dcgettext (((void*)0), "This file cannot be mounted", 5));
1224 callback (file, NULL((void*)0), error, callback_data);
1225 g_error_free (error);
1226 }
1227 } else {
1228 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount (file, mount_op, cancellable, callback, callback_data);
1229 }
1230}
1231
1232typedef struct {
1233 CajaFile *file;
1234 CajaFileOperationCallback callback;
1235 gpointer callback_data;
1236} UnmountData;
1237
1238static void
1239unmount_done (void *callback_data)
1240{
1241 UnmountData *data;
1242
1243 data = (UnmountData *)callback_data;
1244 if (data->callback) {
1245 data->callback (data->file, NULL((void*)0), NULL((void*)0), data->callback_data);
1246 }
1247 caja_file_unref (data->file);
1248 g_free (data);
1249}
1250
1251void
1252caja_file_unmount (CajaFile *file,
1253 GMountOperation *mount_op,
1254 GCancellable *cancellable,
1255 CajaFileOperationCallback callback,
1256 gpointer callback_data)
1257{
1258 GError *error;
1259 UnmountData *data;
1260
1261 if (file->details->can_unmount) {
1262 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount != NULL((void*)0)) {
1263 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount (file, mount_op, cancellable, callback, callback_data);
1264 } else {
1265 if (callback) {
1266 error = NULL((void*)0);
1267 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1268 _("This file cannot be unmounted")dcgettext (((void*)0), "This file cannot be unmounted", 5));
1269 callback (file, NULL((void*)0), error, callback_data);
1270 g_error_free (error);
1271 }
1272 }
1273 } else if (file->details->mount != NULL((void*)0) &&
1274 g_mount_can_unmount (file->details->mount)) {
1275 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1276 data->file = caja_file_ref (file);
1277 data->callback = callback;
1278 data->callback_data = callback_data;
1279 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, FALSE(0), TRUE(!(0)), unmount_done, data);
1280 } else if (callback) {
1281 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1282 }
1283}
1284
1285void
1286caja_file_eject (CajaFile *file,
1287 GMountOperation *mount_op,
1288 GCancellable *cancellable,
1289 CajaFileOperationCallback callback,
1290 gpointer callback_data)
1291{
1292 GError *error;
1293 UnmountData *data;
1294
1295 if (file->details->can_eject) {
1296 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject != NULL((void*)0)) {
1297 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject (file, mount_op, cancellable, callback, callback_data);
1298 } else {
1299 if (callback) {
1300 error = NULL((void*)0);
1301 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1302 _("This file cannot be ejected")dcgettext (((void*)0), "This file cannot be ejected", 5));
1303 callback (file, NULL((void*)0), error, callback_data);
1304 g_error_free (error);
1305 }
1306 }
1307 } else if (file->details->mount != NULL((void*)0) &&
1308 g_mount_can_eject (file->details->mount)) {
1309 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1310 data->file = caja_file_ref (file);
1311 data->callback = callback;
1312 data->callback_data = callback_data;
1313 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, TRUE(!(0)), TRUE(!(0)), unmount_done, data);
1314 } else if (callback) {
1315 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1316 }
1317}
1318
1319void
1320caja_file_start (CajaFile *file,
1321 GMountOperation *start_op,
1322 GCancellable *cancellable,
1323 CajaFileOperationCallback callback,
1324 gpointer callback_data)
1325{
1326 GError *error;
1327
1328 if ((file->details->can_start || file->details->can_start_degraded) &&
1329 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start != NULL((void*)0)) {
1330 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start (file, start_op, cancellable, callback, callback_data);
1331 } else {
1332 if (callback) {
1333 error = NULL((void*)0);
1334 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1335 _("This file cannot be started")dcgettext (((void*)0), "This file cannot be started", 5));
1336 callback (file, NULL((void*)0), error, callback_data);
1337 g_error_free (error);
1338 }
1339 }
1340}
1341
1342static void
1343file_stop_callback (GObject *source_object,
1344 GAsyncResult *res,
1345 gpointer callback_data)
1346{
1347 CajaFileOperation *op;
1348 gboolean stopped;
1349 GError *error;
1350
1351 op = callback_data;
1352
1353 error = NULL((void*)0);
1354 stopped = g_drive_stop_finish (G_DRIVE (source_object)((((GDrive*) (void *) ((source_object))))),
1355 res, &error);
1356
1357 if (!stopped &&
1358 error->domain == G_IO_ERRORg_io_error_quark() &&
1359 (error->code == G_IO_ERROR_FAILED_HANDLED ||
1360 error->code == G_IO_ERROR_CANCELLED)) {
1361 g_error_free (error);
1362 error = NULL((void*)0);
1363 }
1364
1365 caja_file_operation_complete (op, NULL((void*)0), error);
1366 if (error) {
1367 g_error_free (error);
1368 }
1369}
1370
1371void
1372caja_file_stop (CajaFile *file,
1373 GMountOperation *mount_op,
1374 GCancellable *cancellable,
1375 CajaFileOperationCallback callback,
1376 gpointer callback_data)
1377{
1378 GError *error;
1379
1380 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1381 if (file->details->can_stop) {
1382 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop (file, mount_op, cancellable, callback, callback_data);
1383 } else {
1384 if (callback) {
1385 error = NULL((void*)0);
1386 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1387 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1388 callback (file, NULL((void*)0), error, callback_data);
1389 g_error_free (error);
1390 }
1391 }
1392 } else {
1393 GDrive *drive;
1394
1395 drive = NULL((void*)0);
1396 if (file->details->mount != NULL((void*)0))
1397 drive = g_mount_get_drive (file->details->mount);
1398
1399 if (drive != NULL((void*)0) && g_drive_can_stop (drive)) {
1400 CajaFileOperation *op;
1401
1402 op = caja_file_operation_new (file, callback, callback_data);
1403 if (cancellable) {
1404 g_object_unref (op->cancellable);
1405 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
1406 }
1407
1408 g_drive_stop (drive,
1409 G_MOUNT_UNMOUNT_NONE,
1410 mount_op,
1411 op->cancellable,
1412 file_stop_callback,
1413 op);
1414 } else {
1415 if (callback) {
1416 error = NULL((void*)0);
1417 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1418 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1419 callback (file, NULL((void*)0), error, callback_data);
1420 g_error_free (error);
1421 }
1422 }
1423
1424 if (drive != NULL((void*)0)) {
1425 g_object_unref (drive);
1426 }
1427 }
1428}
1429
1430void
1431caja_file_poll_for_media (CajaFile *file)
1432{
1433 if (file->details->can_poll_for_media) {
1434 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1435 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->poll_for_media (file);
1436 }
1437 } else if (file->details->mount != NULL((void*)0)) {
1438 GDrive *drive;
1439 drive = g_mount_get_drive (file->details->mount);
1440 if (drive != NULL((void*)0)) {
1441 g_drive_poll_for_media (drive,
1442 NULL((void*)0), /* cancellable */
1443 NULL((void*)0), /* GAsyncReadyCallback */
1444 NULL((void*)0)); /* user_data */
1445 g_object_unref (drive);
1446 }
1447 }
1448}
1449
1450/**
1451 * caja_file_is_desktop_directory:
1452 *
1453 * Check whether this file is the desktop directory.
1454 *
1455 * @file: The file to check.
1456 *
1457 * Return value: TRUE if this is the physical desktop directory.
1458 */
1459gboolean
1460caja_file_is_desktop_directory (CajaFile *file)
1461{
1462 GFile *dir;
1463
1464 dir = file->details->directory->details->location;
1465
1466 if (dir == NULL((void*)0)) {
1467 return FALSE(0);
1468 }
1469
1470 return caja_is_desktop_directory_file (dir, file->details->name);
1471}
1472
1473static gboolean
1474is_desktop_file (CajaFile *file)
1475{
1476 return caja_file_is_mime_type (file, "application/x-desktop");
1477}
1478
1479static gboolean
1480can_rename_desktop_file (CajaFile *file)
1481{
1482 GFile *location;
1483 gboolean res;
1484
1485 location = caja_file_get_location (file);
1486 res = g_file_is_native (location);
1487 g_object_unref (location);
1488 return res;
1489}
1490
1491/**
1492 * caja_file_can_rename:
1493 *
1494 * Check whether the user is allowed to change the name of the file.
1495 *
1496 * @file: The file to check.
1497 *
1498 * Return value: FALSE if the user is definitely not allowed to change
1499 * the name of the file. If the user is allowed to change the name, or
1500 * the code can't tell whether the user is allowed to change the name,
1501 * returns TRUE (so rename failures must always be handled).
1502 */
1503gboolean
1504caja_file_can_rename (CajaFile *file)
1505{
1506 gboolean can_rename;
1507
1508 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_722
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_722
= 1; else _g_boolean_var_722 = 0; _g_boolean_var_722; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1509
1510 /* Nonexistent files can't be renamed. */
1511 if (caja_file_is_gone (file)) {
1512 return FALSE(0);
1513 }
1514
1515 /* Self-owned files can't be renamed */
1516 if (caja_file_is_self_owned (file)) {
1517 return FALSE(0);
1518 }
1519
1520 if ((is_desktop_file (file) && !can_rename_desktop_file (file)) ||
1521 caja_file_is_home (file)) {
1522 return FALSE(0);
1523 }
1524
1525 can_rename = TRUE(!(0));
1526
1527 /* Certain types of links can't be renamed */
1528 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1529 CajaDesktopLink *link;
1530
1531 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1532
1533 if (link != NULL((void*)0)) {
1534 can_rename = caja_desktop_link_can_rename (link);
1535 g_object_unref (link);
1536 }
1537 }
1538
1539 if (!can_rename) {
1540 return FALSE(0);
1541 }
1542
1543 return file->details->can_rename;
1544}
1545
1546gboolean
1547caja_file_can_delete (CajaFile *file)
1548{
1549 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_723
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_723
= 1; else _g_boolean_var_723 = 0; _g_boolean_var_723; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1550
1551 /* Nonexistent files can't be deleted. */
1552 if (caja_file_is_gone (file)) {
1553 return FALSE(0);
1554 }
1555
1556 /* Self-owned files can't be deleted */
1557 if (caja_file_is_self_owned (file)) {
1558 return FALSE(0);
1559 }
1560
1561 return file->details->can_delete;
1562}
1563
1564gboolean
1565caja_file_can_trash (CajaFile *file)
1566{
1567 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_724
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_724
= 1; else _g_boolean_var_724 = 0; _g_boolean_var_724; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1568
1569 /* Nonexistent files can't be deleted. */
1570 if (caja_file_is_gone (file)) {
1571 return FALSE(0);
1572 }
1573
1574 /* Self-owned files can't be deleted */
1575 if (caja_file_is_self_owned (file)) {
1576 return FALSE(0);
1577 }
1578
1579 return file->details->can_trash;
1580}
1581
1582GFile *
1583caja_file_get_location (CajaFile *file)
1584{
1585 GFile *dir;
1586
1587 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_725
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_725
= 1; else _g_boolean_var_725 = 0; _g_boolean_var_725; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1588
1589 dir = file->details->directory->details->location;
1590
1591 if (caja_file_is_self_owned (file)) {
1592 return g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir));
1593 }
1594
1595 return g_file_get_child (dir, file->details->name);
1596}
1597
1598/* Return the actual uri associated with the passed-in file. */
1599char *
1600caja_file_get_uri (CajaFile *file)
1601{
1602 char *uri;
1603 GFile *loc;
1604
1605 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_726
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_726
= 1; else _g_boolean_var_726 = 0; _g_boolean_var_726; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1606
1607 loc = caja_file_get_location (file);
1608 uri = g_file_get_uri (loc);
1609 g_object_unref (loc);
1610
1611 return uri;
1612}
1613
1614char *
1615caja_file_get_uri_scheme (CajaFile *file)
1616{
1617 GFile *loc;
1618 char *scheme;
1619
1620 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_727
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_727
= 1; else _g_boolean_var_727 = 0; _g_boolean_var_727; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1621
1622 if (file->details->directory == NULL((void*)0) ||
1623 file->details->directory->details->location == NULL((void*)0)) {
1624 return NULL((void*)0);
1625 }
1626
1627 loc = caja_directory_get_location (file->details->directory);
1628 scheme = g_file_get_uri_scheme (loc);
1629 g_object_unref (loc);
1630
1631 return scheme;
1632}
1633
1634CajaFileOperation *
1635caja_file_operation_new (CajaFile *file,
1636 CajaFileOperationCallback callback,
1637 gpointer callback_data)
1638{
1639 CajaFileOperation *op;
1640
1641 op = g_new0 (CajaFileOperation, 1)(CajaFileOperation *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (CajaFileOperation); 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; }))
;
1642 op->file = caja_file_ref (file);
1643 op->callback = callback;
1644 op->callback_data = callback_data;
1645 op->cancellable = g_cancellable_new ();
1646
1647 op->file->details->operations_in_progress = g_list_prepend
1648 (op->file->details->operations_in_progress, op);
1649
1650 return op;
1651}
1652
1653static void
1654caja_file_operation_remove (CajaFileOperation *op)
1655{
1656 op->file->details->operations_in_progress = g_list_remove
1657 (op->file->details->operations_in_progress, op);
1658}
1659
1660void
1661caja_file_operation_free (CajaFileOperation *op)
1662{
1663 caja_file_operation_remove (op);
1664 caja_file_unref (op->file);
1665 g_object_unref (op->cancellable);
1666 if (op->free_data) {
1667 op->free_data (op->data);
1668 }
1669 // Start UNDO-REDO
1670 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1671 op->undo_redo_data);
1672 // End UNDO-REDO
1673 g_free (op);
1674}
1675
1676void
1677caja_file_operation_complete (CajaFileOperation *op, GFile *result_file, GError *error)
1678{
1679 /* Claim that something changed even if the operation failed.
1680 * This makes it easier for some clients who see the "reverting"
1681 * as "changing back".
1682 */
1683 caja_file_operation_remove (op);
1684 caja_file_changed (op->file);
1685 if (op->callback) {
1686 (* op->callback) (op->file, result_file, error, op->callback_data);
1687 }
1688 caja_file_operation_free (op);
1689}
1690
1691void
1692caja_file_operation_cancel (CajaFileOperation *op)
1693{
1694 /* Cancel the operation if it's still in progress. */
1695 g_cancellable_cancel (op->cancellable);
1696}
1697
1698static void
1699rename_get_info_callback (GObject *source_object,
1700 GAsyncResult *res,
1701 gpointer callback_data)
1702{
1703 CajaFileOperation *op;
1704 GFileInfo *new_info;
1705 GError *error;
1706
1707 op = callback_data;
1708
1709 error = NULL((void*)0);
1710 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
1711 if (new_info != NULL((void*)0)) {
1712 CajaDirectory *directory;
1713 CajaFile *existing_file;
1714 char *old_name;
1715 char *old_uri;
1716 char *new_uri;
1717 const char *new_name;
1718
1719 directory = op->file->details->directory;
1720
1721 new_name = g_file_info_get_name (new_info);
1722
1723 /* If there was another file by the same name in this
1724 * directory, mark it gone.
1725 */
1726 existing_file = caja_directory_find_file_by_name (directory, new_name);
1727 if (existing_file != NULL((void*)0)) {
1728 caja_file_mark_gone (existing_file);
1729 caja_file_changed (existing_file);
1730 }
1731
1732 old_uri = caja_file_get_uri (op->file);
1733 old_name = g_strdup (op->file->details->name)g_strdup_inline (op->file->details->name);
1734
1735 update_info_and_name (op->file, new_info);
1736
1737 g_free (old_name);
1738
1739 new_uri = caja_file_get_uri (op->file);
1740 caja_directory_moved (old_uri, new_uri);
1741 g_free (new_uri);
1742 g_free (old_uri);
1743
1744 /* the rename could have affected the display name if e.g.
1745 * we're in a vfolder where the name comes from a desktop file
1746 * and a rename affects the contents of the desktop file.
1747 */
1748 if (op->file->details->got_custom_display_name) {
1749 caja_file_invalidate_attributes (op->file,
1750 CAJA_FILE_ATTRIBUTE_INFO |
1751 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1752 }
1753
1754 g_object_unref (new_info);
1755 }
1756 caja_file_operation_complete (op, NULL((void*)0), error);
1757 if (error) {
1758 g_error_free (error);
1759 }
1760}
1761
1762static void
1763rename_callback (GObject *source_object,
1764 GAsyncResult *res,
1765 gpointer callback_data)
1766{
1767 CajaFileOperation *op;
1768 GFile *new_file;
1769 GError *error;
1770
1771 op = callback_data;
1772
1773 error = NULL((void*)0);
1774 new_file = g_file_set_display_name_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
1775 res, &error);
1776
1777 if (new_file != NULL((void*)0)) {
1778 // Start UNDO-REDO
1779 caja_undostack_manager_data_set_rename_information(op->undo_redo_data, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), new_file);
1780 // End UNDO-REDO
1781 g_file_query_info_async (new_file,
1782 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
1783 0,
1784 G_PRIORITY_DEFAULT0,
1785 op->cancellable,
1786 rename_get_info_callback, op);
1787 } else {
1788 caja_file_operation_complete (op, NULL((void*)0), error);
1789 g_error_free (error);
1790 }
1791}
1792
1793static gboolean
1794name_is (CajaFile *file, const char *new_name)
1795{
1796 const char *old_name;
1797 old_name = file->details->name;
1798 return strcmp (new_name, old_name) == 0;
1799}
1800
1801void
1802caja_file_rename (CajaFile *file,
1803 const char *new_name,
1804 CajaFileOperationCallback callback,
1805 gpointer callback_data)
1806{
1807 CajaFileOperation *op;
1808 char *old_name;
1809 char *new_file_name;
1810 gboolean success, name_changed;
1811 gboolean is_renameable_desktop_file;
1812 GFile *location;
1813 GError *error;
1814
1815 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_728
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_728
= 1; else _g_boolean_var_728 = 0; _g_boolean_var_728; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
1816 g_return_if_fail (new_name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_729
; if (new_name != ((void*)0)) _g_boolean_var_729 = 1; else _g_boolean_var_729
= 0; _g_boolean_var_729; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "new_name != NULL"
); return; } } while (0)
;
1817 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_730
; if (callback != ((void*)0)) _g_boolean_var_730 = 1; else _g_boolean_var_730
= 0; _g_boolean_var_730; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
1818
1819 is_renameable_desktop_file =
1820 is_desktop_file (file) && can_rename_desktop_file (file);
1821
1822 /* Return an error for incoming names containing path separators.
1823 * But not for .desktop files as '/' are allowed for them */
1824 if (strstr (new_name, "/") != NULL((void*)0) && !is_renameable_desktop_file) {
1825 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
1826 _("Slashes are not allowed in filenames")dcgettext (((void*)0), "Slashes are not allowed in filenames"
, 5)
);
1827 (* callback) (file, NULL((void*)0), error, callback_data);
1828 g_error_free (error);
1829 return;
1830 }
1831
1832 /* Can't rename a file that's already gone.
1833 * We need to check this here because there may be a new
1834 * file with the same name.
1835 */
1836 if (caja_file_is_gone (file)) {
1837 /* Claim that something changed even if the rename
1838 * failed. This makes it easier for some clients who
1839 * see the "reverting" to the old name as "changing
1840 * back".
1841 */
1842 caja_file_changed (file);
1843 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_FOUND,
1844 _("File not found")dcgettext (((void*)0), "File not found", 5));
1845 (* callback) (file, NULL((void*)0), error, callback_data);
1846 g_error_free (error);
1847 return;
1848 }
1849
1850 /* Test the name-hasn't-changed case explicitly, for two reasons.
1851 * (1) rename returns an error if new & old are same.
1852 * (2) We don't want to send file-changed signal if nothing changed.
1853 */
1854 if (!CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
&&
1855 !is_renameable_desktop_file &&
1856 name_is (file, new_name)) {
1857 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1858 return;
1859 }
1860
1861 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1862 * case before this case.
1863 */
1864 if (caja_file_is_self_owned (file)) {
1865 /* Claim that something changed even if the rename
1866 * failed. This makes it easier for some clients who
1867 * see the "reverting" to the old name as "changing
1868 * back".
1869 */
1870 caja_file_changed (file);
1871 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1872 _("Toplevel files cannot be renamed")dcgettext (((void*)0), "Toplevel files cannot be renamed", 5));
1873
1874 (* callback) (file, NULL((void*)0), error, callback_data);
1875 g_error_free (error);
1876 return;
1877 }
1878
1879 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1880 CajaDesktopLink *link;
1881
1882 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1883 old_name = caja_file_get_display_name (file);
1884
1885 if ((old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0)) {
1886 success = TRUE(!(0));
1887 } else {
1888 success = (link != NULL((void*)0) && caja_desktop_link_rename (link, new_name));
1889 }
1890
1891 if (success) {
1892 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1893 } else {
1894 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1895 _("Unable to rename desktop icon")dcgettext (((void*)0), "Unable to rename desktop icon", 5));
1896 (* callback) (file, NULL((void*)0), error, callback_data);
1897 g_error_free (error);
1898 }
1899
1900 g_free (old_name);
1901 g_object_unref (link);
1902 return;
1903 }
1904
1905 if (is_renameable_desktop_file) {
1906 char *uri;
1907
1908 /* Don't actually change the name if the new name is the same.
1909 * This helps for the vfolder method where this can happen and
1910 * we want to minimize actual changes
1911 */
1912 uri = caja_file_get_uri (file);
1913 old_name = caja_link_local_get_text (uri);
1914 if (old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0) {
1915 success = TRUE(!(0));
1916 name_changed = FALSE(0);
1917 } else {
1918 success = caja_link_local_set_text (uri, new_name);
1919 name_changed = TRUE(!(0));
1920 }
1921 g_free (old_name);
1922 g_free (uri);
1923
1924 if (!success) {
1925 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1926 _("Unable to rename desktop file")dcgettext (((void*)0), "Unable to rename desktop file", 5));
1927 (* callback) (file, NULL((void*)0), error, callback_data);
1928 g_error_free (error);
1929 return;
1930 }
1931 if (!g_str_has_suffix(new_name, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (new_name); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_731; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_731 = 1; else _g_boolean_var_731
= 0; _g_boolean_var_731; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (new_name, ".desktop") )
)
1932 new_file_name = g_strdup_printf ("%s.desktop", new_name);
1933 else
1934 new_file_name = g_strdup_printf("%s", new_name);
1935 new_file_name = g_strdelimit (new_file_name, "/", '-');
1936
1937 if (name_is (file, new_file_name)) {
1938 if (name_changed) {
1939 caja_file_invalidate_attributes (file,
1940 CAJA_FILE_ATTRIBUTE_INFO |
1941 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1942 }
1943
1944 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1945 g_free (new_file_name);
1946 return;
1947 }
1948 } else {
1949 new_file_name = g_strdup (new_name)g_strdup_inline (new_name);
1950 }
1951
1952 /* Set up a renaming operation. */
1953 op = caja_file_operation_new (file, callback, callback_data);
1954 op->is_rename = TRUE(!(0));
1955
1956 /* Do the renaming. */
1957
1958 location = caja_file_get_location (file);
1959
1960 // Start UNDO-REDO
1961 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
1962 op->undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RENAME, 1);
1963 }
1964 // End UNDO-REDO
1965
1966 g_file_set_display_name_async (location,
1967 new_file_name,
1968 G_PRIORITY_DEFAULT0,
1969 op->cancellable,
1970 rename_callback,
1971 op);
1972 g_free (new_file_name);
1973 g_object_unref (location);
1974}
1975
1976gboolean
1977caja_file_rename_in_progress (CajaFile *file)
1978{
1979 GList *node;
1980 CajaFileOperation *op = NULL((void*)0);
1981
1982 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = node->next) {
1983 op = node->data;
1984 if (op->is_rename) {
1985 return TRUE(!(0));
1986 }
1987 }
1988 return FALSE(0);
1989}
1990
1991void
1992caja_file_cancel (CajaFile *file,
1993 CajaFileOperationCallback callback,
1994 gpointer callback_data)
1995{
1996 GList *node, *next;
1997 CajaFileOperation *op = NULL((void*)0);
1998
1999 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = next) {
2000 next = node->next;
2001 op = node->data;
2002
2003 g_assert (op->file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_732
; if (op->file == file) _g_boolean_var_732 = 1; else _g_boolean_var_732
= 0; _g_boolean_var_732; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2003, ((const char*) (__func__
)), "op->file == file"); } while (0)
;
2004 if (op->callback == callback && op->callback_data == callback_data) {
2005 caja_file_operation_cancel (op);
2006 }
2007 }
2008}
2009
2010gboolean
2011caja_file_matches_uri (CajaFile *file, const char *match_uri)
2012{
2013 GFile *match_file, *location;
2014 gboolean result;
2015
2016 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_733
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_733
= 1; else _g_boolean_var_733 = 0; _g_boolean_var_733; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2017 g_return_val_if_fail (match_uri != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_734
; if (match_uri != ((void*)0)) _g_boolean_var_734 = 1; else _g_boolean_var_734
= 0; _g_boolean_var_734; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "match_uri != NULL"
); return ((0)); } } while (0)
;
2018
2019 location = caja_file_get_location (file);
2020 match_file = g_file_new_for_uri (match_uri);
2021 result = g_file_equal (location, match_file);
2022 g_object_unref (location);
2023 g_object_unref (match_file);
2024
2025 return result;
2026}
2027
2028int
2029caja_file_compare_location (CajaFile *file_1,
2030 CajaFile *file_2)
2031{
2032 GFile *loc_a, *loc_b;
2033 gboolean res;
2034
2035 loc_a = caja_file_get_location (file_1);
2036 loc_b = caja_file_get_location (file_2);
2037
2038 res = !g_file_equal (loc_a, loc_b);
2039
2040 g_object_unref (loc_a);
2041 g_object_unref (loc_b);
2042
2043 return (gint) res;
2044}
2045
2046gboolean
2047caja_file_is_local (CajaFile *file)
2048{
2049 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_735
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_735
= 1; else _g_boolean_var_735 = 0; _g_boolean_var_735; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2050
2051 return caja_directory_is_local (file->details->directory);
2052}
2053
2054static void
2055update_link (CajaFile *link_file, CajaFile *target_file)
2056{
2057 g_assert (CAJA_IS_FILE (link_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_736
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((link_file)); GType __t = (caja_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_736
= 1; else _g_boolean_var_736 = 0; _g_boolean_var_736; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2057, ((const char*) (__func__)), "CAJA_IS_FILE (link_file)"
); } while (0)
;
2058 g_assert (CAJA_IS_FILE (target_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_737
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_file)); GType __t = (caja_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_737
= 1; else _g_boolean_var_737 = 0; _g_boolean_var_737; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2058, ((const char*) (__func__)), "CAJA_IS_FILE (target_file)"
); } while (0)
;
2059
2060 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
2061 * here then the hash table is a waste of time.
2062 */
2063}
2064
2065static GList *
2066get_link_files (CajaFile *target_file)
2067{
2068 GList **link_files;
2069
2070 if (symbolic_links == NULL((void*)0)) {
2071 link_files = NULL((void*)0);
2072 } else {
2073 char *uri;
2074
2075 uri = caja_file_get_uri (target_file);
2076 link_files = g_hash_table_lookup (symbolic_links, uri);
2077 g_free (uri);
2078 }
2079 if (link_files) {
2080 return caja_file_list_copy (*link_files);
2081 }
2082 return NULL((void*)0);
2083}
2084
2085static void
2086update_links_if_target (CajaFile *target_file)
2087{
2088 GList *link_files, *p;
2089
2090 link_files = get_link_files (target_file);
2091 for (p = link_files; p != NULL((void*)0); p = p->next) {
2092 update_link (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))), target_file);
2093 }
2094 caja_file_list_free (link_files);
2095}
2096
2097static gboolean
2098update_info_internal (CajaFile *file,
2099 GFileInfo *info,
2100 gboolean update_name)
2101{
2102 gboolean changed;
2103 gboolean is_symlink, is_hidden, is_backup, is_mountpoint;
2104 gboolean has_permissions;
2105 guint32 permissions;
2106 gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2107 gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2108 GDriveStartStopType start_stop_type;
2109 gboolean thumbnailing_failed;
2110 int uid, gid;
2111 goffset size;
2112 goffset size_on_disk;
2113 int sort_order;
2114 time_t atime, mtime, ctime, btime;
2115 time_t trash_time;
2116 const char * time_string;
2117 const char *symlink_name, *mime_type, *selinux_context, *thumbnail_path;
2118 GFileType file_type;
2119 GIcon *icon;
2120 const char *description;
2121 const char *filesystem_id;
2122 const char *trash_orig_path;
2123 const char *group, *owner, *owner_real;
2124 gboolean free_owner, free_group;
2125
2126 if (file->details->is_gone) {
2127 return FALSE(0);
2128 }
2129
2130 if (info == NULL((void*)0)) {
2131 caja_file_mark_gone (file);
2132 return TRUE(!(0));
2133 }
2134
2135 file->details->file_info_is_up_to_date = TRUE(!(0));
2136
2137 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2138 * point to the old name know that the file has been renamed.
2139 */
2140
2141 remove_from_link_hash_table (file);
2142
2143 changed = FALSE(0);
2144
2145 if (!file->details->got_file_info) {
2146 changed = TRUE(!(0));
2147 }
2148 file->details->got_file_info = TRUE(!(0));
2149
2150 changed |= caja_file_set_display_name (file,
2151 g_file_info_get_display_name (info),
2152 g_file_info_get_edit_name (info),
2153 FALSE(0));
2154
2155 file_type = g_file_info_get_file_type (info);
2156 if (file->details->type != file_type) {
2157 changed = TRUE(!(0));
2158 }
2159 file->details->type = file_type;
2160
2161 if (!file->details->got_custom_activation_uri) {
2162 const char *activation_uri;
2163
2164 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri");
2165 if (activation_uri == NULL((void*)0)) {
2166 if (file->details->activation_uri) {
2167 g_free (file->details->activation_uri);
2168 file->details->activation_uri = NULL((void*)0);
2169 changed = TRUE(!(0));
2170 }
2171 } else {
2172 char *old_activation_uri;
2173
2174 old_activation_uri = file->details->activation_uri;
2175 file->details->activation_uri = g_strdup (activation_uri)g_strdup_inline (activation_uri);
2176
2177 if (old_activation_uri) {
2178 if (strcmp (old_activation_uri,
2179 file->details->activation_uri) != 0) {
2180 changed = TRUE(!(0));
2181 }
2182 g_free (old_activation_uri);
2183 } else {
2184 changed = TRUE(!(0));
2185 }
2186 }
2187 }
2188
2189 is_symlink = g_file_info_get_is_symlink (info);
2190 if (file->details->is_symlink != is_symlink) {
2191 changed = TRUE(!(0));
2192 }
2193 file->details->is_symlink = is_symlink;
2194
2195 is_hidden = g_file_info_get_is_hidden (info);
2196 is_backup = g_file_info_get_is_backup (info);
2197 if (file->details->is_hidden != is_hidden ||
2198 file->details->is_backup != is_backup) {
2199 changed = TRUE(!(0));
2200 }
2201 file->details->is_hidden = is_hidden;
2202 file->details->is_backup = is_backup;
2203
2204 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT"unix::is-mountpoint");
2205 if (file->details->is_mountpoint != is_mountpoint) {
2206 changed = TRUE(!(0));
2207 }
2208 file->details->is_mountpoint = is_mountpoint;
2209
2210 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
2211 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");;
2212 if (file->details->has_permissions != has_permissions ||
2213 file->details->permissions != permissions) {
2214 changed = TRUE(!(0));
2215 }
2216 file->details->has_permissions = has_permissions;
2217 file->details->permissions = permissions;
2218
2219 /* We default to TRUE for this if we can't know */
2220 can_read = TRUE(!(0));
2221 can_write = TRUE(!(0));
2222 can_execute = TRUE(!(0));
2223 can_delete = TRUE(!(0));
2224 can_trash = TRUE(!(0));
2225 can_rename = TRUE(!(0));
2226 can_mount = FALSE(0);
2227 can_unmount = FALSE(0);
2228 can_eject = FALSE(0);
2229 can_start = FALSE(0);
2230 can_start_degraded = FALSE(0);
2231 can_stop = FALSE(0);
2232 can_poll_for_media = FALSE(0);
2233 is_media_check_automatic = FALSE(0);
2234 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2235 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read")) {
2236 can_read = g_file_info_get_attribute_boolean (info,
2237 G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read");
2238 }
2239 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write")) {
2240 can_write = g_file_info_get_attribute_boolean (info,
2241 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write");
2242 }
2243 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute")) {
2244 can_execute = g_file_info_get_attribute_boolean (info,
2245 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute");
2246 }
2247 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete")) {
2248 can_delete = g_file_info_get_attribute_boolean (info,
2249 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete");
2250 }
2251 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash")) {
2252 can_trash = g_file_info_get_attribute_boolean (info,
2253 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash");
2254 }
2255 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename")) {
2256 can_rename = g_file_info_get_attribute_boolean (info,
2257 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename");
2258 }
2259 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount")) {
2260 can_mount = g_file_info_get_attribute_boolean (info,
2261 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount");
2262 }
2263 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount")) {
2264 can_unmount = g_file_info_get_attribute_boolean (info,
2265 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount");
2266 }
2267 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject")) {
2268 can_eject = g_file_info_get_attribute_boolean (info,
2269 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject");
2270 }
2271 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start")) {
2272 can_start = g_file_info_get_attribute_boolean (info,
2273 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start");
2274 }
2275 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded")) {
2276 can_start_degraded = g_file_info_get_attribute_boolean (info,
2277 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded");
2278 }
2279 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop")) {
2280 can_stop = g_file_info_get_attribute_boolean (info,
2281 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop");
2282 }
2283 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type")) {
2284 start_stop_type = g_file_info_get_attribute_uint32 (info,
2285 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type");
2286 }
2287 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll")) {
2288 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2289 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll");
2290 }
2291 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic")) {
2292 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2293 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic");
2294 }
2295 if (file->details->can_read != can_read ||
2296 file->details->can_write != can_write ||
2297 file->details->can_execute != can_execute ||
2298 file->details->can_delete != can_delete ||
2299 file->details->can_trash != can_trash ||
2300 file->details->can_rename != can_rename ||
2301 file->details->can_mount != can_mount ||
2302 file->details->can_unmount != can_unmount ||
2303 file->details->can_eject != can_eject ||
2304 file->details->can_start != can_start ||
2305 file->details->can_start_degraded != can_start_degraded ||
2306 file->details->can_stop != can_stop ||
2307 file->details->start_stop_type != start_stop_type ||
2308 file->details->can_poll_for_media != can_poll_for_media ||
2309 file->details->is_media_check_automatic != is_media_check_automatic) {
2310 changed = TRUE(!(0));
2311 }
2312
2313 file->details->can_read = can_read;
2314 file->details->can_write = can_write;
2315 file->details->can_execute = can_execute;
2316 file->details->can_delete = can_delete;
2317 file->details->can_trash = can_trash;
2318 file->details->can_rename = can_rename;
2319 file->details->can_mount = can_mount;
2320 file->details->can_unmount = can_unmount;
2321 file->details->can_eject = can_eject;
2322 file->details->can_start = can_start;
2323 file->details->can_start_degraded = can_start_degraded;
2324 file->details->can_stop = can_stop;
2325 file->details->start_stop_type = start_stop_type;
2326 file->details->can_poll_for_media = can_poll_for_media;
2327 file->details->is_media_check_automatic = is_media_check_automatic;
2328
2329 free_owner = FALSE(0);
2330 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER"owner::user");
2331 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL"owner::user-real");
2332 free_group = FALSE(0);
2333 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
2334
2335 uid = -1;
2336 gid = -1;
2337 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid")) {
2338 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid");
2339 if (owner == NULL((void*)0)) {
2340 free_owner = TRUE(!(0));
2341 owner = g_strdup_printf ("%d", uid);
2342 }
2343 }
2344 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid")) {
2345 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid");
2346 if (group == NULL((void*)0)) {
2347 free_group = TRUE(!(0));
2348 group = g_strdup_printf ("%d", gid);
2349 }
2350 }
2351 if (file->details->uid != uid ||
2352 file->details->gid != gid) {
2353 changed = TRUE(!(0));
2354 }
2355 file->details->uid = uid;
2356 file->details->gid = gid;
2357
2358 if (eel_strcmp (file->details->owner, owner) != 0) {
2359 changed = TRUE(!(0));
2360 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2361 file->details->owner = g_ref_string_new_intern (owner);
2362 }
2363
2364 if (eel_strcmp (file->details->owner_real, owner_real) != 0) {
2365 changed = TRUE(!(0));
2366 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2367 file->details->owner_real = g_ref_string_new_intern (owner_real);
2368 }
2369
2370 if (eel_strcmp (file->details->group, group) != 0) {
2371 changed = TRUE(!(0));
2372 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2373 file->details->group = g_ref_string_new_intern (group);
2374 }
2375
2376 if (free_owner) {
2377 g_free ((char *)owner);
2378 }
2379 if (free_group) {
2380 g_free ((char *)group);
2381 }
2382
2383 size = -1;
2384 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size")) {
2385 size = g_file_info_get_size (info);
2386 }
2387 if (file->details->size != size) {
2388 changed = TRUE(!(0));
2389 }
2390 file->details->size = size;
2391
2392 size_on_disk = -1;
2393 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size")) {
2394 size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size");
2395 }
2396 if (file->details->size_on_disk != size_on_disk) {
2397 changed = TRUE(!(0));
2398 }
2399 file->details->size_on_disk = size_on_disk;
2400
2401 sort_order = g_file_info_get_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER"standard::sort-order");
2402 if (file->details->sort_order != sort_order) {
2403 changed = TRUE(!(0));
2404 }
2405 file->details->sort_order = sort_order;
2406
2407 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS"time::access");
2408 ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED"time::changed");
2409 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
2410 btime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED"time::created");
2411 if (file->details->atime != atime ||
2412 file->details->mtime != mtime ||
2413 file->details->ctime != ctime ||
2414 file->details->btime != btime) {
2415 if (file->details->thumbnail == NULL((void*)0)) {
2416 file->details->thumbnail_is_up_to_date = FALSE(0);
2417 }
2418
2419 changed = TRUE(!(0));
2420 }
2421 file->details->atime = atime;
2422 file->details->ctime = ctime;
2423 file->details->mtime = mtime;
2424 file->details->btime = btime;
2425
2426 if (file->details->thumbnail != NULL((void*)0) &&
2427 file->details->thumbnail_mtime != 0 &&
2428 file->details->thumbnail_mtime != mtime) {
2429 file->details->thumbnail_is_up_to_date = FALSE(0);
2430 changed = TRUE(!(0));
2431 }
2432
2433 icon = g_file_info_get_icon (info);
2434 if (!g_icon_equal (icon, file->details->icon)) {
2435 changed = TRUE(!(0));
2436
2437 if (file->details->icon) {
2438 g_object_unref (file->details->icon);
2439 }
2440 file->details->icon = g_object_ref (icon)((__typeof__ (icon)) (g_object_ref) (icon));
2441 }
2442
2443 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
2444 if (eel_strcmp (file->details->thumbnail_path, thumbnail_path) != 0) {
2445 changed = TRUE(!(0));
2446 g_free (file->details->thumbnail_path);
2447 file->details->thumbnail_path = g_strdup (thumbnail_path)g_strdup_inline (thumbnail_path);
2448 }
2449
2450 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED"thumbnail::failed");
2451 if (file->details->thumbnailing_failed != thumbnailing_failed) {
2452 changed = TRUE(!(0));
2453 file->details->thumbnailing_failed = thumbnailing_failed;
2454 }
2455
2456 symlink_name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET"standard::symlink-target");
2457
2458 if (eel_strcmp (file->details->symlink_name, symlink_name) != 0) {
2459 changed = TRUE(!(0));
2460 g_free (file->details->symlink_name);
2461 file->details->symlink_name = g_strdup (symlink_name)g_strdup_inline (symlink_name);
2462 }
2463
2464 mime_type = g_file_info_get_content_type (info);
2465 if (eel_strcmp (file->details->mime_type, mime_type) != 0) {
2466 changed = TRUE(!(0));
2467 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2468 file->details->mime_type = g_ref_string_new_intern (mime_type);
2469 }
2470
2471 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT"selinux::context");
2472 if (eel_strcmp (file->details->selinux_context, selinux_context) != 0) {
2473 changed = TRUE(!(0));
2474 g_free (file->details->selinux_context);
2475 file->details->selinux_context = g_strdup (selinux_context)g_strdup_inline (selinux_context);
2476 }
2477
2478 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION"standard::description");
2479 if (eel_strcmp (file->details->description, description) != 0) {
2480 changed = TRUE(!(0));
2481 g_free (file->details->description);
2482 file->details->description = g_strdup (description)g_strdup_inline (description);
2483 }
2484
2485 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
2486 if (eel_strcmp (file->details->filesystem_id, filesystem_id) != 0) {
2487 changed = TRUE(!(0));
2488 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
2489 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2490 }
2491
2492 trash_time = 0;
2493 time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"trash::deletion-date");
2494 if (time_string != NULL((void*)0)) {
2495#if GLIB_CHECK_VERSION(2,61,2)(2 > (2) || (2 == (2) && 80 > (61)) || (2 == (2
) && 80 == (61) && 3 >= (2)))
2496 GDateTime *dt;
2497 GTimeZone *tz;
2498 tz = g_time_zone_new_local ();
2499 dt = g_date_time_new_from_iso8601 (time_string, tz);
2500 if (dt) {
2501 trash_time = (time_t) g_date_time_to_unix (dt);
2502 g_date_time_unref (dt);
2503 }
2504 g_time_zone_unref (tz);
2505#else
2506 GTimeVal g_trash_time;
2507 g_time_val_from_iso8601 (time_string, &g_trash_time);
2508 trash_time = g_trash_time.tv_sec;
2509#endif
2510 }
2511 if (file->details->trash_time != trash_time) {
2512 changed = TRUE(!(0));
2513 file->details->trash_time = trash_time;
2514 }
2515
2516 trash_orig_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path");
2517 if (eel_strcmp (file->details->trash_orig_path, trash_orig_path) != 0) {
2518 changed = TRUE(!(0));
2519 g_free (file->details->trash_orig_path);
2520 file->details->trash_orig_path = g_strdup (trash_orig_path)g_strdup_inline (trash_orig_path);
2521 }
2522
2523 changed |=
2524 caja_file_update_metadata_from_info (file, info);
2525
2526 if (update_name) {
2527 const char *name;
2528
2529 name = g_file_info_get_name (info);
2530 if (file->details->name == NULL((void*)0) ||
2531 strcmp (file->details->name, name) != 0) {
2532 GList *node;
2533
2534 changed = TRUE(!(0));
2535
2536 node = caja_directory_begin_file_name_change
2537 (file->details->directory, file);
2538
2539 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2540 if (eel_strcmp (file->details->display_name, name) == 0) {
2541 file->details->name = g_ref_string_acquire (file->details->display_name);
2542 } else {
2543 file->details->name = g_ref_string_new (name);
2544 }
2545
2546 if (!file->details->got_custom_display_name &&
2547 g_file_info_get_display_name (info) == NULL((void*)0)) {
2548 /* If the file info's display name is NULL,
2549 * caja_file_set_display_name() did
2550 * not unset the display name.
2551 */
2552 caja_file_clear_display_name (file);
2553 }
2554
2555 caja_directory_end_file_name_change
2556 (file->details->directory, file, node);
2557 }
2558 }
2559
2560 if (changed) {
2561 add_to_link_hash_table (file);
2562
2563 update_links_if_target (file);
2564 }
2565
2566 return changed;
2567}
2568
2569static gboolean
2570update_info_and_name (CajaFile *file,
2571 GFileInfo *info)
2572{
2573 return update_info_internal (file, info, TRUE(!(0)));
2574}
2575
2576gboolean
2577caja_file_update_info (CajaFile *file,
2578 GFileInfo *info)
2579{
2580 return update_info_internal (file, info, FALSE(0));
2581}
2582
2583void
2584caja_file_refresh_info (CajaFile *file)
2585{
2586 GFile *gfile;
2587 GFileInfo *new_info;
2588
2589 gfile = caja_file_get_location (file);
2590 new_info = g_file_query_info (gfile, CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
2591 G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
2592 if (new_info != NULL((void*)0)) {
2593 if (caja_file_update_info (file, new_info)) {
2594 caja_file_changed (file);
2595 }
2596 g_object_unref (new_info);
2597 }
2598 g_object_unref (gfile);
2599}
2600
2601static gboolean
2602update_name_internal (CajaFile *file,
2603 const char *name,
2604 gboolean in_directory)
2605{
2606 GList *node;
2607
2608 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_738
; if (name != ((void*)0)) _g_boolean_var_738 = 1; else _g_boolean_var_738
= 0; _g_boolean_var_738; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2608, ((const char*) (__func__
)), "name != NULL"); } while (0)
;
2609
2610 if (file->details->is_gone) {
2611 return FALSE(0);
2612 }
2613
2614 if (name_is (file, name)) {
2615 return FALSE(0);
2616 }
2617
2618 node = NULL((void*)0);
2619 if (in_directory) {
2620 node = caja_directory_begin_file_name_change
2621 (file->details->directory, file);
2622 }
2623
2624 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2625 file->details->name = g_ref_string_new (name);
2626
2627 if (!file->details->got_custom_display_name) {
2628 caja_file_clear_display_name (file);
2629 }
2630
2631 if (in_directory) {
2632 caja_directory_end_file_name_change
2633 (file->details->directory, file, node);
2634 }
2635
2636 return TRUE(!(0));
2637}
2638
2639gboolean
2640caja_file_update_name (CajaFile *file, const char *name)
2641{
2642 gboolean ret;
2643
2644 ret = update_name_internal (file, name, TRUE(!(0)));
2645
2646 if (ret) {
2647 update_links_if_target (file);
2648 }
2649
2650 return ret;
2651}
2652
2653gboolean
2654caja_file_update_name_and_directory (CajaFile *file,
2655 const char *name,
2656 CajaDirectory *new_directory)
2657{
2658 CajaDirectory *old_directory;
2659 FileMonitors *monitors;
2660
2661 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_739
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_739
= 1; else _g_boolean_var_739 = 0; _g_boolean_var_739; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2662 g_return_val_if_fail (CAJA_IS_DIRECTORY (file->details->directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_740
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file->details->directory)); GType __t = (caja_directory_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_740 = 1; else _g_boolean_var_740 =
0; _g_boolean_var_740; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_DIRECTORY (file->details->directory)"
); return ((0)); } } while (0)
;
2663 g_return_val_if_fail (!file->details->is_gone, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_741
; if (!file->details->is_gone) _g_boolean_var_741 = 1; else
_g_boolean_var_741 = 0; _g_boolean_var_741; }), 1))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "!file->details->is_gone"); return ((0)); } } while
(0)
;
2664 g_return_val_if_fail (!caja_file_is_self_owned (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_742
; if (!caja_file_is_self_owned (file)) _g_boolean_var_742 = 1
; else _g_boolean_var_742 = 0; _g_boolean_var_742; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "!caja_file_is_self_owned (file)"); return ((
0)); } } while (0)
;
2665 g_return_val_if_fail (CAJA_IS_DIRECTORY (new_directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_743
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_directory)); GType __t = (caja_directory_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_743 = 1; else _g_boolean_var_743 = 0; _g_boolean_var_743
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "CAJA_IS_DIRECTORY (new_directory)"
); return ((0)); } } while (0)
;
2666
2667 old_directory = file->details->directory;
2668 if (old_directory == new_directory) {
2669 if (name) {
2670 return update_name_internal (file, name, TRUE(!(0)));
2671 } else {
2672 return FALSE(0);
2673 }
2674 }
2675
2676 caja_file_ref (file);
2677
2678 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2679 * point to the old name know that the file has been moved.
2680 */
2681
2682 remove_from_link_hash_table (file);
2683
2684 monitors = caja_directory_remove_file_monitors (old_directory, file);
2685 caja_directory_remove_file (old_directory, file);
2686
2687 file->details->directory = caja_directory_ref (new_directory);
2688 caja_directory_unref (old_directory);
2689
2690 if (name) {
2691 update_name_internal (file, name, FALSE(0));
2692 }
2693
2694 caja_directory_add_file (new_directory, file);
2695 caja_directory_add_file_monitors (new_directory, file, monitors);
2696
2697 add_to_link_hash_table (file);
2698
2699 update_links_if_target (file);
2700
2701 caja_file_unref (file);
2702
2703 return TRUE(!(0));
2704}
2705
2706void
2707caja_file_set_directory (CajaFile *file,
2708 CajaDirectory *new_directory)
2709{
2710 caja_file_update_name_and_directory (file, NULL((void*)0), new_directory);
2711}
2712
2713static Knowledge
2714get_item_count (CajaFile *file,
2715 guint *count)
2716{
2717 gboolean known, unreadable;
2718
2719 known = caja_file_get_directory_item_count
2720 (file, count, &unreadable);
2721 if (!known) {
2722 return UNKNOWN;
2723 }
2724 if (unreadable) {
2725 return UNKNOWABLE;
2726 }
2727 return KNOWN;
2728}
2729
2730static Knowledge
2731get_size (CajaFile *file,
2732 goffset *size,
2733 gboolean size_on_disk)
2734{
2735 /* If we tried and failed, then treat it like there is no size
2736 * to know.
2737 */
2738 if (file->details->get_info_failed) {
2739 return UNKNOWABLE;
2740 }
2741
2742 /* If the info is NULL that means we haven't even tried yet,
2743 * so it's just unknown, not unknowable.
2744 */
2745 if (!file->details->got_file_info) {
2746 return UNKNOWN;
2747 }
2748
2749 /* If we got info with no size in it, it means there is no
2750 * such thing as a size as far as mate-vfs is concerned,
2751 * so "unknowable".
2752 */
2753 if (size_on_disk && file->details->size_on_disk == -1) {
2754 return UNKNOWABLE;
2755 }
2756
2757 if (!size_on_disk && file->details->size == -1) {
2758 return UNKNOWABLE;
2759 }
2760
2761 /* We have a size! */
2762 if (size_on_disk) {
2763 *size = file->details->size_on_disk;
2764 } else {
2765 *size = file->details->size;
2766 }
2767
2768 return KNOWN;
2769}
2770
2771static Knowledge
2772get_time (CajaFile *file,
2773 time_t *time_out,
2774 CajaDateType type)
2775{
2776 time_t time;
2777
2778 /* If we tried and failed, then treat it like there is no size
2779 * to know.
2780 */
2781 if (file->details->get_info_failed) {
2782 return UNKNOWABLE;
2783 }
2784
2785 /* If the info is NULL that means we haven't even tried yet,
2786 * so it's just unknown, not unknowable.
2787 */
2788 if (!file->details->got_file_info) {
2789 return UNKNOWN;
2790 }
2791
2792 time = 0;
2793 switch (type) {
2794 case CAJA_DATE_TYPE_MODIFIED:
2795 time = file->details->mtime;
2796 break;
2797 case CAJA_DATE_TYPE_ACCESSED:
2798 time = file->details->atime;
2799 break;
2800 case CAJA_DATE_TYPE_CREATED:
2801 time = file->details->btime;
2802 break;
2803 case CAJA_DATE_TYPE_TRASHED:
2804 time = file->details->trash_time;
2805 break;
2806 default:
2807 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file.c", 2807
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2808 break;
2809 }
2810
2811 *time_out = time;
2812
2813 /* If we got info with no modification time in it, it means
2814 * there is no such thing as a modification time as far as
2815 * mate-vfs is concerned, so "unknowable".
2816 */
2817 if (time == 0) {
2818 return UNKNOWABLE;
2819 }
2820 return KNOWN;
2821}
2822
2823static int
2824compare_directories_by_count (CajaFile *file_1, CajaFile *file_2)
2825{
2826 /* Sort order:
2827 * Directories with unknown # of items
2828 * Directories with "unknowable" # of items
2829 * Directories with 0 items
2830 * Directories with n items
2831 */
2832
2833 Knowledge count_known_1, count_known_2;
2834 guint count_1, count_2;
2835
2836 count_known_1 = get_item_count (file_1, &count_1);
2837 count_known_2 = get_item_count (file_2, &count_2);
2838
2839 if (count_known_1 > count_known_2) {
2840 return -1;
2841 }
2842 if (count_known_1 < count_known_2) {
2843 return +1;
2844 }
2845
2846 /* count_known_1 and count_known_2 are equal now. Check if count
2847 * details are UNKNOWABLE or UNKNOWN.
2848 */
2849 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2850 return 0;
2851 }
2852
2853 if (count_1 < count_2) {
2854 return -1;
2855 }
2856 if (count_1 > count_2) {
2857 return +1;
2858 }
2859
2860 return 0;
2861}
2862
2863static int
2864compare_files_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2865{
2866 /* Sort order:
2867 * Files with unknown size.
2868 * Files with "unknowable" size.
2869 * Files with smaller sizes.
2870 * Files with large sizes.
2871 */
2872
2873 Knowledge size_known_1, size_known_2;
2874 goffset size_1 = 0, size_2 = 0;
2875
2876 size_known_1 = get_size (file_1, &size_1, size_on_disk);
2877 size_known_2 = get_size (file_2, &size_2, size_on_disk);
2878
2879 if (size_known_1 > size_known_2) {
2880 return -1;
2881 }
2882 if (size_known_1 < size_known_2) {
2883 return +1;
2884 }
2885
2886 /* size_known_1 and size_known_2 are equal now. Check if size
2887 * details are UNKNOWABLE or UNKNOWN
2888 */
2889 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2890 return 0;
2891 }
2892
2893 if (size_1 < size_2) {
2894 return -1;
2895 }
2896 if (size_1 > size_2) {
2897 return +1;
2898 }
2899
2900 return 0;
2901}
2902
2903static int
2904compare_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2905{
2906 /* Sort order:
2907 * Directories with n items
2908 * Directories with 0 items
2909 * Directories with "unknowable" # of items
2910 * Directories with unknown # of items
2911 * Files with large sizes.
2912 * Files with smaller sizes.
2913 * Files with "unknowable" size.
2914 * Files with unknown size.
2915 */
2916
2917 gboolean is_directory_1, is_directory_2;
2918
2919 is_directory_1 = caja_file_is_directory (file_1);
2920 is_directory_2 = caja_file_is_directory (file_2);
2921
2922 if (is_directory_1 && !is_directory_2) {
2923 return -1;
2924 }
2925 if (is_directory_2 && !is_directory_1) {
2926 return +1;
2927 }
2928
2929 if (is_directory_1) {
2930 return compare_directories_by_count (file_1, file_2);
2931 } else {
2932 return compare_files_by_size (file_1, file_2, size_on_disk);
2933 }
2934}
2935
2936static int
2937compare_by_display_name (CajaFile *file_1, CajaFile *file_2)
2938{
2939 const char *name_1, *name_2;
2940 const char *key_1, *key_2;
2941 gboolean sort_last_1, sort_last_2;
2942 int compare;
2943
2944 name_1 = caja_file_peek_display_name (file_1);
2945 name_2 = caja_file_peek_display_name (file_2);
2946
2947 sort_last_1 = name_1[0] == SORT_LAST_CHAR1'.' || name_1[0] == SORT_LAST_CHAR2'#';
2948 sort_last_2 = name_2[0] == SORT_LAST_CHAR1'.' || name_2[0] == SORT_LAST_CHAR2'#';
2949
2950 if (sort_last_1 && !sort_last_2) {
2951 compare = +1;
2952 } else if (!sort_last_1 && sort_last_2) {
2953 compare = -1;
2954 } else {
2955 key_1 = caja_file_peek_display_name_collation_key (file_1);
2956 key_2 = caja_file_peek_display_name_collation_key (file_2);
2957 compare = strcmp (key_1, key_2);
2958 }
2959
2960 return compare;
2961}
2962
2963static int
2964compare_by_directory_name (CajaFile *file_1, CajaFile *file_2)
2965{
2966 char *directory_1, *directory_2;
2967 int compare;
2968
2969 if (file_1->details->directory == file_2->details->directory) {
2970 return 0;
2971 }
2972
2973 directory_1 = caja_file_get_parent_uri_for_display (file_1);
2974 directory_2 = caja_file_get_parent_uri_for_display (file_2);
2975
2976 compare = g_utf8_collate (directory_1, directory_2);
2977
2978 g_free (directory_1);
2979 g_free (directory_2);
2980
2981 return compare;
2982}
2983
2984static gboolean
2985file_has_note (CajaFile *file)
2986{
2987 char *note;
2988 gboolean res;
2989
2990 note = caja_file_get_metadata (file, CAJA_METADATA_KEY_ANNOTATION"annotation", NULL((void*)0));
2991 res = note != NULL((void*)0) && note[0] != 0;
2992 g_free (note);
2993
2994 return res;
2995}
2996
2997static GList *
2998prepend_automatic_keywords (CajaFile *file,
2999 GList *names)
3000{
3001 /* Prepend in reverse order. */
3002 CajaFile *parent;
3003
3004 parent = caja_file_get_parent (file);
3005
3006#ifdef TRASH_IS_FAST_ENOUGH
3007 if (caja_file_is_in_trash (file)) {
3008 names = g_list_prepend
3009 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash"));
3010 }
3011#endif
3012 if (file_has_note (file)) {
3013 names = g_list_prepend
3014 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_NOTE)g_strdup_inline ("note"));
3015 }
3016
3017 /* Trash files are assumed to be read-only,
3018 * so we want to ignore them here. */
3019 if (!caja_file_can_write (file) &&
3020 !caja_file_is_in_trash (file) &&
3021 (parent == NULL((void*)0) || caja_file_can_write (parent))) {
3022 names = g_list_prepend
3023 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite"));
3024 }
3025 if (!caja_file_can_read (file)) {
3026 names = g_list_prepend
3027 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_READ)g_strdup_inline ("noread"));
3028 }
3029 if (caja_file_is_symbolic_link (file)) {
3030 names = g_list_prepend
3031 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_SYMBOLIC_LINK)g_strdup_inline ("symbolic-link"));
3032 }
3033
3034 if (parent) {
3035 caja_file_unref (parent);
3036 }
3037
3038
3039 return names;
3040}
3041
3042static void
3043fill_emblem_cache_if_needed (CajaFile *file)
3044{
3045 GList *node, *keywords;
3046 char *scanner;
3047 size_t length;
3048
3049 if (file->details->compare_by_emblem_cache != NULL((void*)0)) {
3050 /* Got a cache already. */
3051 return;
3052 }
3053
3054 keywords = caja_file_get_keywords (file);
3055
3056 /* Add up the keyword string lengths */
3057 length = 1;
3058 for (node = keywords; node != NULL((void*)0); node = node->next) {
3059 length += strlen ((const char *) node->data) + 1;
3060 }
3061
3062 /* Now that we know how large the cache struct needs to be, allocate it. */
3063 file->details->compare_by_emblem_cache = g_malloc (sizeof(CajaFileSortByEmblemCache) + length);
3064
3065 /* Copy them into the cache. */
3066 scanner = file->details->compare_by_emblem_cache->emblem_keywords;
3067 for (node = keywords; node != NULL((void*)0); node = node->next) {
3068 length = strlen ((const char *) node->data) + 1;
3069 memcpy (scanner, (const char *) node->data, length);
3070 scanner += length;
3071 }
3072
3073 /* Zero-terminate so we can tell where the list ends. */
3074 *scanner = 0;
3075
3076 g_list_free_full (keywords, g_free);
3077}
3078
3079static int
3080compare_by_emblems (CajaFile *file_1, CajaFile *file_2)
3081{
3082 const char *keyword_cache_1, *keyword_cache_2;
3083 int compare_result;
3084
3085 fill_emblem_cache_if_needed (file_1);
3086 fill_emblem_cache_if_needed (file_2);
3087
3088 /* We ignore automatic emblems, and only sort by user-added keywords. */
3089 compare_result = 0;
3090 keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords;
3091 keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords;
3092 for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) {
3093 size_t length;
3094
3095 compare_result = g_utf8_collate (keyword_cache_1, keyword_cache_2);
3096 if (compare_result != 0) {
3097 return compare_result;
3098 }
3099
3100 /* Advance to the next keyword */
3101 length = strlen (keyword_cache_1);
3102 keyword_cache_1 += length + 1;
3103 keyword_cache_2 += length + 1;
3104 }
3105
3106
3107 /* One or both is now NULL. */
3108 if (*keyword_cache_1 != '\0') {
3109 g_assert (*keyword_cache_2 == '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_744
; if (*keyword_cache_2 == '\0') _g_boolean_var_744 = 1; else _g_boolean_var_744
= 0; _g_boolean_var_744; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3109, ((const char*) (__func__
)), "*keyword_cache_2 == '\\0'"); } while (0)
;
3110 return -1;
3111 } else if (*keyword_cache_2 != '\0') {
3112 return +1;
3113 }
3114
3115 return 0;
3116}
3117
3118static int
3119compare_by_type (CajaFile *file_1, CajaFile *file_2)
3120{
3121 gboolean is_directory_1;
3122 gboolean is_directory_2;
3123 char *type_string_1;
3124 char *type_string_2;
3125 int result;
3126
3127 /* Directories go first. Then, if mime types are identical,
3128 * don't bother getting strings (for speed). This assumes
3129 * that the string is dependent entirely on the mime type,
3130 * which is true now but might not be later.
3131 */
3132 is_directory_1 = caja_file_is_directory (file_1);
3133 is_directory_2 = caja_file_is_directory (file_2);
3134
3135 if (is_directory_1 && is_directory_2) {
3136 return 0;
3137 }
3138
3139 if (is_directory_1) {
3140 return -1;
3141 }
3142
3143 if (is_directory_2) {
3144 return +1;
3145 }
3146
3147 if (file_1->details->mime_type != NULL((void*)0) &&
3148 file_2->details->mime_type != NULL((void*)0) &&
3149 strcmp (file_1->details->mime_type,
3150 file_2->details->mime_type) == 0) {
3151 return 0;
3152 }
3153
3154 type_string_1 = caja_file_get_type_as_string (file_1);
3155 type_string_2 = caja_file_get_type_as_string (file_2);
3156
3157 result = g_utf8_collate (type_string_1, type_string_2);
3158
3159 g_free (type_string_1);
3160 g_free (type_string_2);
3161
3162 return result;
3163}
3164
3165static int
3166compare_by_time (CajaFile *file_1, CajaFile *file_2, CajaDateType type)
3167{
3168 /* Sort order:
3169 * Files with unknown times.
3170 * Files with "unknowable" times.
3171 * Files with older times.
3172 * Files with newer times.
3173 */
3174
3175 Knowledge time_known_1, time_known_2;
3176 time_t time_1, time_2;
3177
3178 time_1 = 0;
3179 time_2 = 0;
3180
3181 time_known_1 = get_time (file_1, &time_1, type);
3182 time_known_2 = get_time (file_2, &time_2, type);
3183
3184 if (time_known_1 > time_known_2) {
3185 return -1;
3186 }
3187 if (time_known_1 < time_known_2) {
3188 return +1;
3189 }
3190
3191 /* Now time_known_1 is equal to time_known_2. Check whether
3192 * we failed to get modification times for files
3193 */
3194 if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3195 return 0;
3196 }
3197
3198 if (time_1 < time_2) {
3199 return -1;
3200 }
3201 if (time_1 > time_2) {
3202 return +1;
3203 }
3204
3205 return 0;
3206}
3207
3208static int
3209compare_by_full_path (CajaFile *file_1, CajaFile *file_2)
3210{
3211 int compare;
3212
3213 compare = compare_by_directory_name (file_1, file_2);
3214 if (compare != 0) {
3215 return compare;
3216 }
3217 return compare_by_display_name (file_1, file_2);
3218}
3219
3220/* prev_extension_segment:
3221 * @basename The basename of a file
3222 * @rem_chars A pointer to the amount of remaining characters
3223 *
3224 * Finds the next segment delimiter to the left. A starting character of '.' is
3225 * set to '\0'.
3226 *
3227 * Return value: The start of the previous segment (right of the dot) or
3228 * basename if there are none remaining.
3229 */
3230static char *
3231prev_extension_segment (char *basename, int *rem_chars)
3232{
3233 if (*basename == '.') {
3234 *basename = 0;
3235 basename--;
3236 (*rem_chars)--;
3237 }
3238
3239 while (*rem_chars > 0 && *basename != '.') {
3240 (*rem_chars)--;
3241 basename--;
3242 }
3243
3244 return basename + 1;
3245}
3246
3247/* is_valid_extension_segment:
3248 * @segment Part of a modifiable zero-terminated string
3249 * @segment_index The index of the current segment
3250 *
3251 * Uses a heuristic to identify valid file extensions.
3252 *
3253 * Return value: Whether the segment is part of the file extension.
3254 */
3255static gboolean
3256is_valid_extension_segment (const char *segment, int segment_index)
3257{
3258 gboolean result;
3259 gboolean has_letters;
3260 int char_offset;
3261 switch (segment_index) {
3262 case 0:
3263 /* extremely long segments are probably not part of the extension */
3264 result = strlen (segment) < 20;
3265 break;
3266 default:
3267 has_letters = FALSE(0);
3268 char_offset = 0;
3269 while (TRUE(!(0))) {
3270 char c;
3271
3272 c = *(segment + char_offset);
3273 if (c == '\0') {
3274 result = has_letters;
3275 break;
3276 }
3277 /* allow digits if there are also letters */
3278 else if (isalpha (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha
)
) {
3279 has_letters = TRUE(!(0));
3280 }
3281 /* fail if it is neither digit nor letter */
3282 else if (!isdigit (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
) {
3283 result = FALSE(0);
3284 break;
3285 }
3286
3287 if (char_offset >= SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3) {
3288 result = FALSE(0);
3289 break;
3290 }
3291 char_offset++;
3292 }
3293 }
3294 return result;
3295}
3296
3297static int
3298compare_by_extension_segments (CajaFile *file_1, CajaFile *file_2)
3299{
3300 char *name_1, *name_2;
3301 char *segment_1, *segment_2;
3302 int compare;
3303 int rem_chars_1, rem_chars_2;
3304 gboolean done_1, done_2;
3305 gboolean is_directory_1, is_directory_2;
3306 int segment_index;
3307
3308
3309 /* Directories do not have an extension */
3310 is_directory_1 = caja_file_is_directory (file_1);
3311 is_directory_2 = caja_file_is_directory (file_2);
3312
3313 if (is_directory_1 && is_directory_2) {
3314 return 0;
3315 } else if (is_directory_1) {
3316 return -1;
3317 } else if (is_directory_2) {
3318 return 1;
3319 }
3320
3321 name_1 = caja_file_get_display_name (file_1);
3322 name_2 = caja_file_get_display_name (file_2);
3323 rem_chars_1 = strlen (name_1);
3324 rem_chars_2 = strlen (name_2);
3325
3326 /* Point to one after the zero character */
3327 segment_1 = name_1 + rem_chars_1 + 1;
3328 segment_2 = name_2 + rem_chars_2 + 1;
3329
3330 segment_index = 0;
3331 do {
3332 segment_1 = prev_extension_segment (segment_1 - 1, &rem_chars_1);
3333 segment_2 = prev_extension_segment (segment_2 - 1, &rem_chars_2);
3334
3335 done_1 = rem_chars_1 <= 0 || !is_valid_extension_segment (segment_1, segment_index);
3336 done_2 = rem_chars_2 <= 0 || !is_valid_extension_segment (segment_2, segment_index);
3337 if (done_1 && !done_2) {
3338 compare = -1;
3339 break;
3340 }
3341 else if (!done_1 && done_2) {
3342 compare = 1;
3343 break;
3344 }
3345 else if (done_1 && done_2) {
3346 compare = 0;
3347 break;
3348 }
3349
3350 segment_index++;
3351 if (segment_index > SORT_BY_EXTENSION_MAX_SEGMENTS3 - 1) {
3352 break;
3353 }
3354 compare = strcmp (segment_1, segment_2);
3355 } while (compare == 0);
3356
3357 g_free (name_1);
3358 g_free (name_2);
3359
3360 return compare;
3361}
3362
3363static gchar *
3364caja_file_get_extension_as_string (CajaFile *file)
3365{
3366 int rem_chars;
3367 char *segment;
3368
3369 if (!caja_file_is_directory (file)) {
3370 char *name;
3371
3372 name = caja_file_get_display_name (file);
3373 rem_chars = strlen (name);
3374 segment = prev_extension_segment (name + rem_chars, &rem_chars);
3375
3376 if (rem_chars > 0 && is_valid_extension_segment (segment, 0)) {
3377 int segment_index;
3378 char *right_segment;
3379 char *result;
3380
3381 segment_index = 1;
3382 do {
3383 right_segment = segment;
3384 segment = prev_extension_segment (segment - 1, &rem_chars);
3385 if (rem_chars > 0 && is_valid_extension_segment (segment, segment_index)) {
3386 /* remove zero-termination of segment */
3387 *(right_segment - 1) = '.';
3388 }
3389 else {
3390 break;
3391 }
3392
3393 segment_index++;
3394 } while (segment_index < SORT_BY_EXTENSION_MAX_SEGMENTS3 + 1);
3395 result = g_strdup (right_segment)g_strdup_inline (right_segment);
3396 g_free (name);
3397 return result;
3398 }
3399 g_free (name);
3400 }
3401 return g_strdup ("")g_strdup_inline ("");
3402}
3403
3404static int
3405caja_file_compare_for_sort_internal (CajaFile *file_1,
3406 CajaFile *file_2,
3407 gboolean directories_first,
3408 gboolean reversed)
3409{
3410 gboolean is_directory_1, is_directory_2;
3411
3412 if (directories_first) {
3413 is_directory_1 = caja_file_is_directory (file_1);
3414 is_directory_2 = caja_file_is_directory (file_2);
3415
3416 if (is_directory_1 && !is_directory_2) {
3417 return -1;
3418 }
3419
3420 if (is_directory_2 && !is_directory_1) {
3421 return +1;
3422 }
3423 }
3424
3425 if (file_1->details->sort_order < file_2->details->sort_order) {
3426 return reversed ? 1 : -1;
3427 } else if (file_1->details->sort_order > file_2->details->sort_order) {
3428 return reversed ? -1 : 1;
3429 }
3430
3431 return 0;
3432}
3433
3434/**
3435 * caja_file_compare_for_sort:
3436 * @file_1: A file object
3437 * @file_2: Another file object
3438 * @sort_type: Sort criterion
3439 * @directories_first: Put all directories before any non-directories
3440 * @reversed: Reverse the order of the items, except that
3441 * the directories_first flag is still respected.
3442 *
3443 * Return value: int < 0 if @file_1 should come before file_2 in a
3444 * sorted list; int > 0 if @file_2 should come before file_1 in a
3445 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3446 * that each named sort type may actually break ties several ways, with the name
3447 * of the sort criterion being the primary but not only differentiator.
3448 **/
3449int
3450caja_file_compare_for_sort (CajaFile *file_1,
3451 CajaFile *file_2,
3452 CajaFileSortType sort_type,
3453 gboolean directories_first,
3454 gboolean reversed)
3455{
3456 int result;
3457
3458 if (file_1 == file_2) {
3459 return 0;
3460 }
3461
3462 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3463
3464 if (result == 0) {
3465 switch (sort_type) {
3466 case CAJA_FILE_SORT_BY_DISPLAY_NAME:
3467 result = compare_by_display_name (file_1, file_2);
3468 if (result == 0) {
3469 result = compare_by_directory_name (file_1, file_2);
3470 }
3471 break;
3472 case CAJA_FILE_SORT_BY_DIRECTORY:
3473 result = compare_by_full_path (file_1, file_2);
3474 break;
3475 case CAJA_FILE_SORT_BY_SIZE:
3476 /* Compare directory sizes ourselves, then if necessary
3477 * use MateVFS to compare file sizes.
3478 */
3479 result = compare_by_size (file_1, file_2, FALSE(0));
3480 if (result == 0) {
3481 result = compare_by_full_path (file_1, file_2);
3482 }
3483 break;
3484 case CAJA_FILE_SORT_BY_SIZE_ON_DISK:
3485 /* Compare directory sizes ourselves, then if necessary
3486 * use MateVFS to compare file sizes.
3487 */
3488 result = compare_by_size (file_1, file_2, TRUE(!(0)));
3489 if (result == 0) {
3490 result = compare_by_full_path (file_1, file_2);
3491 }
3492 break;
3493 case CAJA_FILE_SORT_BY_TYPE:
3494 /* MateVFS doesn't know about our special text for certain
3495 * mime types, so we handle the mime-type sorting ourselves.
3496 */
3497 result = compare_by_type (file_1, file_2);
3498 if (result == 0) {
3499 result = compare_by_full_path (file_1, file_2);
3500 }
3501 break;
3502 case CAJA_FILE_SORT_BY_MTIME:
3503 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_MODIFIED);
3504 if (result == 0) {
3505 result = compare_by_full_path (file_1, file_2);
3506 }
3507 break;
3508 case CAJA_FILE_SORT_BY_BTIME:
3509 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_CREATED);
3510 if (result == 0) {
3511 result = compare_by_full_path (file_1, file_2);
3512 }
3513 break;
3514 case CAJA_FILE_SORT_BY_ATIME:
3515 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_ACCESSED);
3516 if (result == 0) {
3517 result = compare_by_full_path (file_1, file_2);
3518 }
3519 break;
3520 case CAJA_FILE_SORT_BY_TRASHED_TIME:
3521 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_TRASHED);
3522 if (result == 0) {
3523 result = compare_by_full_path (file_1, file_2);
3524 }
3525 break;
3526 case CAJA_FILE_SORT_BY_EMBLEMS:
3527 /* MateVFS doesn't know squat about our emblems, so
3528 * we handle comparing them here, before falling back
3529 * to tie-breakers.
3530 */
3531 result = compare_by_emblems (file_1, file_2);
3532 if (result == 0) {
3533 result = compare_by_full_path (file_1, file_2);
3534 }
3535 break;
3536 case CAJA_FILE_SORT_BY_EXTENSION:
3537 result = compare_by_extension_segments (file_1, file_2);
3538 if (result == 0) {
3539 result = compare_by_full_path (file_1, file_2);
3540 }
3541 break;
3542 default:
3543 g_return_val_if_reached (0)do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "caja-file.c", 3543, ((const char*) (__func__))); return (0
); } while (0)
;
3544 }
3545
3546 if (reversed) {
3547 result = -result;
3548 }
3549 }
3550
3551 return result;
3552}
3553
3554int
3555caja_file_compare_for_sort_by_attribute_q (CajaFile *file_1,
3556 CajaFile *file_2,
3557 GQuark attribute,
3558 gboolean directories_first,
3559 gboolean reversed)
3560{
3561 int result;
3562
3563 if (file_1 == file_2) {
3564 return 0;
3565 }
3566
3567 /* Convert certain attributes into CajaFileSortTypes and use
3568 * caja_file_compare_for_sort()
3569 */
3570 if (attribute == 0 || attribute == attribute_name_q) {
3571 return caja_file_compare_for_sort (file_1, file_2,
3572 CAJA_FILE_SORT_BY_DISPLAY_NAME,
3573 directories_first,
3574 reversed);
3575 } else if (attribute == attribute_size_q) {
3576 return caja_file_compare_for_sort (file_1, file_2,
3577 CAJA_FILE_SORT_BY_SIZE,
3578 directories_first,
3579 reversed);
3580 } else if (attribute == attribute_size_on_disk_q) {
3581 return caja_file_compare_for_sort (file_1, file_2,
3582 CAJA_FILE_SORT_BY_SIZE_ON_DISK,
3583 directories_first,
3584 reversed);
3585 } else if (attribute == attribute_type_q) {
3586 return caja_file_compare_for_sort (file_1, file_2,
3587 CAJA_FILE_SORT_BY_TYPE,
3588 directories_first,
3589 reversed);
3590 } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q) {
3591 return caja_file_compare_for_sort (file_1, file_2,
3592 CAJA_FILE_SORT_BY_MTIME,
3593 directories_first,
3594 reversed);
3595 } else if (attribute == attribute_creation_date_q || attribute == attribute_date_created_q) {
3596 return caja_file_compare_for_sort (file_1, file_2,
3597 CAJA_FILE_SORT_BY_BTIME,
3598 directories_first,
3599 reversed);
3600 } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q) {
3601 return caja_file_compare_for_sort (file_1, file_2,
3602 CAJA_FILE_SORT_BY_ATIME,
3603 directories_first,
3604 reversed);
3605 } else if (attribute == attribute_trashed_on_q) {
3606 return caja_file_compare_for_sort (file_1, file_2,
3607 CAJA_FILE_SORT_BY_TRASHED_TIME,
3608 directories_first,
3609 reversed);
3610 } else if (attribute == attribute_emblems_q) {
3611 return caja_file_compare_for_sort (file_1, file_2,
3612 CAJA_FILE_SORT_BY_EMBLEMS,
3613 directories_first,
3614 reversed);
3615 } else if (attribute == attribute_extension_q) {
3616 return caja_file_compare_for_sort (file_1, file_2,
3617 CAJA_FILE_SORT_BY_EXTENSION,
3618 directories_first,
3619 reversed);
3620 }
3621
3622 /* it is a normal attribute, compare by strings */
3623
3624 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3625
3626 if (result == 0) {
3627 char *value_1;
3628 char *value_2;
3629
3630 value_1 = caja_file_get_string_attribute_q (file_1,
3631 attribute);
3632 value_2 = caja_file_get_string_attribute_q (file_2,
3633 attribute);
3634
3635 if (value_1 != NULL((void*)0) && value_2 != NULL((void*)0)) {
3636 result = strcmp (value_1, value_2);
3637 }
3638
3639 g_free (value_1);
3640 g_free (value_2);
3641
3642 if (reversed) {
3643 result = -result;
3644 }
3645 }
3646
3647 return result;
3648}
3649
3650int
3651caja_file_compare_for_sort_by_attribute (CajaFile *file_1,
3652 CajaFile *file_2,
3653 const char *attribute,
3654 gboolean directories_first,
3655 gboolean reversed)
3656{
3657 return caja_file_compare_for_sort_by_attribute_q (file_1, file_2,
3658 g_quark_from_string (attribute),
3659 directories_first,
3660 reversed);
3661}
3662
3663
3664/**
3665 * caja_file_compare_name:
3666 * @file: A file object
3667 * @pattern: A string we are comparing it with
3668 *
3669 * Return value: result of a comparison of the file name and the given pattern,
3670 * using the same sorting order as sort by name.
3671 **/
3672int
3673caja_file_compare_display_name (CajaFile *file,
3674 const char *pattern)
3675{
3676 const char *name;
3677 int result;
3678
3679 g_return_val_if_fail (pattern != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_745
; if (pattern != ((void*)0)) _g_boolean_var_745 = 1; else _g_boolean_var_745
= 0; _g_boolean_var_745; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "pattern != NULL"
); return (-1); } } while (0)
;
3680
3681 name = caja_file_peek_display_name (file);
3682 result = g_utf8_collate (name, pattern);
3683 return result;
3684}
3685
3686
3687gboolean
3688caja_file_is_hidden_file (CajaFile *file)
3689{
3690 return file->details->is_hidden;
3691}
3692
3693static gboolean
3694caja_file_is_backup_file (CajaFile *file)
3695{
3696 return file->details->is_backup;
3697}
3698
3699/**
3700 * caja_file_should_show:
3701 * @file: the file to check.
3702 * @show_hidden: whether we want to show hidden files or not.
3703 * @show_backup: whether we want to show backup files or not.
3704 *
3705 * Determines if a #CajaFile should be shown. Note that when browsing
3706 * a trash directory, this function will always return %TRUE.
3707 *
3708 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3709 */
3710gboolean
3711caja_file_should_show (CajaFile *file,
3712 gboolean show_hidden,
3713 gboolean show_foreign,
3714 gboolean show_backup)
3715{
3716 /* Never hide any files in trash. */
3717 if (caja_file_is_in_trash (file)) {
3718 return TRUE(!(0));
3719 } else {
3720 return (show_hidden || !caja_file_is_hidden_file (file)) &&
3721 (show_backup || !caja_file_is_backup_file (file)) &&
3722 (show_foreign || !(caja_file_is_in_desktop (file) && caja_file_is_foreign_link (file)));
3723 }
3724}
3725
3726gboolean
3727caja_file_is_home (CajaFile *file)
3728{
3729 GFile *dir;
3730
3731 dir = file->details->directory->details->location;
3732 if (dir == NULL((void*)0)) {
3733 return FALSE(0);
3734 }
3735
3736 return caja_is_home_directory_file (dir, file->details->name);
3737}
3738
3739gboolean
3740caja_file_is_in_desktop (CajaFile *file)
3741{
3742 if (file->details->directory->details->location) {
3743 return caja_is_desktop_directory (file->details->directory->details->location);
3744 }
3745 return FALSE(0);
3746
3747}
3748
3749static gboolean
3750filter_hidden_partition_callback (gpointer data,
3751 gpointer callback_data)
3752{
3753 CajaFile *file;
3754 FilterOptions options;
3755
3756 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
3757 options = GPOINTER_TO_INT (callback_data)((gint) (glong) (callback_data));
3758
3759 return caja_file_should_show (file,
3760 options & SHOW_HIDDEN,
3761 TRUE(!(0)),
3762 options & SHOW_BACKUP);
3763}
3764
3765GList *
3766caja_file_list_filter_hidden (GList *files,
3767 gboolean show_hidden)
3768{
3769 GList *filtered_files;
3770 GList *removed_files;
3771
3772 /* FIXME bugzilla.gnome.org 40653:
3773 * Eventually this should become a generic filtering thingy.
3774 */
3775
3776 filtered_files = caja_file_list_copy (files);
3777 filtered_files = eel_g_list_partition (filtered_files,
3778 filter_hidden_partition_callback,
3779 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0))((gpointer) (glong) ((show_hidden ? SHOW_HIDDEN : 0))),
3780 &removed_files);
3781 caja_file_list_free (removed_files);
3782
3783 return filtered_files;
3784}
3785
3786char *
3787caja_file_get_metadata (CajaFile *file,
3788 const char *key,
3789 const char *default_metadata)
3790{
3791 guint id;
3792 char *value;
3793
3794 g_return_val_if_fail (key != NULL, g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_746
; if (key != ((void*)0)) _g_boolean_var_746 = 1; else _g_boolean_var_746
= 0; _g_boolean_var_746; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(g_strdup_inline (default_metadata)); } } while (0)
;
3795 g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_747
; if (key[0] != '\0') _g_boolean_var_747 = 1; else _g_boolean_var_747
= 0; _g_boolean_var_747; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (g_strdup_inline (default_metadata)); } } while (0)
;
3796
3797 if (file == NULL((void*)0) ||
3798 file->details->metadata == NULL((void*)0)) {
3799 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3800 }
3801
3802 g_return_val_if_fail (CAJA_IS_FILE (file), g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_748
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_748
= 1; else _g_boolean_var_748 = 0; _g_boolean_var_748; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (g_strdup_inline
(default_metadata)); } } while (0)
;
3803
3804 id = caja_metadata_get_id (key);
3805 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3806
3807 if (value) {
3808 return g_strdup (value)g_strdup_inline (value);
3809 }
3810 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3811}
3812
3813GList *
3814caja_file_get_metadata_list (CajaFile *file,
3815 const char *key)
3816{
3817 guint id;
3818 char **value;
3819
3820 g_return_val_if_fail (key != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_749
; if (key != ((void*)0)) _g_boolean_var_749 = 1; else _g_boolean_var_749
= 0; _g_boolean_var_749; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(((void*)0)); } } while (0)
;
3821 g_return_val_if_fail (key[0] != '\0', NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_750
; if (key[0] != '\0') _g_boolean_var_750 = 1; else _g_boolean_var_750
= 0; _g_boolean_var_750; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (((void*)0)); } } while (0)
;
3822
3823 if (file == NULL((void*)0) ||
3824 file->details->metadata == NULL((void*)0)) {
3825 return NULL((void*)0);
3826 }
3827
3828 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_751
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_751
= 1; else _g_boolean_var_751 = 0; _g_boolean_var_751; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
3829
3830 id = caja_metadata_get_id (key);
3831 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
3832
3833 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3834
3835 if (value) {
3836 GList *res;
3837 int i;
3838
3839 res = NULL((void*)0);
3840 for (i = 0; value[i] != NULL((void*)0); i++) {
3841 res = g_list_prepend (res, g_strdup (value[i])g_strdup_inline (value[i]));
3842 }
3843 return g_list_reverse (res);
3844 }
3845
3846 return NULL((void*)0);
3847}
3848
3849void
3850caja_file_set_metadata (CajaFile *file,
3851 const char *key,
3852 const char *default_metadata,
3853 const char *metadata)
3854{
3855 const char *val;
3856
3857 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_752
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_752
= 1; else _g_boolean_var_752 = 0; _g_boolean_var_752; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3858 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_753
; if (key != ((void*)0)) _g_boolean_var_753 = 1; else _g_boolean_var_753
= 0; _g_boolean_var_753; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3859 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_754
; if (key[0] != '\0') _g_boolean_var_754 = 1; else _g_boolean_var_754
= 0; _g_boolean_var_754; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3860
3861 val = metadata;
3862 if (val == NULL((void*)0)) {
3863 val = default_metadata;
3864 }
3865
3866 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3867 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3868 set_metadata, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
;
3869}
3870
3871void
3872caja_file_set_metadata_list (CajaFile *file,
3873 const char *key,
3874 GList *list)
3875{
3876 char **val;
3877 int len, i;
3878 GList *l;
3879
3880 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_755
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_755
= 1; else _g_boolean_var_755 = 0; _g_boolean_var_755; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3881 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_756
; if (key != ((void*)0)) _g_boolean_var_756 = 1; else _g_boolean_var_756
= 0; _g_boolean_var_756; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3882 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_757
; if (key[0] != '\0') _g_boolean_var_757 = 1; else _g_boolean_var_757
= 0; _g_boolean_var_757; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3883
3884 len = g_list_length (list);
3885 val = g_new (char *, len + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
3886 for (l = list, i = 0; l != NULL((void*)0); l = l->next, i++) {
3887 val[i] = l->data;
3888 }
3889 val[i] = NULL((void*)0);
3890
3891 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3892 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3893 set_metadata_as_list, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
;
3894
3895 g_free (val);
3896}
3897
3898
3899gboolean
3900caja_file_get_boolean_metadata (CajaFile *file,
3901 const char *key,
3902 gboolean default_metadata)
3903{
3904 char *result_as_string;
3905 gboolean result;
3906
3907 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_758
; if (key != ((void*)0)) _g_boolean_var_758 = 1; else _g_boolean_var_758
= 0; _g_boolean_var_758; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3908 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_759
; if (key[0] != '\0') _g_boolean_var_759 = 1; else _g_boolean_var_759
= 0; _g_boolean_var_759; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3909
3910 if (file == NULL((void*)0)) {
3911 return default_metadata;
3912 }
3913
3914 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_760
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_760
= 1; else _g_boolean_var_760 = 0; _g_boolean_var_760; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3915
3916 result_as_string = caja_file_get_metadata
3917 (file, key, default_metadata ? "true" : "false");
3918 g_assert (result_as_string != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_761
; if (result_as_string != ((void*)0)) _g_boolean_var_761 = 1;
else _g_boolean_var_761 = 0; _g_boolean_var_761; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file.c", 3918,
((const char*) (__func__)), "result_as_string != NULL"); } while
(0)
;
3919
3920 if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3921 result = TRUE(!(0));
3922 } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3923 result = FALSE(0);
3924 } else {
3925 g_error ("boolean metadata with value other than true or false");
3926 result = default_metadata;
This statement is never executed
3927 }
3928
3929 g_free (result_as_string);
3930 return result;
3931}
3932
3933int
3934caja_file_get_integer_metadata (CajaFile *file,
3935 const char *key,
3936 int default_metadata)
3937{
3938 char *result_as_string;
3939 char default_as_string[32];
3940 int result;
3941 char c;
3942
3943 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_762
; if (key != ((void*)0)) _g_boolean_var_762 = 1; else _g_boolean_var_762
= 0; _g_boolean_var_762; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3944 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_763
; if (key[0] != '\0') _g_boolean_var_763 = 1; else _g_boolean_var_763
= 0; _g_boolean_var_763; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3945
3946 if (file == NULL((void*)0)) {
3947 return default_metadata;
3948 }
3949 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_764
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_764
= 1; else _g_boolean_var_764 = 0; _g_boolean_var_764; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3950
3951 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3952 result_as_string = caja_file_get_metadata
3953 (file, key, default_as_string);
3954
3955 /* Normally we can't get a a NULL, but we check for it here to
3956 * handle the oddball case of a non-existent directory.
3957 */
3958 if (result_as_string == NULL((void*)0)) {
3959 result = default_metadata;
3960 } else {
3961 if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3962 result = default_metadata;
3963 }
3964 g_free (result_as_string);
3965 }
3966
3967 return result;
3968}
3969
3970static gboolean
3971get_time_from_time_string (const char *time_string,
3972 time_t *time)
3973{
3974 long scanned_time;
3975 char c;
3976
3977 g_assert (time != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_765
; if (time != ((void*)0)) _g_boolean_var_765 = 1; else _g_boolean_var_765
= 0; _g_boolean_var_765; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3977, ((const char*) (__func__
)), "time != NULL"); } while (0)
;
3978
3979 /* Only accept string if it has one integer with nothing
3980 * afterwards.
3981 */
3982 if (time_string == NULL((void*)0) ||
3983 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3984 return FALSE(0);
3985 }
3986 *time = (time_t) scanned_time;
3987 return TRUE(!(0));
3988}
3989
3990time_t
3991caja_file_get_time_metadata (CajaFile *file,
3992 const char *key)
3993{
3994 time_t time;
3995 char *time_string;
3996
3997 time_string = caja_file_get_metadata (file, key, NULL((void*)0));
3998 if (!get_time_from_time_string (time_string, &time)) {
3999 time = UNDEFINED_TIME((time_t) (-1));
4000 }
4001 g_free (time_string);
4002
4003 return time;
4004}
4005
4006void
4007caja_file_set_time_metadata (CajaFile *file,
4008 const char *key,
4009 time_t time)
4010{
4011 char time_str[21];
4012 char *metadata;
4013
4014 if (time != UNDEFINED_TIME((time_t) (-1))) {
4015 /* 2^64 turns out to be 20 characters */
4016 g_snprintf (time_str, 20, "%ld", (long int)time);
4017 time_str[20] = '\0';
4018 metadata = time_str;
4019 } else {
4020 metadata = NULL((void*)0);
4021 }
4022
4023 caja_file_set_metadata (file, key, NULL((void*)0), metadata);
4024}
4025
4026
4027void
4028caja_file_set_boolean_metadata (CajaFile *file,
4029 const char *key,
4030 gboolean default_metadata,
4031 gboolean metadata)
4032{
4033 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_766
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_766
= 1; else _g_boolean_var_766 = 0; _g_boolean_var_766; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4034 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_767
; if (key != ((void*)0)) _g_boolean_var_767 = 1; else _g_boolean_var_767
= 0; _g_boolean_var_767; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4035 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_768
; if (key[0] != '\0') _g_boolean_var_768 = 1; else _g_boolean_var_768
= 0; _g_boolean_var_768; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4036
4037 caja_file_set_metadata (file, key,
4038 default_metadata ? "true" : "false",
4039 metadata ? "true" : "false");
4040}
4041
4042void
4043caja_file_set_integer_metadata (CajaFile *file,
4044 const char *key,
4045 int default_metadata,
4046 int metadata)
4047{
4048 char value_as_string[32];
4049 char default_as_string[32];
4050
4051 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_769
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_769
= 1; else _g_boolean_var_769 = 0; _g_boolean_var_769; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4052 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_770
; if (key != ((void*)0)) _g_boolean_var_770 = 1; else _g_boolean_var_770
= 0; _g_boolean_var_770; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4053 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_771
; if (key[0] != '\0') _g_boolean_var_771 = 1; else _g_boolean_var_771
= 0; _g_boolean_var_771; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4054
4055 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4056 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4057
4058 caja_file_set_metadata (file, key,
4059 default_as_string, value_as_string);
4060}
4061
4062static const char *
4063caja_file_peek_display_name_collation_key (CajaFile *file)
4064{
4065 const char *res;
4066
4067 res = file->details->display_name_collation_key;
4068 if (res == NULL((void*)0))
4069 res = "";
4070
4071 return res;
4072}
4073
4074static const char *
4075caja_file_peek_display_name (CajaFile *file)
4076{
4077 /*
4078 stefano-k: Imported 15_nautilus_file_peek_crash.patch from debian nautilus
4079 Date: Thu, 27 Jan 2011 10:22:10 +0000
4080 Subject: Prevent a crash in nautilus_file_peek_display_name() on invalid NautilusFile
4081 This is more a workaround only, expect assert failures at other
4082 places when something bad happens. There's a race condition somewhere,
4083 this patch only prevents immediate crash.
4084 Patch by Marcus Husar <marcus.husar@rose.uni-heidelberg.de>
4085 https://bugzilla.gnome.org/show_bug.cgi?id=602500
4086 */
4087 if (file == NULL((void*)0) || caja_file_is_gone (file))
4088 return "";
4089
4090 /* Default to display name based on filename if its not set yet */
4091
4092 if (file->details->display_name == NULL((void*)0)) {
4093 const char *name;
4094
4095 name = file->details->name;
4096 if (g_utf8_validate (name, -1, NULL((void*)0))) {
4097 caja_file_set_display_name (file,
4098 name,
4099 NULL((void*)0),
4100 FALSE(0));
4101 } else {
4102 char *escaped_name;
4103
4104 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
4105 caja_file_set_display_name (file,
4106 escaped_name,
4107 NULL((void*)0),
4108 FALSE(0));
4109 g_free (escaped_name);
4110 }
4111 }
4112
4113 return file->details->display_name;
4114}
4115
4116char *
4117caja_file_get_display_name (CajaFile *file)
4118{
4119 return g_strdup (caja_file_peek_display_name (file))g_strdup_inline (caja_file_peek_display_name (file));
4120}
4121
4122char *
4123caja_file_get_edit_name (CajaFile *file)
4124{
4125 const char *res;
4126
4127 res = file->details->edit_name;
4128 if (res == NULL((void*)0))
4129 res = "";
4130
4131 return g_strdup (res)g_strdup_inline (res);
4132}
4133
4134char *
4135caja_file_get_name (CajaFile *file)
4136{
4137 return g_strdup (file->details->name)g_strdup_inline (file->details->name);
4138}
4139
4140/**
4141 * caja_file_get_description:
4142 * @file: a #CajaFile.
4143 *
4144 * Gets the standard::description key from @file, if
4145 * it has been cached.
4146 *
4147 * Returns: a string containing the value of the standard::description
4148 * key, or %NULL.
4149 */
4150char *
4151caja_file_get_description (CajaFile *file)
4152{
4153 return g_strdup (file->details->description)g_strdup_inline (file->details->description);
4154}
4155
4156void
4157caja_file_monitor_add (CajaFile *file,
4158 gconstpointer client,
4159 CajaFileAttributes attributes)
4160{
4161 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_772
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_772
= 1; else _g_boolean_var_772 = 0; _g_boolean_var_772; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4162 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_773
; if (client != ((void*)0)) _g_boolean_var_773 = 1; else _g_boolean_var_773
= 0; _g_boolean_var_773; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4163
4164 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4165 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4166 monitor_add, (file, client, attributes))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
;
4167}
4168
4169void
4170caja_file_monitor_remove (CajaFile *file,
4171 gconstpointer client)
4172{
4173 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_774
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_774
= 1; else _g_boolean_var_774 = 0; _g_boolean_var_774; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4174 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_775
; if (client != ((void*)0)) _g_boolean_var_775 = 1; else _g_boolean_var_775
= 0; _g_boolean_var_775; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4175
4176 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4177 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4178 monitor_remove, (file, client))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
;
4179}
4180
4181gboolean
4182caja_file_is_launcher (CajaFile *file)
4183{
4184 return file->details->is_launcher;
4185}
4186
4187gboolean
4188caja_file_is_foreign_link (CajaFile *file)
4189{
4190 return file->details->is_foreign_link;
4191}
4192
4193gboolean
4194caja_file_is_trusted_link (CajaFile *file)
4195{
4196 return file->details->is_trusted_link;
4197}
4198
4199gboolean
4200caja_file_has_activation_uri (CajaFile *file)
4201{
4202 return file->details->activation_uri != NULL((void*)0);
4203}
4204
4205
4206/* Return the uri associated with the passed-in file, which may not be
4207 * the actual uri if the file is an desktop file or a caja
4208 * xml link file.
4209 */
4210char *
4211caja_file_get_activation_uri (CajaFile *file)
4212{
4213 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_776
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_776
= 1; else _g_boolean_var_776 = 0; _g_boolean_var_776; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4214
4215 if (file->details->activation_uri != NULL((void*)0)) {
4216 return g_strdup (file->details->activation_uri)g_strdup_inline (file->details->activation_uri);
4217 }
4218
4219 return caja_file_get_uri (file);
4220}
4221
4222GFile *
4223caja_file_get_activation_location (CajaFile *file)
4224{
4225 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_777
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_777
= 1; else _g_boolean_var_777 = 0; _g_boolean_var_777; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4226
4227 if (file->details->activation_uri != NULL((void*)0)) {
4228 return g_file_new_for_uri (file->details->activation_uri);
4229 }
4230
4231 return caja_file_get_location (file);
4232}
4233
4234
4235char *
4236caja_file_get_drop_target_uri (CajaFile *file)
4237{
4238 char *uri, *target_uri;
4239 GFile *location;
4240
4241 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_778
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_778
= 1; else _g_boolean_var_778 = 0; _g_boolean_var_778; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4242
4243 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
4244 CajaDesktopLink *link;
4245
4246 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
4247
4248 if (link != NULL((void*)0)) {
4249 location = caja_desktop_link_get_activation_location (link);
4250 g_object_unref (link);
4251 if (location != NULL((void*)0)) {
4252 uri = g_file_get_uri (location);
4253 g_object_unref (location);
4254 return uri;
4255 }
4256 }
4257 }
4258
4259 uri = caja_file_get_uri (file);
4260
4261 /* Check for Caja link */
4262 if (caja_file_is_caja_link (file)) {
4263 location = caja_file_get_location (file);
4264 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
4265 if (g_file_is_native (location)) {
4266 target_uri = caja_link_local_get_link_uri (uri);
4267 if (target_uri != NULL((void*)0)) {
4268 g_free (uri);
4269 uri = target_uri;
4270 }
4271 }
4272 g_object_unref (location);
4273 }
4274
4275 return uri;
4276}
4277
4278static gboolean
4279is_uri_relative (const char *uri)
4280{
4281 char *scheme;
4282 gboolean ret;
4283
4284 scheme = g_uri_parse_scheme (uri);
4285 ret = (scheme == NULL((void*)0));
4286 g_free (scheme);
4287 return ret;
4288}
4289
4290static char *
4291get_custom_icon_metadata_uri (CajaFile *file)
4292{
4293 char *custom_icon_uri;
4294 char *uri;
4295
4296 uri = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
4297 if (uri != NULL((void*)0) &&
4298 caja_file_is_directory (file) &&
4299 is_uri_relative (uri)) {
4300 char *dir_uri;
4301
4302 dir_uri = caja_file_get_uri (file);
4303 custom_icon_uri = g_build_filename (dir_uri, uri, NULL((void*)0));
4304 g_free (dir_uri);
4305 g_free (uri);
4306 } else {
4307 custom_icon_uri = uri;
4308 }
4309 return custom_icon_uri;
4310}
4311
4312static GIcon *
4313get_custom_icon (CajaFile *file)
4314{
4315 char *custom_icon_uri;
4316 GFile *icon_file;
4317 GIcon *icon;
4318
4319 if (file == NULL((void*)0)) {
4320 return NULL((void*)0);
4321 }
4322
4323 icon = NULL((void*)0);
4324
4325 /* Metadata takes precedence */
4326 custom_icon_uri = get_custom_icon_metadata_uri (file);
4327
4328 if (custom_icon_uri) {
4329 icon_file = g_file_new_for_uri (custom_icon_uri);
4330 icon = g_file_icon_new (icon_file);
4331 g_object_unref (icon_file);
4332 g_free (custom_icon_uri);
4333 }
4334
4335 if (icon == NULL((void*)0) && file->details->got_link_info && file->details->custom_icon != NULL((void*)0)) {
4336 if (g_path_is_absolute (file->details->custom_icon)) {
4337 icon_file = g_file_new_for_path (file->details->custom_icon);
4338 icon = g_file_icon_new (icon_file);
4339 g_object_unref (icon_file);
4340 } else {
4341 icon = g_themed_icon_new (file->details->custom_icon);
4342 }
4343 }
4344
4345 return icon;
4346}
4347
4348
4349static guint64 cached_thumbnail_limit;
4350int cached_thumbnail_size;
4351static int show_image_thumbs;
4352
4353GFilesystemPreviewType
4354caja_file_get_filesystem_use_preview (CajaFile *file)
4355{
4356 GFilesystemPreviewType use_preview;
4357 CajaFile *parent;
4358
4359 parent = caja_file_get_parent (file);
4360 if (parent != NULL((void*)0)) {
4361 use_preview = parent->details->filesystem_use_preview;
4362 g_object_unref (parent);
4363 } else {
4364 use_preview = 0;
4365 }
4366
4367 return use_preview;
4368}
4369
4370gboolean
4371caja_file_should_show_thumbnail (CajaFile *file)
4372{
4373 const char *mime_type;
4374 GFilesystemPreviewType use_preview;
4375
4376 use_preview = caja_file_get_filesystem_use_preview (file);
4377
4378 mime_type = file->details->mime_type;
4379 if (mime_type == NULL((void*)0)) {
4380 mime_type = "application/octet-stream";
4381 }
4382
4383 /* If the thumbnail has already been created, don't care about the size
4384 * of the original file.
4385 */
4386 if (caja_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4387 file->details->thumbnail_path == NULL((void*)0) &&
4388 caja_file_get_size (file) > cached_thumbnail_limit) {
4389 return FALSE(0);
4390 }
4391
4392 if (show_image_thumbs == CAJA_SPEED_TRADEOFF_ALWAYS) {
4393 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4394 return FALSE(0);
4395 } else {
4396 return TRUE(!(0));
4397 }
4398 } else if (show_image_thumbs == CAJA_SPEED_TRADEOFF_NEVER) {
4399 return FALSE(0);
4400 } else {
4401 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4402 /* file system says to never thumbnail anything */
4403 return FALSE(0);
4404 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4405 /* file system says we should treat file as if it's local */
4406 return TRUE(!(0));
4407 } else {
4408 /* only local files */
4409 return caja_file_is_local (file);
4410 }
4411 }
4412
4413 return FALSE(0);
4414}
4415
4416static void
4417prepend_icon_name (const char *name,
4418 GThemedIcon *icon)
4419{
4420 g_themed_icon_prepend_name(icon, name);
4421}
4422
4423GIcon *
4424caja_file_get_gicon (CajaFile *file,
4425 CajaFileIconFlags flags)
4426{
4427 const char * const * names;
4428 GIcon *icon, *mount_icon = NULL((void*)0), *emblemed_icon;
4429 gboolean is_folder = FALSE(0), is_preview = FALSE(0), is_inode_directory = FALSE(0);
4430
4431 if (file == NULL((void*)0)) {
4432 return NULL((void*)0);
4433 }
4434
4435 icon = get_custom_icon (file);
4436 if (icon != NULL((void*)0)) {
4437 return icon;
4438 }
4439
4440 if (file->details->icon) {
4441 icon = NULL((void*)0);
4442
4443 /* fetch the mount icon here, we'll use it later */
4444 if (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4445 flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4446 GMount *mount;
4447
4448 mount = caja_file_get_mount (file);
4449
4450 if (mount != NULL((void*)0)) {
4451 mount_icon = g_mount_get_icon (mount);
4452 g_object_unref (mount);
4453 }
4454 }
4455
4456 if (((flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4457 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4458 (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4459 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4460 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4461 ((flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4462 caja_file_has_open_window (file))) &&
4463 G_IS_THEMED_ICON (file->details->icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file->details->icon)); GType __t = ((g_themed_icon_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; }))))
) {
4464 GPtrArray *prepend_array;
4465 int i;
4466
4467 names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon)((((GThemedIcon*) (void *) ((file->details->icon))))));
4468 prepend_array = g_ptr_array_new ();
4469
4470 for (i = 0; names[i] != NULL((void*)0); i++) {
4471 const char *name;
4472
4473 name = names[i];
4474
4475 if (strcmp (name, "folder") == 0) {
4476 is_folder = TRUE(!(0));
4477 }
4478 if (strcmp (name, "inode-directory") == 0) {
4479 is_inode_directory = TRUE(!(0));
4480 }
4481 if (strcmp (name, "text-x-generic") == 0 &&
4482 (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4483 is_preview = TRUE(!(0));
4484 }
4485 }
4486
4487 /* Here, we add icons in reverse order of precedence,
4488 * because they are later prepended */
4489 if (is_preview) {
4490 g_ptr_array_add (prepend_array, "text-x-preview");
4491 }
4492
4493 /* "folder" should override "inode-directory", not the other way around */
4494 if (is_inode_directory) {
4495 g_ptr_array_add (prepend_array, "folder");
4496 }
4497 if (is_folder && (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4498 g_ptr_array_add (prepend_array, "folder-open");
4499 }
4500 if (is_folder &&
4501 (flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4502 caja_file_has_open_window (file)) {
4503 g_ptr_array_add (prepend_array, "folder-visiting");
4504 }
4505 if (is_folder &&
4506 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4507 g_ptr_array_add (prepend_array, "folder-drag-accept");
4508 }
4509
4510 if (prepend_array->len) {
4511 /* When constructing GThemed Icon, pointers from the array
4512 * are reused, but not the array itself, so the cast is safe */
4513 icon = g_themed_icon_new_from_names ((char**) names, -1);
4514 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4515 }
4516
4517 g_ptr_array_free (prepend_array, TRUE(!(0)));
4518 }
4519
4520 if (icon == NULL((void*)0)) {
4521 icon = g_object_ref (file->details->icon)((__typeof__ (file->details->icon)) (g_object_ref) (file
->details->icon))
;
4522 }
4523
4524 if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4525 mount_icon != NULL((void*)0)) {
4526 g_object_unref (icon);
4527 icon = mount_icon;
4528 } else if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4529 mount_icon != NULL((void*)0) && !g_icon_equal (mount_icon, icon)) {
4530 GEmblem *emblem;
4531
4532 emblem = g_emblem_new (mount_icon);
4533 emblemed_icon = g_emblemed_icon_new (icon, emblem);
4534
4535 g_object_unref (emblem);
4536 g_object_unref (icon);
4537 g_object_unref (mount_icon);
4538
4539 icon = emblemed_icon;
4540 } else if (mount_icon != NULL((void*)0)) {
4541 g_object_unref (mount_icon);
4542 }
4543
4544 return icon;
4545 }
4546
4547 return g_themed_icon_new ("text-x-generic");
4548}
4549
4550static GIcon *
4551get_default_file_icon (CajaFileIconFlags flags)
4552{
4553 static GIcon *fallback_icon = NULL((void*)0);
4554 static GIcon *fallback_icon_preview = NULL((void*)0);
4555 if (fallback_icon == NULL((void*)0)) {
4556 fallback_icon = g_themed_icon_new ("text-x-generic");
4557 fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4558 g_themed_icon_append_name (G_THEMED_ICON (fallback_icon_preview)((((GThemedIcon*) (void *) ((fallback_icon_preview))))), "text-x-generic");
4559 }
4560 if (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4561 return fallback_icon_preview;
4562 } else {
4563 return fallback_icon;
4564 }
4565}
4566
4567CajaIconInfo *
4568caja_file_get_icon (CajaFile *file,
4569 int size,
4570 int scale,
4571 CajaFileIconFlags flags)
4572{
4573 CajaIconInfo *icon;
4574 GIcon *gicon;
4575 GdkPixbuf *scaled_pixbuf;
4576
4577 if (file == NULL((void*)0)) {
4578 return NULL((void*)0);
4579 }
4580
4581 gicon = get_custom_icon (file);
4582 if (gicon) {
4583 GdkPixbuf *pixbuf;
4584
4585 icon = caja_icon_info_lookup (gicon, size, scale);
4586 g_object_unref (gicon);
4587
4588 pixbuf = caja_icon_info_get_pixbuf (icon);
4589 if (pixbuf != NULL((void*)0)) {
4590 if (!file->details->is_launcher && !gdk_pixbuf_get_has_alpha (pixbuf)) {
4591 caja_ui_frame_image (&pixbuf);
4592 }
4593 g_object_unref (icon);
4594
4595 icon = caja_icon_info_new_for_pixbuf (pixbuf, scale);
4596 g_object_unref (pixbuf);
4597 }
4598
4599 return icon;
4600 }
4601
4602 if (flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4603 caja_file_should_show_thumbnail (file)) {
4604 int modified_size;
4605
4606 if (flags & CAJA_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4607 modified_size = size * scale;
4608 } else {
4609 modified_size = size * scale * cached_thumbnail_size / CAJA_ICON_SIZE_STANDARD48;
4610 }
4611
4612 if (file->details->thumbnail) {
4613 int w, h, s;
4614 double thumb_scale;
4615 GdkPixbuf *raw_pixbuf;
4616
4617 raw_pixbuf = g_object_ref (file->details->thumbnail)((__typeof__ (file->details->thumbnail)) (g_object_ref)
(file->details->thumbnail))
;
4618
4619 w = gdk_pixbuf_get_width (raw_pixbuf);
4620 h = gdk_pixbuf_get_height (raw_pixbuf);
4621
4622 s = MAX (w, h)(((w) > (h)) ? (w) : (h));
4623 /* Don't scale up small thumbnails in the standard view */
4624 if (s <= cached_thumbnail_size) {
4625 thumb_scale = (double)size / CAJA_ICON_SIZE_STANDARD48;
4626 }
4627 else {
4628 thumb_scale = (double)modified_size / s;
4629 }
4630 /* Make sure that icons don't get smaller than CAJA_ICON_SIZE_SMALLEST */
4631 if (s*thumb_scale <= CAJA_ICON_SIZE_SMALLEST16) {
4632 thumb_scale = (double) CAJA_ICON_SIZE_SMALLEST16 / s;
4633 }
4634
4635 scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4636 MAX (w * thumb_scale, 1)(((w * thumb_scale) > (1)) ? (w * thumb_scale) : (1)),
4637 MAX (h * thumb_scale, 1)(((h * thumb_scale) > (1)) ? (h * thumb_scale) : (1)),
4638 GDK_INTERP_BILINEAR);
4639
4640 /* Render frames only for thumbnails of non-image files
4641 and for images with no alpha channel. */
4642 gboolean is_image = file->details->mime_type &&
4643 (strncmp (file->details->mime_type, "image/", 6) == 0);
4644 if (!is_image || !gdk_pixbuf_get_has_alpha (raw_pixbuf)) {
4645 caja_ui_frame_image (&scaled_pixbuf);
4646 }
4647
4648 g_object_unref (raw_pixbuf);
4649
4650 /* Don't scale up if more than 25%, then read the original
4651 image instead. We don't want to compare to exactly 100%,
4652 since the zoom level 150% gives thumbnails at 144, which is
4653 ok to scale up from 128. */
4654 if (modified_size > 128 * 1.25 * scale &&
4655 !file->details->thumbnail_wants_original &&
4656 caja_can_thumbnail_internally (file)) {
4657 /* Invalidate if we resize upward */
4658 file->details->thumbnail_wants_original = TRUE(!(0));
4659 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_THUMBNAIL);
4660 }
4661
4662 icon = caja_icon_info_new_for_pixbuf (scaled_pixbuf, scale);
4663 g_object_unref (scaled_pixbuf);
4664 return icon;
4665 } else if (file->details->thumbnail_path == NULL((void*)0) &&
4666 file->details->can_read &&
4667 !file->details->is_thumbnailing &&
4668 !file->details->thumbnailing_failed) {
4669 if (caja_can_thumbnail (file)) {
4670 caja_create_thumbnail (file);
4671 }
4672 }
4673 }
4674
4675 if (file->details->is_thumbnailing &&
4676 flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS)
4677 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING"image-loading");
4678 else
4679 gicon = caja_file_get_gicon (file, flags);
4680
4681 if (gicon) {
4682 icon = caja_icon_info_lookup (gicon, size, scale);
4683 g_object_unref (gicon);
4684 return icon;
4685 } else {
4686 return caja_icon_info_lookup (get_default_file_icon (flags), size, scale);
4687 }
4688}
4689
4690cairo_surface_t *
4691caja_file_get_icon_surface (CajaFile *file,
4692 int size,
4693 gboolean force_size,
4694 int scale,
4695 CajaFileIconFlags flags)
4696{
4697 CajaIconInfo *info;
4698 cairo_surface_t *surface;
4699
4700 info = caja_file_get_icon (file, size, scale, flags);
4701 if (force_size) {
4702 surface = caja_icon_info_get_surface_at_size (info, size);
4703 } else {
4704 surface = caja_icon_info_get_surface (info);
4705 }
4706 g_object_unref (info);
4707
4708 return surface;
4709}
4710
4711char *
4712caja_file_get_custom_icon (CajaFile *file)
4713{
4714 char *custom_icon;
4715
4716 if (file == NULL((void*)0)) {
4717 return NULL((void*)0);
4718 }
4719
4720 /* Metadata takes precedence */
4721 custom_icon = get_custom_icon_metadata_uri (file);
4722
4723 if (custom_icon == NULL((void*)0) && file->details->got_link_info) {
4724 custom_icon = g_strdup (file->details->custom_icon)g_strdup_inline (file->details->custom_icon);
4725 }
4726
4727 return custom_icon;
4728}
4729
4730
4731gboolean
4732caja_file_get_date (CajaFile *file,
4733 CajaDateType date_type,
4734 time_t *date)
4735{
4736 if (date != NULL((void*)0)) {
4737 *date = 0;
4738 }
4739
4740 g_return_val_if_fail (date_type == CAJA_DATE_TYPE_CHANGEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_779
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_779 = 1; else _g_boolean_var_779 = 0; _g_boolean_var_779
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4741 || date_type == CAJA_DATE_TYPE_ACCESSEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_779
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_779 = 1; else _g_boolean_var_779 = 0; _g_boolean_var_779
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4742 || date_type == CAJA_DATE_TYPE_MODIFIEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_779
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_779 = 1; else _g_boolean_var_779 = 0; _g_boolean_var_779
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4743 || date_type == CAJA_DATE_TYPE_CREATEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_779
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_779 = 1; else _g_boolean_var_779 = 0; _g_boolean_var_779
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4744 || date_type == CAJA_DATE_TYPE_TRASHEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_779
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_779 = 1; else _g_boolean_var_779 = 0; _g_boolean_var_779
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4745 || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_779
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_779 = 1; else _g_boolean_var_779 = 0; _g_boolean_var_779
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
;
4746
4747 if (file == NULL((void*)0)) {
4748 return FALSE(0);
4749 }
4750
4751 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_780
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_780
= 1; else _g_boolean_var_780 = 0; _g_boolean_var_780; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
4752
4753 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4754 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4755 get_date, (file, date_type, date))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
;
4756}
4757
4758static char *
4759caja_file_get_where_string (CajaFile *file)
4760{
4761 if (file == NULL((void*)0)) {
4762 return NULL((void*)0);
4763 }
4764
4765 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_781
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_781
= 1; else _g_boolean_var_781 = 0; _g_boolean_var_781; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4766
4767 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4768 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4769 get_where_string, (file))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
;
4770}
4771
4772static const char *TODAY_TIME_FORMATS [] = {
4773 /* Today, use special word.
4774 * strftime patterns preceeded with the widest
4775 * possible resulting string for that pattern.
4776 *
4777 * Note to localizers: You can look at man strftime
4778 * for details on the format, but you should only use
4779 * the specifiers from the C standard, not extensions.
4780 * These include "%" followed by one of
4781 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
4782 * in the Caja version of strftime that can be
4783 * used (and match GNU extensions). Putting a "-"
4784 * between the "%" and any numeric directive will turn
4785 * off zero padding, and putting a "_" there will use
4786 * space padding instead of zero padding.
4787 */
4788 N_("today at 00:00:00 PM")("today at 00:00:00 PM"),
4789 N_("today at %-I:%M:%S %p")("today at %-I:%M:%S %p"),
4790
4791 N_("today at 00:00 PM")("today at 00:00 PM"),
4792 N_("today at %-I:%M %p")("today at %-I:%M %p"),
4793
4794 N_("today, 00:00 PM")("today, 00:00 PM"),
4795 N_("today, %-I:%M %p")("today, %-I:%M %p"),
4796
4797 N_("today")("today"),
4798 N_("today")("today"),
4799
4800 NULL((void*)0)
4801};
4802
4803static const char *YESTERDAY_TIME_FORMATS [] = {
4804 /* Yesterday, use special word.
4805 * Note to localizers: Same issues as "today" string.
4806 */
4807 N_("yesterday at 00:00:00 PM")("yesterday at 00:00:00 PM"),
4808 N_("yesterday at %-I:%M:%S %p")("yesterday at %-I:%M:%S %p"),
4809
4810 N_("yesterday at 00:00 PM")("yesterday at 00:00 PM"),
4811 N_("yesterday at %-I:%M %p")("yesterday at %-I:%M %p"),
4812
4813 N_("yesterday, 00:00 PM")("yesterday, 00:00 PM"),
4814 N_("yesterday, %-I:%M %p")("yesterday, %-I:%M %p"),
4815
4816 N_("yesterday")("yesterday"),
4817 N_("yesterday")("yesterday"),
4818
4819 NULL((void*)0)
4820};
4821
4822static const char *CURRENT_WEEK_TIME_FORMATS [] = {
4823 /* Current week, include day of week.
4824 * Note to localizers: Same issues as "today" string.
4825 * The width measurement templates correspond to
4826 * the day/month name with the most letters.
4827 */
4828 N_("Wednesday, September 00 0000 at 00:00:00 PM")("Wednesday, September 00 0000 at 00:00:00 PM"),
4829 N_("%A, %B %-d %Y at %-I:%M:%S %p")("%A, %B %-d %Y at %-I:%M:%S %p"),
4830
4831 N_("Mon, Oct 00 0000 at 00:00:00 PM")("Mon, Oct 00 0000 at 00:00:00 PM"),
4832 N_("%a, %b %-d %Y at %-I:%M:%S %p")("%a, %b %-d %Y at %-I:%M:%S %p"),
4833
4834 N_("Mon, Oct 00 0000 at 00:00 PM")("Mon, Oct 00 0000 at 00:00 PM"),
4835 N_("%a, %b %-d %Y at %-I:%M %p")("%a, %b %-d %Y at %-I:%M %p"),
4836
4837 N_("Oct 00 0000 at 00:00 PM")("Oct 00 0000 at 00:00 PM"),
4838 N_("%b %-d %Y at %-I:%M %p")("%b %-d %Y at %-I:%M %p"),
4839
4840 N_("Oct 00 0000, 00:00 PM")("Oct 00 0000, 00:00 PM"),
4841 N_("%b %-d %Y, %-I:%M %p")("%b %-d %Y, %-I:%M %p"),
4842
4843 N_("00/00/00, 00:00 PM")("00/00/00, 00:00 PM"),
4844 N_("%m/%-d/%y, %-I:%M %p")("%m/%-d/%y, %-I:%M %p"),
4845
4846 N_("00/00/00")("00/00/00"),
4847 N_("%m/%d/%y")("%m/%d/%y"),
4848
4849 NULL((void*)0)
4850};
4851
4852static char *
4853caja_file_fit_date_as_string (CajaFile *file,
4854 CajaDateType date_type,
4855 int width,
4856 CajaWidthMeasureCallback measure_callback,
4857 CajaTruncateCallback truncate_callback,
4858 void *measure_context)
4859{
4860 time_t file_time_raw;
4861 const char **formats;
4862 const char *format;
4863 char *date_string;
4864 gchar *result = NULL((void*)0);
4865 int i;
4866 GDateTime *date_time, *today, *end_of_today;
4867 GTimeSpan file_date_age;
4868
4869 if (!caja_file_get_date (file, date_type, &file_time_raw)) {
4870 return NULL((void*)0);
4871 }
4872
4873 date_time = g_date_time_new_from_unix_local (file_time_raw);
4874
4875 if (date_format_pref == CAJA_DATE_FORMAT_LOCALE) {
4876 result = g_date_time_format (date_time, "%c");
4877 goto out;
4878 } else if (date_format_pref == CAJA_DATE_FORMAT_ISO) {
4879 result = g_date_time_format (date_time, "%Y-%m-%d %H:%M:%S");
4880 goto out;
4881 }
4882
4883 today = g_date_time_new_now_local ();
4884 end_of_today = g_date_time_add_full (today, 0, 0, 1,
4885 -1 * g_date_time_get_hour (today),
4886 -1 * g_date_time_get_minute (today),
4887 -1.0 * g_date_time_get_seconds (today));
4888 g_date_time_unref (today);
4889
4890 file_date_age = g_date_time_difference (end_of_today, date_time);
4891 g_date_time_unref (end_of_today);
4892
4893 /* Format varies depending on how old the date is. This minimizes
4894 * the length (and thus clutter & complication) of typical dates
4895 * while providing sufficient detail for recent dates to make
4896 * them maximally understandable at a glance. Keep all format
4897 * strings separate rather than combining bits & pieces for
4898 * internationalization's sake.
4899 */
4900
4901 if (file_date_age <= 0 || file_date_age > 2 * G_TIME_SPAN_DAY((86400000000L))) {
4902 formats = CURRENT_WEEK_TIME_FORMATS;
4903 } else if (file_date_age > G_TIME_SPAN_DAY((86400000000L))) {
4904 formats = YESTERDAY_TIME_FORMATS;
4905 } else {
4906 formats = TODAY_TIME_FORMATS;
4907 }
4908
4909 /* Find the date format that just fits the required width. Instead of measuring
4910 * the resulting string width directly, measure the width of a template that represents
4911 * the widest possible version of a date in a given format. This is done by using M, m
4912 * and 0 for the variable letters/digits respectively.
4913 */
4914 format = NULL((void*)0);
4915
4916 for (i = 0; ; i += 2) {
4917 const char *width_template;
4918
4919 width_template = (formats [i] ? _(formats [i])dcgettext (((void*)0), formats [i], 5) : NULL((void*)0));
4920 if (width_template == NULL((void*)0)) {
4921 /* no more formats left */
4922 g_assert (format != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_782
; if (format != ((void*)0)) _g_boolean_var_782 = 1; else _g_boolean_var_782
= 0; _g_boolean_var_782; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 4922, ((const char*) (__func__
)), "format != NULL"); } while (0)
;
4923
4924 /* Can't fit even the shortest format -- return an ellipsized form in the
4925 * shortest format
4926 */
4927
4928 date_string = g_date_time_format (date_time, format);
4929
4930 if (truncate_callback == NULL((void*)0)) {
4931 result = date_string;
4932 break;
4933 }
4934
4935 result = (* truncate_callback) (date_string, width, measure_context);
4936 g_free (date_string);
4937 break;
4938 }
4939
4940 format = _(formats [i + 1])dcgettext (((void*)0), formats [i + 1], 5);
4941
4942 if (measure_callback == NULL((void*)0)) {
4943 /* don't care about fitting the width */
4944 break;
4945 }
4946
4947 if ((* measure_callback) (width_template, measure_context) <= width) {
4948 /* The template fits, this is the format we can fit. */
4949 break;
4950 }
4951 }
4952
4953 if (result == NULL((void*)0)) {
4954 result = g_date_time_format (date_time, format);
4955 }
4956
4957out:
4958 g_date_time_unref (date_time);
4959 return result;
4960}
4961
4962/**
4963 * caja_file_fit_modified_date_as_string:
4964 *
4965 * Get a user-displayable string representing a file modification date,
4966 * truncated to @width using the measuring and truncating callbacks.
4967 * @file: CajaFile representing the file in question.
4968 * @width: The desired resulting string width.
4969 * @measure_callback: The callback used to measure the string width.
4970 * @truncate_callback: The callback used to truncate the string to a desired width.
4971 * @measure_context: Data neede when measuring and truncating.
4972 *
4973 * Returns: Newly allocated string ready to display to the user.
4974 *
4975 **/
4976char *
4977caja_file_fit_modified_date_as_string (CajaFile *file,
4978 int width,
4979 CajaWidthMeasureCallback measure_callback,
4980 CajaTruncateCallback truncate_callback,
4981 void *measure_context)
4982{
4983 return caja_file_fit_date_as_string (file, CAJA_DATE_TYPE_MODIFIED,
4984 width, measure_callback, truncate_callback, measure_context);
4985}
4986
4987static char *
4988caja_file_get_trash_original_file_parent_as_string (CajaFile *file)
4989{
4990 if (file->details->trash_orig_path != NULL((void*)0)) {
4991 CajaFile *orig_file, *parent;
4992 GFile *location;
4993 char *filename;
4994
4995 orig_file = caja_file_get_trash_original_file (file);
4996 parent = caja_file_get_parent (orig_file);
4997 location = caja_file_get_location (parent);
4998
4999 filename = g_file_get_parse_name (location);
5000
5001 g_object_unref (location);
5002 caja_file_unref (parent);
5003 caja_file_unref (orig_file);
5004
5005 return filename;
5006 }
5007
5008 return NULL((void*)0);
5009}
5010
5011/**
5012 * caja_file_get_date_as_string:
5013 *
5014 * Get a user-displayable string representing a file modification date.
5015 * The caller is responsible for g_free-ing this string.
5016 * @file: CajaFile representing the file in question.
5017 *
5018 * Returns: Newly allocated string ready to display to the user.
5019 *
5020 **/
5021static char *
5022caja_file_get_date_as_string (CajaFile *file, CajaDateType date_type)
5023{
5024 return caja_file_fit_date_as_string (file, date_type,
5025 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5026}
5027
5028static CajaSpeedTradeoffValue show_directory_item_count;
5029static CajaSpeedTradeoffValue show_text_in_icons;
5030
5031static void
5032show_text_in_icons_changed_callback (gpointer callback_data)
5033{
5034 show_text_in_icons = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS"show-icon-text");
5035}
5036
5037static void
5038show_directory_item_count_changed_callback (gpointer callback_data)
5039{
5040 show_directory_item_count = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS"show-directory-item-counts");
5041}
5042
5043static gboolean
5044get_speed_tradeoff_preference_for_file (CajaFile *file, CajaSpeedTradeoffValue value)
5045{
5046 GFilesystemPreviewType use_preview;
5047
5048 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_783
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_783
= 1; else _g_boolean_var_783 = 0; _g_boolean_var_783; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5049
5050 use_preview = caja_file_get_filesystem_use_preview (file);
5051
5052 if (value == CAJA_SPEED_TRADEOFF_ALWAYS) {
5053 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5054 return FALSE(0);
5055 } else {
5056 return TRUE(!(0));
5057 }
5058 }
5059
5060 if (value == CAJA_SPEED_TRADEOFF_NEVER) {
5061 return FALSE(0);
5062 }
5063
5064 g_assert (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_784
; if (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY) _g_boolean_var_784
= 1; else _g_boolean_var_784 = 0; _g_boolean_var_784; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5064, ((const char*) (__func__)), "value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY"
); } while (0)
;
5065
5066 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5067 /* file system says to never preview anything */
5068 return FALSE(0);
5069 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
5070 /* file system says we should treat file as if it's local */
5071 return TRUE(!(0));
5072 } else {
5073 /* only local files */
5074 return caja_file_is_local (file);
5075 }
5076}
5077
5078gboolean
5079caja_file_should_show_directory_item_count (CajaFile *file)
5080{
5081 static gboolean show_directory_item_count_callback_added = FALSE(0);
5082
5083 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_785
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_785
= 1; else _g_boolean_var_785 = 0; _g_boolean_var_785; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5084
5085 if (file->details->mime_type &&
5086 strcmp (file->details->mime_type, "x-directory/smb-share") == 0) {
5087 return FALSE(0);
5088 }
5089
5090 /* Add the callback once for the life of our process */
5091 if (!show_directory_item_count_callback_added) {
5092 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5093 "changed::" CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5094 G_CALLBACK(show_directory_item_count_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5095 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5096 show_directory_item_count_callback_added = TRUE(!(0));
5097
5098 /* Peek for the first time */
5099 show_directory_item_count_changed_callback (NULL((void*)0));
5100 }
5101
5102 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5103}
5104
5105gboolean
5106caja_file_should_show_type (CajaFile *file)
5107{
5108 char *uri;
5109 gboolean ret;
5110
5111 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_786
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_786
= 1; else _g_boolean_var_786 = 0; _g_boolean_var_786; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5112
5113 uri = caja_file_get_uri (file);
5114 ret = ((strcmp (uri, "computer:///") != 0) &&
5115 (strcmp (uri, "network:///") != 0) &&
5116 (strcmp (uri, "smb:///") != 0));
5117 g_free (uri);
5118
5119 return ret;
5120}
5121
5122gboolean
5123caja_file_should_get_top_left_text (CajaFile *file)
5124{
5125 static gboolean show_text_in_icons_callback_added = FALSE(0);
5126
5127 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_787
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_787
= 1; else _g_boolean_var_787 = 0; _g_boolean_var_787; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5128
5129 /* Add the callback once for the life of our process */
5130 if (!show_text_in_icons_callback_added) {
5131 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5132 "changed::" CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5133 G_CALLBACK (show_text_in_icons_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5134 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5135 show_text_in_icons_callback_added = TRUE(!(0));
5136
5137 /* Peek for the first time */
5138 show_text_in_icons_changed_callback (NULL((void*)0));
5139 }
5140
5141 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_ALWAYS) {
5142 return TRUE(!(0));
5143 }
5144
5145 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_NEVER) {
5146 return FALSE(0);
5147 }
5148
5149 return get_speed_tradeoff_preference_for_file (file, show_text_in_icons);
5150}
5151
5152/**
5153 * caja_file_get_directory_item_count
5154 *
5155 * Get the number of items in a directory.
5156 * @file: CajaFile representing a directory.
5157 * @count: Place to put count.
5158 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5159 * the item count from being read on this directory. Otherwise set to FALSE.
5160 *
5161 * Returns: TRUE if count is available.
5162 *
5163 **/
5164gboolean
5165caja_file_get_directory_item_count (CajaFile *file,
5166 guint *count,
5167 gboolean *count_unreadable)
5168{
5169 if (count != NULL((void*)0)) {
5170 *count = 0;
5171 }
5172 if (count_unreadable != NULL((void*)0)) {
5173 *count_unreadable = FALSE(0);
5174 }
5175
5176 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_788
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_788
= 1; else _g_boolean_var_788 = 0; _g_boolean_var_788; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5177
5178 if (!caja_file_is_directory (file)) {
5179 return FALSE(0);
5180 }
5181
5182 if (!caja_file_should_show_directory_item_count (file)) {
5183 return FALSE(0);
5184 }
5185
5186 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5187 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5188 get_item_count, (file, count, count_unreadable))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
;
5189}
5190
5191/**
5192 * caja_file_get_deep_counts
5193 *
5194 * Get the statistics about items inside a directory.
5195 * @file: CajaFile representing a directory or file.
5196 * @directory_count: Place to put count of directories inside.
5197 * @files_count: Place to put count of files inside.
5198 * @unreadable_directory_count: Number of directories encountered
5199 * that were unreadable.
5200 * @total_size: Total size of all files and directories visited.
5201 * @total_size_on_disk: Total size on disk of all files and directories visited.
5202 * @force: Whether the deep counts should even be collected if
5203 * caja_file_should_show_directory_item_count returns FALSE
5204 * for this file.
5205 *
5206 * Returns: Status to indicate whether sizes are available.
5207 *
5208 **/
5209CajaRequestStatus
5210caja_file_get_deep_counts (CajaFile *file,
5211 guint *directory_count,
5212 guint *file_count,
5213 guint *unreadable_directory_count,
5214 goffset *total_size,
5215 goffset *total_size_on_disk,
5216 gboolean force)
5217{
5218 if (directory_count != NULL((void*)0)) {
5219 *directory_count = 0;
5220 }
5221 if (file_count != NULL((void*)0)) {
5222 *file_count = 0;
5223 }
5224 if (unreadable_directory_count != NULL((void*)0)) {
5225 *unreadable_directory_count = 0;
5226 }
5227 if (total_size != NULL((void*)0)) {
5228 *total_size = 0;
5229 }
5230 if (total_size_on_disk != NULL((void*)0)) {
5231 *total_size_on_disk = 0;
5232 }
5233
5234 g_return_val_if_fail (CAJA_IS_FILE (file), CAJA_REQUEST_DONE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_789
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_789
= 1; else _g_boolean_var_789 = 0; _g_boolean_var_789; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (CAJA_REQUEST_DONE
); } } while (0)
;
5235
5236 if (!force && !caja_file_should_show_directory_item_count (file)) {
5237 /* Set field so an existing value isn't treated as up-to-date
5238 * when preference changes later.
5239 */
5240 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5241 return file->details->deep_counts_status;
5242 }
5243
5244 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5245 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5246 get_deep_counts, (file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5247 directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5248 file_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5249 unreadable_directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5250 total_size,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5251 total_size_on_disk))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
;
5252}
5253
5254void
5255caja_file_recompute_deep_counts (CajaFile *file)
5256{
5257 if (file->details->deep_counts_status != CAJA_REQUEST_IN_PROGRESS) {
5258 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5259 if (file->details->directory != NULL((void*)0)) {
5260 caja_directory_add_file_to_work_queue (file->details->directory, file);
5261 caja_directory_async_state_changed (file->details->directory);
5262 }
5263 }
5264}
5265
5266gboolean
5267caja_file_can_get_size (CajaFile *file)
5268{
5269 return file->details->size == -1;
5270}
5271
5272
5273/**
5274 * caja_file_get_size
5275 *
5276 * Get the file size.
5277 * @file: CajaFile representing the file in question.
5278 *
5279 * Returns: Size in bytes.
5280 *
5281 **/
5282goffset
5283caja_file_get_size (CajaFile *file)
5284{
5285 /* Before we have info on the file, we don't know the size. */
5286 if (file->details->size == -1)
5287 return 0;
5288 return file->details->size;
5289}
5290
5291/**
5292 * caja_file_get_size_on_disk
5293 *
5294 * Get the file size on disk (how many bytes is using on the filesystem).
5295 * e.g.: usually files with 1 byte will use a whole inode so it will return the
5296 * size of 1 inode. If the file is sparse the size on disk will be equal or less
5297 * than the size of the file.
5298 * @file: CajaFile representing the file in question.
5299 *
5300 * Returns: Size in bytes.
5301 *
5302 **/
5303goffset
5304caja_file_get_size_on_disk (CajaFile *file)
5305{
5306 /* Before we have info on the file, we don't know the size. */
5307 if (file->details->size_on_disk == -1)
5308 return 0;
5309 return file->details->size_on_disk;
5310}
5311
5312time_t
5313caja_file_get_mtime (CajaFile *file)
5314{
5315 return file->details->mtime;
5316}
5317
5318
5319static void
5320set_attributes_get_info_callback (GObject *source_object,
5321 GAsyncResult *res,
5322 gpointer callback_data)
5323{
5324 CajaFileOperation *op;
5325 GFileInfo *new_info;
5326 GError *error;
5327
5328 op = callback_data;
5329
5330 error = NULL((void*)0);
5331 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
5332 if (new_info != NULL((void*)0)) {
5333 if (caja_file_update_info (op->file, new_info)) {
5334 caja_file_changed (op->file);
5335 }
5336 g_object_unref (new_info);
5337 }
5338 caja_file_operation_complete (op, NULL((void*)0), error);
5339 if (error) {
5340 g_error_free (error);
5341 }
5342}
5343
5344
5345static void
5346set_attributes_callback (GObject *source_object,
5347 GAsyncResult *result,
5348 gpointer callback_data)
5349{
5350 CajaFileOperation *op;
5351 GError *error;
5352 gboolean res;
5353
5354 op = callback_data;
5355
5356 error = NULL((void*)0);
5357 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5358 result,
5359 NULL((void*)0),
5360 &error);
5361
5362 if (res) {
5363 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5364 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
5365 0,
5366 G_PRIORITY_DEFAULT0,
5367 op->cancellable,
5368 set_attributes_get_info_callback, op);
5369 } else {
5370 caja_file_operation_complete (op, NULL((void*)0), error);
5371 g_error_free (error);
5372 }
5373}
5374
5375void
5376caja_file_set_attributes (CajaFile *file,
5377 GFileInfo *attributes,
5378 CajaFileOperationCallback callback,
5379 gpointer callback_data)
5380{
5381 CajaFileOperation *op;
5382 GFile *location;
5383
5384 op = caja_file_operation_new (file, callback, callback_data);
5385
5386 location = caja_file_get_location (file);
5387 g_file_set_attributes_async (location,
5388 attributes,
5389 0,
5390 G_PRIORITY_DEFAULT0,
5391 op->cancellable,
5392 set_attributes_callback,
5393 op);
5394 g_object_unref (location);
5395}
5396
5397
5398/**
5399 * caja_file_can_get_permissions:
5400 *
5401 * Check whether the permissions for a file are determinable.
5402 * This might not be the case for files on non-UNIX file systems.
5403 *
5404 * @file: The file in question.
5405 *
5406 * Return value: TRUE if the permissions are valid.
5407 */
5408gboolean
5409caja_file_can_get_permissions (CajaFile *file)
5410{
5411 return file->details->has_permissions;
5412}
5413
5414/**
5415 * caja_file_can_set_permissions:
5416 *
5417 * Check whether the current user is allowed to change
5418 * the permissions of a file.
5419 *
5420 * @file: The file in question.
5421 *
5422 * Return value: TRUE if the current user can change the
5423 * permissions of @file, FALSE otherwise. It's always possible
5424 * that when you actually try to do it, you will fail.
5425 */
5426gboolean
5427caja_file_can_set_permissions (CajaFile *file)
5428{
5429 uid_t user_id;
5430
5431 if (file->details->uid != -1 &&
5432 caja_file_is_local (file)) {
5433 /* Check the user. */
5434 user_id = geteuid();
5435
5436 /* Owner is allowed to set permissions. */
5437 if (user_id == (uid_t) file->details->uid) {
5438 return TRUE(!(0));
5439 }
5440
5441 /* Root is also allowed to set permissions. */
5442 if (user_id == 0) {
5443 return TRUE(!(0));
5444 }
5445
5446 /* Nobody else is allowed. */
5447 return FALSE(0);
5448 }
5449
5450 /* pretend to have full chmod rights when no info is available, relevant when
5451 * the FS can't provide ownership info, for instance for FTP */
5452 return TRUE(!(0));
5453}
5454
5455guint
5456caja_file_get_permissions (CajaFile *file)
5457{
5458 g_return_val_if_fail (caja_file_can_get_permissions (file), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_790
; if (caja_file_can_get_permissions (file)) _g_boolean_var_790
= 1; else _g_boolean_var_790 = 0; _g_boolean_var_790; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "caja_file_can_get_permissions (file)");
return (0); } } while (0)
;
5459
5460 return file->details->permissions;
5461}
5462
5463/**
5464 * caja_file_set_permissions:
5465 *
5466 * Change a file's permissions. This should only be called if
5467 * caja_file_can_set_permissions returned TRUE.
5468 *
5469 * @file: CajaFile representing the file in question.
5470 * @new_permissions: New permissions value. This is the whole
5471 * set of permissions, not a delta.
5472 **/
5473void
5474caja_file_set_permissions (CajaFile *file,
5475 guint32 new_permissions,
5476 CajaFileOperationCallback callback,
5477 gpointer callback_data)
5478{
5479 GFileInfo *info;
5480
5481 if (!caja_file_can_set_permissions (file)) {
5482 GError *error;
5483
5484 /* Claim that something changed even if the permission change failed.
5485 * This makes it easier for some clients who see the "reverting"
5486 * to the old permissions as "changing back".
5487 */
5488 caja_file_changed (file);
5489 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5490 _("Not allowed to set permissions")dcgettext (((void*)0), "Not allowed to set permissions", 5));
5491 (* callback) (file, NULL((void*)0), error, callback_data);
5492 g_error_free (error);
5493 return;
5494 }
5495
5496 /* Test the permissions-haven't-changed case explicitly
5497 * because we don't want to send the file-changed signal if
5498 * nothing changed.
5499 */
5500 if (new_permissions == file->details->permissions) {
5501 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5502 return;
5503 }
5504
5505 // Start UNDO-REDO
5506 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5507 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_SETPERMISSIONS, 1);
5508 caja_undostack_manager_data_set_file_permissions(undo_redo_data, caja_file_get_uri(file), file->details->permissions, new_permissions);
5509 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5510 undo_redo_data);
5511 }
5512 // End UNDO-REDO
5513
5514 info = g_file_info_new ();
5515 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode", new_permissions);
5516 caja_file_set_attributes (file, info, callback, callback_data);
5517 g_object_unref (info);
5518}
5519
5520/**
5521 * caja_file_can_get_selinux_context:
5522 *
5523 * Check whether the selinux context for a file are determinable.
5524 * This might not be the case for files on non-UNIX file systems,
5525 * files without a context or systems that don't support selinux.
5526 *
5527 * @file: The file in question.
5528 *
5529 * Return value: TRUE if the permissions are valid.
5530 */
5531gboolean
5532caja_file_can_get_selinux_context (CajaFile *file)
5533{
5534 return file->details->selinux_context != NULL((void*)0);
5535}
5536
5537
5538/**
5539 * caja_file_get_selinux_context:
5540 *
5541 * Get a user-displayable string representing a file's selinux
5542 * context
5543 * @file: CajaFile representing the file in question.
5544 *
5545 * Returns: Newly allocated string ready to display to the user.
5546 *
5547 **/
5548char *
5549caja_file_get_selinux_context (CajaFile *file)
5550{
5551 char *translated;
5552 char *raw;
5553
5554 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_791
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_791
= 1; else _g_boolean_var_791 = 0; _g_boolean_var_791; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
5555
5556 if (!caja_file_can_get_selinux_context (file)) {
5557 return NULL((void*)0);
5558 }
5559
5560 raw = file->details->selinux_context;
5561
5562#ifdef HAVE_SELINUX1
5563 if (selinux_raw_to_trans_context (raw, &translated) == 0) {
5564 char *tmp;
5565 tmp = g_strdup (translated)g_strdup_inline (translated);
5566 freecon (translated);
5567 translated = tmp;
5568 }
5569 else
5570#endif
5571 {
5572 translated = g_strdup (raw)g_strdup_inline (raw);
5573 }
5574
5575 return translated;
5576}
5577
5578static char *
5579get_real_name (const char *name, const char *gecos)
5580{
5581 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
5582
5583 if (gecos == NULL((void*)0)) {
5584 return NULL((void*)0);
5585 }
5586
5587 locale_string = eel_str_strip_substring_and_after (gecos, ",");
5588 if (!g_utf8_validate (locale_string, -1, NULL((void*)0))) {
5589 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5590 g_free (locale_string);
5591 } else {
5592 part_before_comma = locale_string;
5593 }
5594
5595 if (!g_utf8_validate (name, -1, NULL((void*)0))) {
5596 locale_string = g_locale_to_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5597 } else {
5598 locale_string = g_strdup (name)g_strdup_inline (name);
5599 }
5600
5601 capitalized_login_name = eel_str_capitalize (locale_string);
5602 g_free (locale_string);
5603
5604 if (capitalized_login_name == NULL((void*)0)) {
5605 real_name = part_before_comma;
5606 } else {
5607 real_name = eel_str_replace_substring
5608 (part_before_comma, "&", capitalized_login_name);
5609 g_free (part_before_comma);
5610 }
5611
5612
5613 if (eel_str_is_empty (real_name)
5614 || eel_strcmp (name, real_name) == 0
5615 || eel_strcmp (capitalized_login_name, real_name) == 0) {
5616 g_free (real_name);
5617 real_name = NULL((void*)0);
5618 }
5619
5620 g_free (capitalized_login_name);
5621
5622 return real_name;
5623}
5624
5625static gboolean
5626get_group_id_from_group_name (const char *group_name, uid_t *gid)
5627{
5628 struct group *group;
5629
5630 g_assert (gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_792
; if (gid != ((void*)0)) _g_boolean_var_792 = 1; else _g_boolean_var_792
= 0; _g_boolean_var_792; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5630, ((const char*) (__func__
)), "gid != NULL"); } while (0)
;
5631
5632 group = getgrnam (group_name);
5633
5634 if (group == NULL((void*)0)) {
5635 return FALSE(0);
5636 }
5637
5638 *gid = group->gr_gid;
5639
5640 return TRUE(!(0));
5641}
5642
5643static gboolean
5644get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid)
5645{
5646 struct passwd *password_info;
5647
5648 g_assert (uid != NULL || gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_793
; if (uid != ((void*)0) || gid != ((void*)0)) _g_boolean_var_793
= 1; else _g_boolean_var_793 = 0; _g_boolean_var_793; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5648, ((const char*) (__func__)), "uid != NULL || gid != NULL"
); } while (0)
;
5649
5650 password_info = getpwnam (user_name);
5651
5652 if (password_info == NULL((void*)0)) {
5653 return FALSE(0);
5654 }
5655
5656 if (uid != NULL((void*)0)) {
5657 *uid = password_info->pw_uid;
5658 }
5659
5660 if (gid != NULL((void*)0)) {
5661 *gid = password_info->pw_gid;
5662 }
5663
5664 return TRUE(!(0));
5665}
5666
5667static gboolean
5668get_user_id_from_user_name (const char *user_name, uid_t *id)
5669{
5670 return get_ids_from_user_name (user_name, id, NULL((void*)0));
5671}
5672
5673static gboolean
5674get_id_from_digit_string (const char *digit_string, uid_t *id)
5675{
5676 long scanned_id;
5677 char c;
5678
5679 g_assert (id != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_794
; if (id != ((void*)0)) _g_boolean_var_794 = 1; else _g_boolean_var_794
= 0; _g_boolean_var_794; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5679, ((const char*) (__func__
)), "id != NULL"); } while (0)
;
5680
5681 /* Only accept string if it has one integer with nothing
5682 * afterwards.
5683 */
5684 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) {
5685 return FALSE(0);
5686 }
5687 *id = scanned_id;
5688 return TRUE(!(0));
5689}
5690
5691/**
5692 * caja_file_can_get_owner:
5693 *
5694 * Check whether the owner a file is determinable.
5695 * This might not be the case for files on non-UNIX file systems.
5696 *
5697 * @file: The file in question.
5698 *
5699 * Return value: TRUE if the owner is valid.
5700 */
5701gboolean
5702caja_file_can_get_owner (CajaFile *file)
5703{
5704 /* Before we have info on a file, the owner is unknown. */
5705 return file->details->uid != -1;
5706}
5707
5708/**
5709 * caja_file_get_owner_name:
5710 *
5711 * Get the user name of the file's owner. If the owner has no
5712 * name, returns the userid as a string. The caller is responsible
5713 * for g_free-ing this string.
5714 *
5715 * @file: The file in question.
5716 *
5717 * Return value: A newly-allocated string.
5718 */
5719char *
5720caja_file_get_owner_name (CajaFile *file)
5721{
5722 return caja_file_get_owner_as_string (file, FALSE(0));
5723}
5724
5725/**
5726 * caja_file_can_set_owner:
5727 *
5728 * Check whether the current user is allowed to change
5729 * the owner of a file.
5730 *
5731 * @file: The file in question.
5732 *
5733 * Return value: TRUE if the current user can change the
5734 * owner of @file, FALSE otherwise. It's always possible
5735 * that when you actually try to do it, you will fail.
5736 */
5737gboolean
5738caja_file_can_set_owner (CajaFile *file)
5739{
5740 /* Not allowed to set the owner if we can't
5741 * even read it. This can happen on non-UNIX file
5742 * systems.
5743 */
5744 if (!caja_file_can_get_owner (file)) {
5745 return FALSE(0);
5746 }
5747
5748 /* Only root is also allowed to set the owner. */
5749 return geteuid() == 0;
5750}
5751
5752/**
5753 * caja_file_set_owner:
5754 *
5755 * Set the owner of a file. This will only have any effect if
5756 * caja_file_can_set_owner returns TRUE.
5757 *
5758 * @file: The file in question.
5759 * @user_name_or_id: The user name to set the owner to.
5760 * If the string does not match any user name, and the
5761 * string is an integer, the owner will be set to the
5762 * userid represented by that integer.
5763 * @callback: Function called when asynch owner change succeeds or fails.
5764 * @callback_data: Parameter passed back with callback function.
5765 */
5766void
5767caja_file_set_owner (CajaFile *file,
5768 const char *user_name_or_id,
5769 CajaFileOperationCallback callback,
5770 gpointer callback_data)
5771{
5772 GError *error;
5773 GFileInfo *info;
5774 uid_t new_id;
5775
5776 if (!caja_file_can_set_owner (file)) {
5777 /* Claim that something changed even if the permission
5778 * change failed. This makes it easier for some
5779 * clients who see the "reverting" to the old owner as
5780 * "changing back".
5781 */
5782 caja_file_changed (file);
5783 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5784 _("Not allowed to set owner")dcgettext (((void*)0), "Not allowed to set owner", 5));
5785 (* callback) (file, NULL((void*)0), error, callback_data);
5786 g_error_free (error);
5787 return;
5788 }
5789
5790 /* If no match treating user_name_or_id as name, try treating
5791 * it as id.
5792 */
5793 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
5794 && !get_id_from_digit_string (user_name_or_id, &new_id)) {
5795 /* Claim that something changed even if the permission
5796 * change failed. This makes it easier for some
5797 * clients who see the "reverting" to the old owner as
5798 * "changing back".
5799 */
5800 caja_file_changed (file);
5801 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
5802 _("Specified owner '%s' doesn't exist")dcgettext (((void*)0), "Specified owner '%s' doesn't exist", 5
)
, user_name_or_id);
5803 (* callback) (file, NULL((void*)0), error, callback_data);
5804 g_error_free (error);
5805 return;
5806 }
5807
5808 /* Test the owner-hasn't-changed case explicitly because we
5809 * don't want to send the file-changed signal if nothing
5810 * changed.
5811 */
5812 if (new_id == (uid_t) file->details->uid) {
5813 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5814 return;
5815 }
5816
5817 // Start UNDO-REDO
5818 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5819 char* current_owner = caja_file_get_owner_as_string (file, FALSE(0));
5820 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEOWNER, 1);
5821 caja_undostack_manager_data_set_owner_change_information(undo_redo_data, caja_file_get_uri(file), current_owner, user_name_or_id);
5822 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5823 undo_redo_data);
5824 g_free(current_owner);
5825 }
5826 // End UNDO-REDO
5827
5828 info = g_file_info_new ();
5829 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid", new_id);
5830 caja_file_set_attributes (file, info, callback, callback_data);
5831 g_object_unref (info);
5832}
5833
5834/**
5835 * caja_get_user_names:
5836 *
5837 * Get a list of user names. For users with a different associated
5838 * "real name", the real name follows the standard user name, separated
5839 * by a carriage return. The caller is responsible for freeing this list
5840 * and its contents.
5841 */
5842GList *
5843caja_get_user_names (void)
5844{
5845 GList *list;
5846 char *name;
5847 struct passwd *user;
5848
5849 list = NULL((void*)0);
5850
5851 setpwent ();
5852
5853 while ((user = getpwent ()) != NULL((void*)0)) {
5854 char *real_name;
5855
5856 real_name = get_real_name (user->pw_name, user->pw_gecos);
5857 if (real_name != NULL((void*)0)) {
5858 name = g_strconcat (user->pw_name, "\n", real_name, NULL((void*)0));
5859 } else {
5860 name = g_strdup (user->pw_name)g_strdup_inline (user->pw_name);
5861 }
5862 g_free (real_name);
5863 list = g_list_prepend (list, name);
5864 }
5865
5866 endpwent ();
5867
5868 return eel_g_str_list_alphabetize (list);
5869}
5870
5871/**
5872 * caja_file_can_get_group:
5873 *
5874 * Check whether the group a file is determinable.
5875 * This might not be the case for files on non-UNIX file systems.
5876 *
5877 * @file: The file in question.
5878 *
5879 * Return value: TRUE if the group is valid.
5880 */
5881gboolean
5882caja_file_can_get_group (CajaFile *file)
5883{
5884 /* Before we have info on a file, the group is unknown. */
5885 return file->details->gid != -1;
5886}
5887
5888/**
5889 * caja_file_get_group_name:
5890 *
5891 * Get the name of the file's group. If the group has no
5892 * name, returns the groupid as a string. The caller is responsible
5893 * for g_free-ing this string.
5894 *
5895 * @file: The file in question.
5896 *
5897 * Return value: A newly-allocated string.
5898 **/
5899char *
5900caja_file_get_group_name (CajaFile *file)
5901{
5902 return g_strdup (file->details->group)g_strdup_inline (file->details->group);
5903}
5904
5905/**
5906 * caja_file_can_set_group:
5907 *
5908 * Check whether the current user is allowed to change
5909 * the group of a file.
5910 *
5911 * @file: The file in question.
5912 *
5913 * Return value: TRUE if the current user can change the
5914 * group of @file, FALSE otherwise. It's always possible
5915 * that when you actually try to do it, you will fail.
5916 */
5917gboolean
5918caja_file_can_set_group (CajaFile *file)
5919{
5920 uid_t user_id;
5921
5922 /* Not allowed to set the permissions if we can't
5923 * even read them. This can happen on non-UNIX file
5924 * systems.
5925 */
5926 if (!caja_file_can_get_group (file)) {
5927 return FALSE(0);
5928 }
5929
5930 /* Check the user. */
5931 user_id = geteuid();
5932
5933 /* Owner is allowed to set group (with restrictions). */
5934 if (user_id == (uid_t) file->details->uid) {
5935 return TRUE(!(0));
5936 }
5937
5938 /* Root is also allowed to set group. */
5939 if (user_id == 0) {
5940 return TRUE(!(0));
5941 }
5942
5943 /* Nobody else is allowed. */
5944 return FALSE(0);
5945}
5946
5947/* Get a list of group names, filtered to only the ones
5948 * that contain the given username. If the username is
5949 * NULL, returns a list of all group names.
5950 */
5951static GList *
5952caja_get_group_names_for_user (void)
5953{
5954 GList *list;
5955 int count, i;
5956 gid_t gid_list[NGROUPS_MAX65536 + 1];
5957 struct group *group = NULL((void*)0);
5958
5959
5960 list = NULL((void*)0);
5961
5962 count = getgroups (NGROUPS_MAX65536 + 1, gid_list);
5963 for (i = 0; i < count; i++) {
5964 group = getgrgid (gid_list[i]);
5965 if (group == NULL((void*)0))
5966 break;
5967
5968 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5969 }
5970
5971 return eel_g_str_list_alphabetize (list);
5972}
5973
5974/**
5975 * caja_get_group_names:
5976 *
5977 * Get a list of all group names.
5978 */
5979GList *
5980caja_get_all_group_names (void)
5981{
5982 GList *list;
5983 struct group *group;
5984
5985 list = NULL((void*)0);
5986
5987 setgrent ();
5988
5989 while ((group = getgrent ()) != NULL((void*)0))
5990 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5991
5992 endgrent ();
5993
5994 return eel_g_str_list_alphabetize (list);
5995}
5996
5997/**
5998 * caja_file_get_settable_group_names:
5999 *
6000 * Get a list of all group names that the current user
6001 * can set the group of a specific file to.
6002 *
6003 * @file: The CajaFile in question.
6004 */
6005GList *
6006caja_file_get_settable_group_names (CajaFile *file)
6007{
6008 uid_t user_id;
6009 GList *result;
6010
6011 if (!caja_file_can_set_group (file)) {
6012 return NULL((void*)0);
6013 }
6014
6015 /* Check the user. */
6016 user_id = geteuid();
6017
6018 if (user_id == 0) {
6019 /* Root is allowed to set group to anything. */
6020 result = caja_get_all_group_names ();
6021 } else if (user_id == (uid_t) file->details->uid) {
6022 /* Owner is allowed to set group to any that owner is member of. */
6023 result = caja_get_group_names_for_user ();
6024 } else {
6025 g_warning ("unhandled case in caja_get_settable_group_names");
6026 result = NULL((void*)0);
6027 }
6028
6029 return result;
6030}
6031
6032/**
6033 * caja_file_set_group:
6034 *
6035 * Set the group of a file. This will only have any effect if
6036 * caja_file_can_set_group returns TRUE.
6037 *
6038 * @file: The file in question.
6039 * @group_name_or_id: The group name to set the owner to.
6040 * If the string does not match any group name, and the
6041 * string is an integer, the group will be set to the
6042 * group id represented by that integer.
6043 * @callback: Function called when asynch group change succeeds or fails.
6044 * @callback_data: Parameter passed back with callback function.
6045 */
6046void
6047caja_file_set_group (CajaFile *file,
6048 const char *group_name_or_id,
6049 CajaFileOperationCallback callback,
6050 gpointer callback_data)
6051{
6052 GError *error;
6053 GFileInfo *info;
6054 uid_t new_id;
6055
6056 if (!caja_file_can_set_group (file)) {
6057 /* Claim that something changed even if the group
6058 * change failed. This makes it easier for some
6059 * clients who see the "reverting" to the old group as
6060 * "changing back".
6061 */
6062 caja_file_changed (file);
6063 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
6064 _("Not allowed to set group")dcgettext (((void*)0), "Not allowed to set group", 5));
6065 (* callback) (file, NULL((void*)0), error, callback_data);
6066 g_error_free (error);
6067 return;
6068 }
6069
6070 /* If no match treating group_name_or_id as name, try treating
6071 * it as id.
6072 */
6073 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6074 && !get_id_from_digit_string (group_name_or_id, &new_id)) {
6075 /* Claim that something changed even if the group
6076 * change failed. This makes it easier for some
6077 * clients who see the "reverting" to the old group as
6078 * "changing back".
6079 */
6080 caja_file_changed (file);
6081 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
6082 _("Specified group '%s' doesn't exist")dcgettext (((void*)0), "Specified group '%s' doesn't exist", 5
)
, group_name_or_id);
6083 (* callback) (file, NULL((void*)0), error, callback_data);
6084 g_error_free (error);
6085 return;
6086 }
6087
6088 if (new_id == (gid_t) file->details->gid) {
6089 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
6090 return;
6091 }
6092
6093 // Start UNDO-REDO
6094 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6095 char* current_group = caja_file_get_group_name (file);
6096 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEGROUP, 1);
6097 caja_undostack_manager_data_set_group_change_information(undo_redo_data, caja_file_get_uri(file), current_group, group_name_or_id);
6098 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
6099 undo_redo_data);
6100 g_free(current_group);
6101 }
6102 // End UNDO-REDO
6103
6104 info = g_file_info_new ();
6105 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid", new_id);
6106 caja_file_set_attributes (file, info, callback, callback_data);
6107 g_object_unref (info);
6108}
6109
6110/**
6111 * caja_file_get_octal_permissions_as_string:
6112 *
6113 * Get a user-displayable string representing a file's permissions
6114 * as an octal number. The caller
6115 * is responsible for g_free-ing this string.
6116 * @file: CajaFile representing the file in question.
6117 *
6118 * Returns: Newly allocated string ready to display to the user.
6119 *
6120 **/
6121static char *
6122caja_file_get_octal_permissions_as_string (CajaFile *file)
6123{
6124 guint32 permissions;
6125
6126 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_795
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_795
= 1; else _g_boolean_var_795 = 0; _g_boolean_var_795; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6126, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6127
6128 if (!caja_file_can_get_permissions (file)) {
6129 return NULL((void*)0);
6130 }
6131
6132 permissions = file->details->permissions;
6133 return g_strdup_printf ("%03o", permissions);
6134}
6135
6136/**
6137 * caja_file_get_permissions_as_string:
6138 *
6139 * Get a user-displayable string representing a file's permissions. The caller
6140 * is responsible for g_free-ing this string.
6141 * @file: CajaFile representing the file in question.
6142 *
6143 * Returns: Newly allocated string ready to display to the user.
6144 *
6145 **/
6146static char *
6147caja_file_get_permissions_as_string (CajaFile *file)
6148{
6149 guint32 permissions;
6150 gboolean is_directory;
6151 gboolean is_link;
6152 gboolean suid, sgid, sticky;
6153
6154 if (!caja_file_can_get_permissions (file)) {
6155 return NULL((void*)0);
6156 }
6157
6158 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_796
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_796
= 1; else _g_boolean_var_796 = 0; _g_boolean_var_796; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6158, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6159
6160 permissions = file->details->permissions;
6161 is_directory = caja_file_is_directory (file);
6162 is_link = caja_file_is_symbolic_link (file);
6163
6164 /* We use ls conventions for displaying these three obscure flags */
6165 suid = permissions & S_ISUID04000;
6166 sgid = permissions & S_ISGID02000;
6167 sticky = permissions & S_ISVTX01000;
6168
6169 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6170 is_link ? 'l' : is_directory ? 'd' : '-',
6171 permissions & S_IRUSR0400 ? 'r' : '-',
6172 permissions & S_IWUSR0200 ? 'w' : '-',
6173 permissions & S_IXUSR0100
6174 ? (suid ? 's' : 'x')
6175 : (suid ? 'S' : '-'),
6176 permissions & S_IRGRP(0400 >> 3) ? 'r' : '-',
6177 permissions & S_IWGRP(0200 >> 3) ? 'w' : '-',
6178 permissions & S_IXGRP(0100 >> 3)
6179 ? (sgid ? 's' : 'x')
6180 : (sgid ? 'S' : '-'),
6181 permissions & S_IROTH((0400 >> 3) >> 3) ? 'r' : '-',
6182 permissions & S_IWOTH((0200 >> 3) >> 3) ? 'w' : '-',
6183 permissions & S_IXOTH((0100 >> 3) >> 3)
6184 ? (sticky ? 't' : 'x')
6185 : (sticky ? 'T' : '-'));
6186}
6187
6188/**
6189 * caja_file_get_owner_as_string:
6190 *
6191 * Get a user-displayable string representing a file's owner. The caller
6192 * is responsible for g_free-ing this string.
6193 * @file: CajaFile representing the file in question.
6194 * @include_real_name: Whether or not to append the real name (if any)
6195 * for this user after the user name.
6196 *
6197 * Returns: Newly allocated string ready to display to the user.
6198 *
6199 **/
6200static char *
6201caja_file_get_owner_as_string (CajaFile *file, gboolean include_real_name)
6202{
6203 char *user_name;
6204
6205 /* Before we have info on a file, the owner is unknown. */
6206 if (file->details->owner == NULL((void*)0) &&
6207 file->details->owner_real == NULL((void*)0)) {
6208 return NULL((void*)0);
6209 }
6210
6211 if (file->details->owner_real == NULL((void*)0)) {
6212 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6213 } else if (file->details->owner == NULL((void*)0)) {
6214 user_name = g_strdup (file->details->owner_real)g_strdup_inline (file->details->owner_real);
6215 } else if (include_real_name &&
6216 strcmp (file->details->owner, file->details->owner_real) != 0) {
6217 user_name = g_strdup_printf ("%s - %s",
6218 file->details->owner,
6219 file->details->owner_real);
6220 } else {
6221 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6222 }
6223
6224 return user_name;
6225}
6226
6227static char *
6228format_item_count_for_display (guint item_count,
6229 gboolean includes_directories,
6230 gboolean includes_files)
6231{
6232 g_assert (includes_directories || includes_files)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_797
; if (includes_directories || includes_files) _g_boolean_var_797
= 1; else _g_boolean_var_797 = 0; _g_boolean_var_797; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6232, ((const char*) (__func__)), "includes_directories || includes_files"
); } while (0)
;
6233
6234 return g_strdup_printf (includes_directories
6235 ? (includes_files
6236 ? ngettext ("%'u item", "%'u items", item_count)dcngettext (((void*)0), "%'u item", "%'u items", item_count, 5
)
6237 : ngettext ("%'u folder", "%'u folders", item_count)dcngettext (((void*)0), "%'u folder", "%'u folders", item_count
, 5)
)
6238 : ngettext ("%'u file", "%'u files", item_count)dcngettext (((void*)0), "%'u file", "%'u files", item_count, 5
)
, item_count);
6239}
6240
6241/**
6242 * caja_file_get_size_as_string:
6243 *
6244 * Get a user-displayable string representing a file size. The caller
6245 * is responsible for g_free-ing this string. The string is an item
6246 * count for directories.
6247 * @file: CajaFile representing the file in question.
6248 * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
6249 *
6250 * Returns: Newly allocated string ready to display to the user.
6251 *
6252 **/
6253static char *
6254caja_file_get_size_as_string (CajaFile *file,
6255 gboolean size_on_disk)
6256{
6257 guint item_count;
6258 gboolean count_unreadable;
6259 goffset size;
6260
6261 if (file == NULL((void*)0)) {
6262 return NULL((void*)0);
6263 }
6264
6265 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_798
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_798
= 1; else _g_boolean_var_798 = 0; _g_boolean_var_798; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6265, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6266
6267 if (caja_file_is_directory (file)) {
6268 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6269 return NULL((void*)0);
6270 }
6271 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6272 }
6273
6274 if (size_on_disk) {
6275 size = file->details->size_on_disk;
6276 } else {
6277 size = file->details->size;
6278 }
6279
6280 if (size == -1) {
6281 return NULL((void*)0);
6282 }
6283
6284 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6285 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6286 else
6287 return g_format_size (size);
6288}
6289
6290/**
6291 * caja_file_get_size_as_string_with_real_size:
6292 *
6293 * Get a user-displayable string representing a file size. The caller
6294 * is responsible for g_free-ing this string. The string is an item
6295 * count for directories.
6296 * This function adds the real size in the string.
6297 * @file: CajaFile representing the file in question.
6298 *
6299 * Returns: Newly allocated string ready to display to the user.
6300 *
6301 **/
6302static char *
6303caja_file_get_size_as_string_with_real_size (CajaFile *file,
6304 gboolean size_on_disk)
6305{
6306 guint item_count;
6307 gboolean count_unreadable;
6308 goffset size;
6309 char * formatted;
6310 char * formatted_plus_real;
6311 char * real_size;
6312
6313 if (file == NULL((void*)0)) {
6314 return NULL((void*)0);
6315 }
6316
6317 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_799
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_799
= 1; else _g_boolean_var_799 = 0; _g_boolean_var_799; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6317, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6318
6319 if (caja_file_is_directory (file)) {
6320 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6321 return NULL((void*)0);
6322 }
6323 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6324 }
6325
6326 if (size_on_disk) {
6327 size = file->details->size_on_disk;
6328 } else {
6329 size = file->details->size;
6330 }
6331
6332 if (size == -1) {
6333 return NULL((void*)0);
6334 }
6335
6336 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6337 formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6338 else
6339 formatted = g_format_size(size);
6340
6341 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
6342 real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT)dcgettext (((void*)0), "%""lu", 5), (guint64) size);
6343 formatted_plus_real = g_strdup_printf (_("%s (%s bytes)")dcgettext (((void*)0), "%s (%s bytes)", 5), formatted, real_size);
6344 g_free (real_size);
6345 g_free (formatted);
6346 return formatted_plus_real;
6347}
6348
6349static char *
6350caja_file_get_deep_count_as_string_internal (CajaFile *file,
6351 gboolean report_size,
6352 gboolean report_size_on_disk,
6353 gboolean report_directory_count,
6354 gboolean report_file_count)
6355{
6356 CajaRequestStatus status;
6357 guint directory_count;
6358 guint file_count;
6359 guint unreadable_count;
6360 guint total_count;
6361 goffset total_size;
6362 goffset total_size_on_disk;
6363
6364 /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
6365 g_assert (!(report_size && report_size_on_disk))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_800
; if (!(report_size && report_size_on_disk)) _g_boolean_var_800
= 1; else _g_boolean_var_800 = 0; _g_boolean_var_800; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6365, ((const char*) (__func__)), "!(report_size && report_size_on_disk)"
); } while (0)
;
6366 g_assert (!(report_size && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_801
; if (!(report_size && (report_directory_count || report_file_count
))) _g_boolean_var_801 = 1; else _g_boolean_var_801 = 0; _g_boolean_var_801
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6366, ((const char*) (__func__)), "!(report_size && (report_directory_count || report_file_count))"
); } while (0)
;
6367 g_assert (!(report_size_on_disk && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_802
; if (!(report_size_on_disk && (report_directory_count
|| report_file_count))) _g_boolean_var_802 = 1; else _g_boolean_var_802
= 0; _g_boolean_var_802; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6367, ((const char*) (__func__
)), "!(report_size_on_disk && (report_directory_count || report_file_count))"
); } while (0)
;
6368
6369 /* Must ask for something */
6370 g_assert (report_size || report_size_on_disk || report_directory_count || report_file_count)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_803
; if (report_size || report_size_on_disk || report_directory_count
|| report_file_count) _g_boolean_var_803 = 1; else _g_boolean_var_803
= 0; _g_boolean_var_803; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6370, ((const char*) (__func__
)), "report_size || report_size_on_disk || report_directory_count || report_file_count"
); } while (0)
;
6371
6372 if (file == NULL((void*)0)) {
6373 return NULL((void*)0);
6374 }
6375
6376 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_804
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_804
= 1; else _g_boolean_var_804 = 0; _g_boolean_var_804; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6376, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6377 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_805
; if (caja_file_is_directory (file)) _g_boolean_var_805 = 1; else
_g_boolean_var_805 = 0; _g_boolean_var_805; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6377, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
6378
6379 status = caja_file_get_deep_counts (file,
6380 &directory_count,
6381 &file_count,
6382 &unreadable_count,
6383 &total_size,
6384 &total_size_on_disk,
6385 FALSE(0));
6386
6387 /* Check whether any info is available. */
6388 if (status == CAJA_REQUEST_NOT_STARTED) {
6389 return NULL((void*)0);
6390 }
6391
6392 total_count = file_count + directory_count;
6393
6394 if (total_count == 0) {
6395 switch (status) {
6396 case CAJA_REQUEST_IN_PROGRESS:
6397 /* Don't return confident "zero" until we're finished looking,
6398 * because of next case.
6399 */
6400 return NULL((void*)0);
6401 case CAJA_REQUEST_DONE:
6402 /* Don't return "zero" if we there were contents but we couldn't read them. */
6403 if (unreadable_count != 0) {
6404 return NULL((void*)0);
6405 }
6406 default: break;
6407 }
6408 }
6409
6410 /* Note that we don't distinguish the "everything was readable" case
6411 * from the "some things but not everything was readable" case here.
6412 * Callers can distinguish them using caja_file_get_deep_counts
6413 * directly if desired.
6414 */
6415 if (report_size)
6416 {
6417 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6418 return g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
6419 else
6420 return g_format_size(total_size);
6421 }
6422
6423 if (report_size_on_disk)
6424 {
6425 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6426 return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
6427 else
6428 return g_format_size (total_size_on_disk);
6429 }
6430
6431 return format_item_count_for_display (report_directory_count
6432 ? (report_file_count ? total_count : directory_count)
6433 : file_count,
6434 report_directory_count, report_file_count);
6435}
6436
6437/**
6438 * caja_file_get_deep_size_as_string:
6439 *
6440 * Get a user-displayable string representing the size of all contained
6441 * items (only makes sense for directories). The caller
6442 * is responsible for g_free-ing this string.
6443 * @file: CajaFile representing the file in question.
6444 * @size_on_disk: if TRUE will return the size on disk, else return size of file.
6445 *
6446 * Returns: Newly allocated string ready to display to the user.
6447 *
6448 **/
6449static char *
6450caja_file_get_deep_size_as_string (CajaFile *file, gboolean size_on_disk)
6451{
6452 if (size_on_disk) {
6453 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), TRUE(!(0)), FALSE(0), FALSE(0));
6454 } else {
6455 return caja_file_get_deep_count_as_string_internal (file, TRUE(!(0)), FALSE(0), FALSE(0), FALSE(0));
6456 }
6457}
6458
6459/**
6460 * caja_file_get_deep_total_count_as_string:
6461 *
6462 * Get a user-displayable string representing the count of all contained
6463 * items (only makes sense for directories). The caller
6464 * is responsible for g_free-ing this string.
6465 * @file: CajaFile representing the file in question.
6466 *
6467 * Returns: Newly allocated string ready to display to the user.
6468 *
6469 **/
6470static char *
6471caja_file_get_deep_total_count_as_string (CajaFile *file)
6472{
6473 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), TRUE(!(0)));
6474}
6475
6476/**
6477 * caja_file_get_deep_file_count_as_string:
6478 *
6479 * Get a user-displayable string representing the count of all contained
6480 * items, not including directories. It only makes sense to call this
6481 * function on a directory. The caller
6482 * is responsible for g_free-ing this string.
6483 * @file: CajaFile representing the file in question.
6484 *
6485 * Returns: Newly allocated string ready to display to the user.
6486 *
6487 **/
6488static char *
6489caja_file_get_deep_file_count_as_string (CajaFile *file)
6490{
6491 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), FALSE(0), TRUE(!(0)));
6492}
6493
6494/**
6495 * caja_file_get_deep_directory_count_as_string:
6496 *
6497 * Get a user-displayable string representing the count of all contained
6498 * directories. It only makes sense to call this
6499 * function on a directory. The caller
6500 * is responsible for g_free-ing this string.
6501 * @file: CajaFile representing the file in question.
6502 *
6503 * Returns: Newly allocated string ready to display to the user.
6504 *
6505 **/
6506static char *
6507caja_file_get_deep_directory_count_as_string (CajaFile *file)
6508{
6509 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), FALSE(0));
6510}
6511
6512/**
6513 * caja_file_get_string_attribute:
6514 *
6515 * Get a user-displayable string from a named attribute. Use g_free to
6516 * free this string. If the value is unknown, returns NULL. You can call
6517 * caja_file_get_string_attribute_with_default if you want a non-NULL
6518 * default.
6519 *
6520 * @file: CajaFile representing the file in question.
6521 * @attribute_name: The name of the desired attribute. The currently supported
6522 * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
6523 * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
6524 * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
6525 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
6526 *
6527 * Returns: Newly allocated string ready to display to the user, or NULL
6528 * if the value is unknown or @attribute_name is not supported.
6529 *
6530 **/
6531char *
6532caja_file_get_string_attribute_q (CajaFile *file, GQuark attribute_q)
6533{
6534 char *extension_attribute;
6535
6536 if (attribute_q == attribute_name_q) {
6537 return caja_file_get_display_name (file);
6538 }
6539 if (attribute_q == attribute_type_q) {
6540 return caja_file_get_type_as_string (file);
6541 }
6542 if (attribute_q == attribute_mime_type_q) {
6543 return caja_file_get_mime_type (file);
6544 }
6545 if (attribute_q == attribute_size_q) {
6546 return caja_file_get_size_as_string (file, FALSE(0));
6547 }
6548 if (attribute_q == attribute_size_on_disk_q) {
6549 return caja_file_get_size_as_string (file, TRUE(!(0)));
6550 }
6551 if (attribute_q == attribute_size_detail_q) {
6552 return caja_file_get_size_as_string_with_real_size (file, FALSE(0));
6553 }
6554 if (attribute_q == attribute_size_on_disk_detail_q) {
6555 return caja_file_get_size_as_string_with_real_size (file, TRUE(!(0)));
6556 }
6557 if (attribute_q == attribute_deep_size_q) {
6558 return caja_file_get_deep_size_as_string (file, FALSE(0));
6559 }
6560 if (attribute_q == attribute_deep_size_on_disk_q) {
6561 return caja_file_get_deep_size_as_string (file, TRUE(!(0)));
6562 }
6563 if (attribute_q == attribute_deep_file_count_q) {
6564 return caja_file_get_deep_file_count_as_string (file);
6565 }
6566 if (attribute_q == attribute_deep_directory_count_q) {
6567 return caja_file_get_deep_directory_count_as_string (file);
6568 }
6569 if (attribute_q == attribute_deep_total_count_q) {
6570 return caja_file_get_deep_total_count_as_string (file);
6571 }
6572 if (attribute_q == attribute_trash_orig_path_q) {
6573 return caja_file_get_trash_original_file_parent_as_string (file);
6574 }
6575 if (attribute_q == attribute_date_modified_q) {
6576 return caja_file_get_date_as_string (file,
6577 CAJA_DATE_TYPE_MODIFIED);
6578 }
6579 if (attribute_q == attribute_date_changed_q) {
6580 return caja_file_get_date_as_string (file,
6581 CAJA_DATE_TYPE_CHANGED);
6582 }
6583 if (attribute_q == attribute_date_accessed_q) {
6584 return caja_file_get_date_as_string (file,
6585 CAJA_DATE_TYPE_ACCESSED);
6586 }
6587 if (attribute_q == attribute_date_created_q) {
6588 return caja_file_get_date_as_string (file,
6589 CAJA_DATE_TYPE_CREATED);
6590 }
6591 if (attribute_q == attribute_trashed_on_q) {
6592 return caja_file_get_date_as_string (file,
6593 CAJA_DATE_TYPE_TRASHED);
6594 }
6595 if (attribute_q == attribute_date_permissions_q) {
6596 return caja_file_get_date_as_string (file,
6597 CAJA_DATE_TYPE_PERMISSIONS_CHANGED);
6598 }
6599 if (attribute_q == attribute_extension_q) {
6600 return caja_file_get_extension_as_string (file);
6601 }
6602 if (attribute_q == attribute_permissions_q) {
6603 return caja_file_get_permissions_as_string (file);
6604 }
6605 if (attribute_q == attribute_selinux_context_q) {
6606 return caja_file_get_selinux_context (file);
6607 }
6608 if (attribute_q == attribute_octal_permissions_q) {
6609 return caja_file_get_octal_permissions_as_string (file);
6610 }
6611 if (attribute_q == attribute_owner_q) {
6612 return caja_file_get_owner_as_string (file, TRUE(!(0)));
6613 }
6614 if (attribute_q == attribute_group_q) {
6615 return caja_file_get_group_name (file);
6616 }
6617 if (attribute_q == attribute_uri_q) {
6618 return caja_file_get_uri (file);
6619 }
6620 if (attribute_q == attribute_where_q) {
6621 return caja_file_get_where_string (file);
6622 }
6623 if (attribute_q == attribute_link_target_q) {
6624 return caja_file_get_symbolic_link_target_path (file);
6625 }
6626 if (attribute_q == attribute_volume_q) {
6627 return caja_file_get_volume_name (file);
6628 }
6629 if (attribute_q == attribute_free_space_q) {
6630 return caja_file_get_volume_free_space (file);
6631 }
6632
6633 extension_attribute = NULL((void*)0);
6634
6635 if (file->details->pending_extension_attributes) {
6636 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
6637 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6638 }
6639
6640 if (extension_attribute == NULL((void*)0) && file->details->extension_attributes) {
6641 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
6642 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6643 }
6644
6645 return g_strdup (extension_attribute)g_strdup_inline (extension_attribute);
6646}
6647
6648char *
6649caja_file_get_string_attribute (CajaFile *file, const char *attribute_name)
6650{
6651 return caja_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
6652}
6653
6654
6655/**
6656 * caja_file_get_string_attribute_with_default:
6657 *
6658 * Get a user-displayable string from a named attribute. Use g_free to
6659 * free this string. If the value is unknown, returns a string representing
6660 * the unknown value, which varies with attribute. You can call
6661 * caja_file_get_string_attribute if you want NULL instead of a default
6662 * result.
6663 *
6664 * @file: CajaFile representing the file in question.
6665 * @attribute_name: The name of the desired attribute. See the description of
6666 * caja_file_get_string for the set of available attributes.
6667 *
6668 * Returns: Newly allocated string ready to display to the user, or a string
6669 * such as "unknown" if the value is unknown or @attribute_name is not supported.
6670 *
6671 **/
6672char *
6673caja_file_get_string_attribute_with_default_q (CajaFile *file, GQuark attribute_q)
6674{
6675 char *result;
6676 guint item_count;
6677 gboolean count_unreadable;
6678 CajaRequestStatus status;
6679
6680 result = caja_file_get_string_attribute_q (file, attribute_q);
6681 if (result != NULL((void*)0)) {
6682 return result;
6683 }
6684
6685 /* Supply default values for the ones we know about. */
6686 /* FIXME bugzilla.gnome.org 40646:
6687 * Use hash table and switch statement or function pointers for speed?
6688 */
6689 if (attribute_q == attribute_size_q) {
6690 if (!caja_file_should_show_directory_item_count (file)) {
6691 return g_strdup ("--")g_strdup_inline ("--");
6692 }
6693 count_unreadable = FALSE(0);
6694 if (caja_file_is_directory (file)) {
6695 caja_file_get_directory_item_count (file, &item_count, &count_unreadable);
6696 }
6697 return g_strdup (count_unreadable ? _("? items") : "...")g_strdup_inline (count_unreadable ? dcgettext (((void*)0), "? items"
, 5) : "...")
;
6698 }
6699 if (attribute_q == attribute_deep_size_q) {
6700 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6701 if (status == CAJA_REQUEST_DONE) {
6702 /* This means no contents at all were readable */
6703 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6704 }
6705 return g_strdup ("...")g_strdup_inline ("...");
6706 }
6707 if (attribute_q == attribute_deep_size_on_disk_q) {
6708 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6709 if (status == CAJA_REQUEST_DONE) {
6710 /* This means no contents at all were readable */
6711 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6712 }
6713 return g_strdup ("...")g_strdup_inline ("...");
6714 }
6715 if (attribute_q == attribute_deep_file_count_q
6716 || attribute_q == attribute_deep_directory_count_q
6717 || attribute_q == attribute_deep_total_count_q) {
6718 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6719 if (status == CAJA_REQUEST_DONE) {
6720 /* This means no contents at all were readable */
6721 return g_strdup (_("? items"))g_strdup_inline (dcgettext (((void*)0), "? items", 5));
6722 }
6723 return g_strdup ("...")g_strdup_inline ("...");
6724 }
6725 if (attribute_q == attribute_type_q) {
6726 return g_strdup (_("unknown type"))g_strdup_inline (dcgettext (((void*)0), "unknown type", 5));
6727 }
6728 if (attribute_q == attribute_mime_type_q) {
6729 return g_strdup (_("unknown MIME type"))g_strdup_inline (dcgettext (((void*)0), "unknown MIME type", 5
))
;
6730 }
6731 if (attribute_q == attribute_trashed_on_q) {
6732 /* If n/a */
6733 return g_strdup ("")g_strdup_inline ("");
6734 }
6735 if (attribute_q == attribute_trash_orig_path_q) {
6736 /* If n/a */
6737 return g_strdup ("")g_strdup_inline ("");
6738 }
6739
6740 /* Fallback, use for both unknown attributes and attributes
6741 * for which we have no more appropriate default.
6742 */
6743 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
6744}
6745
6746char *
6747caja_file_get_string_attribute_with_default (CajaFile *file, const char *attribute_name)
6748{
6749 return caja_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
6750}
6751
6752gboolean
6753caja_file_is_date_sort_attribute_q (GQuark attribute_q)
6754{
6755 if (attribute_q == attribute_modification_date_q ||
6756 attribute_q == attribute_date_modified_q ||
6757 attribute_q == attribute_creation_date_q ||
6758 attribute_q == attribute_date_created_q ||
6759 attribute_q == attribute_accessed_date_q ||
6760 attribute_q == attribute_date_accessed_q ||
6761 attribute_q == attribute_date_changed_q ||
6762 attribute_q == attribute_trashed_on_q ||
6763 attribute_q == attribute_date_permissions_q) {
6764 return TRUE(!(0));
6765 }
6766
6767 return FALSE(0);
6768}
6769
6770/**
6771 * get_description:
6772 *
6773 * Get a user-displayable string representing a file type. The caller
6774 * is responsible for g_free-ing this string.
6775 * @file: CajaFile representing the file in question.
6776 *
6777 * Returns: Newly allocated string ready to display to the user.
6778 *
6779 **/
6780static char *
6781get_description (CajaFile *file)
6782{
6783 const char *mime_type;
6784 char *description;
6785
6786 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_806
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_806
= 1; else _g_boolean_var_806 = 0; _g_boolean_var_806; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6786, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6787
6788 mime_type = file->details->mime_type;
6789 if (eel_str_is_empty (mime_type)) {
6790 return NULL((void*)0);
6791 }
6792
6793 if (g_content_type_is_unknown (mime_type) &&
6794 caja_file_is_executable (file)) {
6795 return g_strdup (_("program"))g_strdup_inline (dcgettext (((void*)0), "program", 5));
6796 }
6797
6798 description = g_content_type_get_description (mime_type);
6799 if (!eel_str_is_empty (description)) {
6800 return description;
6801 }
6802
6803 return g_strdup (mime_type)g_strdup_inline (mime_type);
6804}
6805
6806/* Takes ownership of string */
6807static char *
6808update_description_for_link (CajaFile *file, char *string)
6809{
6810 if (caja_file_is_symbolic_link (file)) {
6811 char *res;
6812
6813 g_assert (!caja_file_is_broken_symbolic_link (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_807
; if (!caja_file_is_broken_symbolic_link (file)) _g_boolean_var_807
= 1; else _g_boolean_var_807 = 0; _g_boolean_var_807; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6813, ((const char*) (__func__)), "!caja_file_is_broken_symbolic_link (file)"
); } while (0)
;
6814 if (string == NULL((void*)0)) {
6815 return g_strdup (_("link"))g_strdup_inline (dcgettext (((void*)0), "link", 5));
6816 }
6817 /* Note to localizers: convert file type string for file
6818 * (e.g. "folder", "plain text") to file type for symbolic link
6819 * to that kind of file (e.g. "link to folder").
6820 */
6821 res = g_strdup_printf (_("Link to %s")dcgettext (((void*)0), "Link to %s", 5), string);
6822 g_free (string);
6823 return res;
6824 }
6825
6826 return string;
6827}
6828
6829static char *
6830caja_file_get_type_as_string (CajaFile *file)
6831{
6832 if (file == NULL((void*)0)) {
6833 return NULL((void*)0);
6834 }
6835
6836 if (caja_file_is_broken_symbolic_link (file)) {
6837 return g_strdup (_("link (broken)"))g_strdup_inline (dcgettext (((void*)0), "link (broken)", 5));
6838 }
6839
6840 return update_description_for_link (file, get_description (file));
6841}
6842
6843/**
6844 * caja_file_get_file_type
6845 *
6846 * Return this file's type.
6847 * @file: CajaFile representing the file in question.
6848 *
6849 * Returns: The type.
6850 *
6851 **/
6852GFileType
6853caja_file_get_file_type (CajaFile *file)
6854{
6855 if (file == NULL((void*)0)) {
6856 return G_FILE_TYPE_UNKNOWN;
6857 }
6858
6859 return file->details->type;
6860}
6861
6862/**
6863 * caja_file_get_mime_type
6864 *
6865 * Return this file's default mime type.
6866 * @file: CajaFile representing the file in question.
6867 *
6868 * Returns: The mime type.
6869 *
6870 **/
6871char *
6872caja_file_get_mime_type (CajaFile *file)
6873{
6874 if (file != NULL((void*)0)) {
6875 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_808
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_808
= 1; else _g_boolean_var_808 = 0; _g_boolean_var_808; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6876 if (file->details->mime_type != NULL((void*)0)) {
6877 return g_strdup (file->details->mime_type)g_strdup_inline (file->details->mime_type);
6878 }
6879 }
6880 return g_strdup ("application/octet-stream")g_strdup_inline ("application/octet-stream");
6881}
6882
6883/**
6884 * caja_file_is_mime_type
6885 *
6886 * Check whether a file is of a particular MIME type, or inherited
6887 * from it.
6888 * @file: CajaFile representing the file in question.
6889 * @mime_type: The MIME-type string to test (e.g. "text/plain")
6890 *
6891 * Return value: TRUE if @mime_type exactly matches the
6892 * file's MIME type.
6893 *
6894 **/
6895gboolean
6896caja_file_is_mime_type (CajaFile *file, const char *mime_type)
6897{
6898 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_809
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_809
= 1; else _g_boolean_var_809 = 0; _g_boolean_var_809; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
6899 g_return_val_if_fail (mime_type != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_810
; if (mime_type != ((void*)0)) _g_boolean_var_810 = 1; else _g_boolean_var_810
= 0; _g_boolean_var_810; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "mime_type != NULL"
); return ((0)); } } while (0)
;
6900
6901 if (file->details->mime_type == NULL((void*)0)) {
6902 return FALSE(0);
6903 }
6904 return g_content_type_is_a (file->details->mime_type,
6905 mime_type);
6906}
6907
6908gboolean
6909caja_file_is_launchable (CajaFile *file)
6910{
6911 gboolean type_can_be_executable;
6912
6913 type_can_be_executable = FALSE(0);
6914 if (file->details->mime_type != NULL((void*)0)) {
6915 type_can_be_executable =
6916 g_content_type_can_be_executable (file->details->mime_type);
6917 }
6918
6919 return type_can_be_executable &&
6920 caja_file_can_get_permissions (file) &&
6921 caja_file_can_execute (file) &&
6922 caja_file_is_executable (file) &&
6923 !caja_file_is_directory (file);
6924}
6925
6926
6927/**
6928 * caja_file_get_emblem_icons
6929 *
6930 * Return the list of names of emblems that this file should display,
6931 * in canonical order.
6932 * @file: CajaFile representing the file in question.
6933 *
6934 * Returns: A list of emblem names.
6935 *
6936 **/
6937GList *
6938caja_file_get_emblem_icons (CajaFile *file,
6939 char **exclude)
6940{
6941 GList *keywords, *l;
6942 GList *icons;
6943 char *icon_names[2];
6944 char *keyword;
6945 int i;
6946 GIcon *icon;
6947
6948 if (file == NULL((void*)0)) {
6949 return NULL((void*)0);
6950 }
6951
6952 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_811
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_811
= 1; else _g_boolean_var_811 = 0; _g_boolean_var_811; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6953
6954 keywords = caja_file_get_keywords (file);
6955 keywords = prepend_automatic_keywords (file, keywords);
6956
6957 icons = NULL((void*)0);
6958 for (l = keywords; l != NULL((void*)0); l = l->next) {
6959 keyword = l->data;
6960
6961#ifdef TRASH_IS_FAST_ENOUGH
6962 if (strcmp (keyword, CAJA_FILE_EMBLEM_NAME_TRASH"trash") == 0) {
6963 char *uri;
6964 gboolean file_is_trash;
6965 /* Leave out the trash emblem for the trash itself, since
6966 * putting a trash emblem on a trash icon is gilding the
6967 * lily.
6968 */
6969 uri = caja_file_get_uri (file);
6970 file_is_trash = strcmp (uri, EEL_TRASH_URI"trash:") == 0;
6971 g_free (uri);
6972 if (file_is_trash) {
6973 continue;
6974 }
6975 }
6976#endif
6977 if (exclude) {
6978 for (i = 0; exclude[i] != NULL((void*)0); i++) {
6979 if (strcmp (exclude[i], keyword) == 0) {
6980 continue;
6981 }
6982 }
6983 }
6984
6985
6986 icon_names[0] = g_strconcat ("emblem-", keyword, NULL((void*)0));
6987 icon_names[1] = keyword;
6988 icon = g_themed_icon_new_from_names (icon_names, 2);
6989 g_free (icon_names[0]);
6990
6991 icons = g_list_prepend (icons, icon);
6992 }
6993
6994 g_list_free_full (keywords, g_free);
6995
6996 return icons;
6997}
6998
6999GList *
7000caja_file_get_emblem_pixbufs (CajaFile *file,
7001 int size,
7002 gboolean force_size,
7003 char **exclude)
7004{
7005 GList *icons, *l;
7006 GList *pixbufs;
7007 GdkPixbuf *pixbuf;
7008 GIcon *icon = NULL((void*)0);
7009 CajaIconInfo *icon_info = NULL((void*)0);
7010
7011 icons = caja_file_get_emblem_icons (file, exclude);
7012 pixbufs = NULL((void*)0);
7013
7014 for (l = icons; l != NULL((void*)0); l = l->next) {
7015 icon = l->data;
7016
7017 icon_info = caja_icon_info_lookup (icon, size, 1);
7018 if (force_size) {
7019 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (icon_info, size);
7020 } else {
7021 pixbuf = caja_icon_info_get_pixbuf_nodefault (icon_info);
7022 }
7023
7024 if (pixbuf) {
7025 pixbufs = g_list_prepend (pixbufs, pixbuf);
7026 }
7027
7028
7029 g_object_unref (icon_info);
7030 g_object_unref (icon);
7031 }
7032 g_list_free (icons);
7033
7034 return g_list_reverse (pixbufs);
7035
7036
7037}
7038
7039static GList *
7040sort_keyword_list_and_remove_duplicates (GList *keywords)
7041{
7042 GList *p;
7043
7044 if (keywords != NULL((void*)0)) {
7045 GList *duplicate_link = NULL((void*)0);
7046
7047 keywords = eel_g_str_list_alphabetize (keywords);
7048
7049 p = keywords;
7050 while (p->next != NULL((void*)0)) {
7051 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) {
7052 duplicate_link = p->next;
7053 keywords = g_list_remove_link (keywords, duplicate_link);
7054 g_list_free_full (duplicate_link, g_free);
7055 } else {
7056 p = p->next;
7057 }
7058 }
7059 }
7060
7061 return keywords;
7062}
7063
7064/**
7065 * caja_file_get_keywords
7066 *
7067 * Return this file's keywords.
7068 * @file: CajaFile representing the file in question.
7069 *
7070 * Returns: A list of keywords.
7071 *
7072 **/
7073GList *
7074caja_file_get_keywords (CajaFile *file)
7075{
7076 GList *keywords;
7077
7078 if (file == NULL((void*)0)) {
7079 return NULL((void*)0);
7080 }
7081
7082 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_812
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_812
= 1; else _g_boolean_var_812 = 0; _g_boolean_var_812; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7083
7084 /* Put all the keywords into a list. */
7085 keywords = caja_file_get_metadata_list
7086 (file, CAJA_METADATA_KEY_EMBLEMS"emblems");
7087
7088 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7089 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7090
7091 return sort_keyword_list_and_remove_duplicates (keywords);
7092}
7093
7094/**
7095 * caja_file_set_keywords
7096 *
7097 * Change this file's keywords.
7098 * @file: CajaFile representing the file in question.
7099 * @keywords: New set of keywords (a GList of strings).
7100 *
7101 **/
7102void
7103caja_file_set_keywords (CajaFile *file, GList *keywords)
7104{
7105 GList *canonical_keywords;
7106
7107 /* Invalidate the emblem compare cache */
7108 g_free (file->details->compare_by_emblem_cache);
7109 file->details->compare_by_emblem_cache = NULL((void*)0);
7110
7111 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_813
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_813
= 1; else _g_boolean_var_813 = 0; _g_boolean_var_813; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7112
7113 canonical_keywords = sort_keyword_list_and_remove_duplicates
7114 (g_list_copy (keywords));
7115 caja_file_set_metadata_list
7116 (file, CAJA_METADATA_KEY_EMBLEMS"emblems", canonical_keywords);
7117 g_list_free (canonical_keywords);
7118}
7119
7120/**
7121 * caja_file_is_symbolic_link
7122 *
7123 * Check if this file is a symbolic link.
7124 * @file: CajaFile representing the file in question.
7125 *
7126 * Returns: True if the file is a symbolic link.
7127 *
7128 **/
7129gboolean
7130caja_file_is_symbolic_link (CajaFile *file)
7131{
7132 return file->details->is_symlink;
7133}
7134
7135gboolean
7136caja_file_is_mountpoint (CajaFile *file)
7137{
7138 return file->details->is_mountpoint;
7139}
7140
7141GMount *
7142caja_file_get_mount (CajaFile *file)
7143{
7144 if (file->details->mount) {
7145 return g_object_ref (file->details->mount)((__typeof__ (file->details->mount)) (g_object_ref) (file
->details->mount))
;
7146 }
7147 return NULL((void*)0);
7148}
7149
7150static void
7151file_mount_unmounted (GMount *mount,
7152 gpointer data)
7153{
7154 CajaFile *file;
7155
7156 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
7157
7158 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_MOUNT);
7159}
7160
7161void
7162caja_file_set_mount (CajaFile *file,
7163 GMount *mount)
7164{
7165 if (file->details->mount) {
7166 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
7167 g_object_unref (file->details->mount);
7168 file->details->mount = NULL((void*)0);
7169 }
7170
7171 if (mount) {
7172 file->details->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
7173 g_signal_connect (mount, "unmounted",g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
7174 G_CALLBACK (file_mount_unmounted), file)g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
;
7175 }
7176}
7177
7178/**
7179 * caja_file_is_broken_symbolic_link
7180 *
7181 * Check if this file is a symbolic link with a missing target.
7182 * @file: CajaFile representing the file in question.
7183 *
7184 * Returns: True if the file is a symbolic link with a missing target.
7185 *
7186 **/
7187gboolean
7188caja_file_is_broken_symbolic_link (CajaFile *file)
7189{
7190 if (file == NULL((void*)0)) {
7191 return FALSE(0);
7192 }
7193
7194 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_814
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_814
= 1; else _g_boolean_var_814 = 0; _g_boolean_var_814; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7195
7196 /* Non-broken symbolic links return the target's type for get_file_type. */
7197 return caja_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7198}
7199
7200static void
7201get_fs_free_cb (GObject *source_object,
7202 GAsyncResult *res,
7203 gpointer user_data)
7204{
7205 CajaDirectory *directory;
7206 guint64 free_space;
7207 GFileInfo *info;
7208
7209 directory = CAJA_DIRECTORY (user_data)((((CajaDirectory*) (void *) ((user_data)))));
7210
7211 free_space = (guint64)-1;
7212 info = g_file_query_filesystem_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
7213 res, NULL((void*)0));
7214 if (info) {
7215 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
7216 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
7217 }
7218 g_object_unref (info);
7219 }
7220
7221 if (directory->details->free_space != free_space) {
7222 CajaFile *file;
7223
7224 directory->details->free_space = free_space;
7225 file = caja_directory_get_existing_corresponding_file (directory);
7226 if (file) {
7227 caja_file_emit_changed (file);
7228 caja_file_unref (file);
7229 }
7230 }
7231 caja_directory_unref (directory);
7232}
7233
7234/**
7235 * caja_file_get_volume_free_space
7236 * Get a nicely formatted char with free space on the file's volume
7237 * @file: CajaFile representing the file in question.
7238 *
7239 * Returns: newly-allocated copy of file size in a formatted string
7240 */
7241char *
7242caja_file_get_volume_free_space (CajaFile *file)
7243{
7244 CajaDirectory *directory;
7245 char *res;
7246 time_t now;
7247
7248 directory = caja_directory_get_for_file (file);
7249
7250 now = time (NULL((void*)0));
7251 /* Update first time and then every 2 seconds */
7252 if (directory->details->free_space_read == 0 ||
7253 (now - directory->details->free_space_read) > 2) {
7254 GFile *location;
7255
7256 directory->details->free_space_read = now;
7257 location = caja_file_get_location (file);
7258 g_file_query_filesystem_info_async (location,
7259 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free",
7260 0, NULL((void*)0),
7261 get_fs_free_cb,
7262 directory); /* Inherits ref */
7263 g_object_unref (location);
7264 } else {
7265 caja_directory_unref (directory);
7266 }
7267
7268
7269 res = NULL((void*)0);
7270
7271 if (directory->details->free_space != (guint64) -1)
7272 {
7273 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
7274 res = g_format_size_full (directory->details->free_space, G_FORMAT_SIZE_IEC_UNITS);
7275 else
7276 res = g_format_size(directory->details->free_space);
7277 }
7278
7279 return res;
7280}
7281
7282/**
7283 * caja_file_get_volume_name
7284 * Get the path of the volume the file resides on
7285 * @file: CajaFile representing the file in question.
7286 *
7287 * Returns: newly-allocated copy of the volume name of the target file,
7288 * if the volume name isn't set, it returns the mount path of the volume
7289 */
7290char *
7291caja_file_get_volume_name (CajaFile *file)
7292{
7293 GFile *location;
7294 char *res;
7295 GMount *mount;
7296
7297 res = NULL((void*)0);
7298
7299 location = caja_file_get_location (file);
7300 mount = g_file_find_enclosing_mount (location, NULL((void*)0), NULL((void*)0));
7301 if (mount) {
7302 res = g_strdup (g_mount_get_name (mount))g_strdup_inline (g_mount_get_name (mount));
7303 g_object_unref (mount);
7304 }
7305 g_object_unref (location);
7306
7307 return res;
7308}
7309
7310/**
7311 * caja_file_get_symbolic_link_target_path
7312 *
7313 * Get the file path of the target of a symbolic link. It is an error
7314 * to call this function on a file that isn't a symbolic link.
7315 * @file: CajaFile representing the symbolic link in question.
7316 *
7317 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7318 */
7319char *
7320caja_file_get_symbolic_link_target_path (CajaFile *file)
7321{
7322 if (!caja_file_is_symbolic_link (file)) {
7323 g_warning ("File has symlink target, but is not marked as symlink");
7324 }
7325
7326 return g_strdup (file->details->symlink_name)g_strdup_inline (file->details->symlink_name);
7327}
7328
7329/**
7330 * caja_file_get_symbolic_link_target_uri
7331 *
7332 * Get the uri of the target of a symbolic link. It is an error
7333 * to call this function on a file that isn't a symbolic link.
7334 * @file: CajaFile representing the symbolic link in question.
7335 *
7336 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7337 */
7338char *
7339caja_file_get_symbolic_link_target_uri (CajaFile *file)
7340{
7341 if (!caja_file_is_symbolic_link (file)) {
7342 g_warning ("File has symlink target, but is not marked as symlink");
7343 }
7344
7345 if (file->details->symlink_name == NULL((void*)0)) {
7346 return NULL((void*)0);
7347 } else {
7348 GFile *location, *parent, *target;
7349 char *target_uri;
7350
7351 target = NULL((void*)0);
7352
7353 location = caja_file_get_location (file);
7354 parent = g_file_get_parent (location);
7355 g_object_unref (location);
7356 if (parent) {
7357 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7358 g_object_unref (parent);
7359 }
7360
7361 target_uri = NULL((void*)0);
7362 if (target) {
7363 target_uri = g_file_get_uri (target);
7364 g_object_unref (target);
7365 }
7366 return target_uri;
7367 }
7368}
7369
7370/**
7371 * caja_file_is_caja_link
7372 *
7373 * Check if this file is a "caja link", meaning a historical
7374 * caja xml link file or a desktop file.
7375 * @file: CajaFile representing the file in question.
7376 *
7377 * Returns: True if the file is a caja link.
7378 *
7379 **/
7380gboolean
7381caja_file_is_caja_link (CajaFile *file)
7382{
7383 if (file->details->mime_type == NULL((void*)0))
7384 {
7385 return FALSE(0);
7386 }
7387 return g_content_type_equals (file->details->mime_type,
7388 "application/x-desktop");
7389}
7390
7391/**
7392 * caja_file_is_directory
7393 *
7394 * Check if this file is a directory.
7395 * @file: CajaFile representing the file in question.
7396 *
7397 * Returns: TRUE if @file is a directory.
7398 *
7399 **/
7400gboolean
7401caja_file_is_directory (CajaFile *file)
7402{
7403 return caja_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
7404}
7405
7406/**
7407 * caja_file_is_user_special_directory
7408 *
7409 * Check if this file is a special platform directory.
7410 * @file: CajaFile representing the file in question.
7411 * @special_directory: GUserDirectory representing the type to test for
7412 *
7413 * Returns: TRUE if @file is a special directory of the given kind.
7414 */
7415gboolean
7416caja_file_is_user_special_directory (CajaFile *file,
7417 GUserDirectory special_directory)
7418{
7419 gboolean is_special_dir;
7420 const gchar *special_dir;
7421
7422 special_dir = g_get_user_special_dir (special_directory);
7423 is_special_dir = FALSE(0);
7424
7425 if (special_dir) {
7426 GFile *loc;
7427 GFile *special_gfile;
7428
7429 loc = caja_file_get_location (file);
7430 special_gfile = g_file_new_for_path (special_dir);
7431 is_special_dir = g_file_equal (loc, special_gfile);
7432 g_object_unref (special_gfile);
7433 g_object_unref (loc);
7434 }
7435
7436 return is_special_dir;
7437}
7438
7439gboolean
7440caja_file_is_archive (CajaFile *file)
7441{
7442 char *mime_type;
7443 int i;
7444 static const char * archive_mime_types[] = { "application/x-gtar",
7445 "application/x-zip",
7446 "application/x-zip-compressed",
7447 "application/zip",
7448 "application/x-zip",
7449 "application/x-tar",
7450 "application/x-7z-compressed",
7451 "application/x-rar",
7452 "application/x-rar-compressed",
7453 "application/x-jar",
7454 "application/x-java-archive",
7455 "application/x-war",
7456 "application/x-ear",
7457 "application/x-arj",
7458 "application/x-gzip",
7459 "application/x-bzip-compressed-tar",
7460 "application/x-compressed-tar" };
7461
7462 g_return_val_if_fail (file != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_815
; if (file != ((void*)0)) _g_boolean_var_815 = 1; else _g_boolean_var_815
= 0; _g_boolean_var_815; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file != NULL"); return
((0)); } } while (0)
;
7463
7464 mime_type = caja_file_get_mime_type (file);
7465 for (i = 0; i < G_N_ELEMENTS (archive_mime_types)(sizeof (archive_mime_types) / sizeof ((archive_mime_types)[0
]))
; i++) {
7466 if (!strcmp (mime_type, archive_mime_types[i])) {
7467 g_free (mime_type);
7468 return TRUE(!(0));
7469 }
7470 }
7471 g_free (mime_type);
7472
7473 return FALSE(0);
7474}
7475
7476
7477/**
7478 * caja_file_is_in_trash
7479 *
7480 * Check if this file is a file in trash.
7481 * @file: CajaFile representing the file in question.
7482 *
7483 * Returns: TRUE if @file is in a trash.
7484 *
7485 **/
7486gboolean
7487caja_file_is_in_trash (CajaFile *file)
7488{
7489 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_816
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_816
= 1; else _g_boolean_var_816 = 0; _g_boolean_var_816; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7489, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7490
7491 return caja_directory_is_in_trash (file->details->directory);
7492}
7493
7494GError *
7495caja_file_get_file_info_error (CajaFile *file)
7496{
7497 if (!file->details->get_info_failed) {
7498 return NULL((void*)0);
7499 }
7500
7501 return file->details->get_info_error;
7502}
7503
7504/**
7505 * caja_file_contains_text
7506 *
7507 * Check if this file contains text.
7508 * This is private and is used to decide whether or not to read the top left text.
7509 * @file: CajaFile representing the file in question.
7510 *
7511 * Returns: TRUE if @file has a text MIME type.
7512 *
7513 **/
7514gboolean
7515caja_file_contains_text (CajaFile *file)
7516{
7517 if (file == NULL((void*)0)) {
7518 return FALSE(0);
7519 }
7520
7521 /* All text files inherit from text/plain */
7522 return caja_file_is_mime_type (file, "text/plain");
7523}
7524
7525/**
7526 * caja_file_is_binary
7527 *
7528 * Check if this file is a binary file.
7529 * This is private and is used to decide whether or not to show the diff
7530 * button in the file conflict dialog.
7531 * @file: CajaFile representing the file in question.
7532 *
7533 * Returns: TRUE if @file is a binary file.
7534 *
7535 **/
7536gboolean
7537caja_file_is_binary (CajaFile *file)
7538{
7539 if (!caja_file_can_read(file))
7540 {
7541 return FALSE(0);
7542 }
7543
7544 gboolean is_binary = FALSE(0);
7545 int i = 0;
7546 FILE *fp;
7547
7548 /* Check the first 4096 bytes of the files. If these contains a 0,
7549 * we can assume the file is binary.
7550 * This idea is taken from python code of meld.
7551 */
7552
7553 fp = g_fopenfopen (g_file_get_path (caja_file_get_location (file)), "r");
7554 if (fp == NULL((void*)0))
7555 {
7556 return FALSE(0);
7557 }
7558
7559 while (!feof (fp)) {
7560 int c;
7561
7562 if (i > 4096) {
7563 break;
7564 }
7565 c = fgetc(fp);
7566 if (c == 0) {
7567 is_binary = TRUE(!(0));
7568 break;
7569 }
7570 i++;
7571 }
7572 fclose(fp);
7573
7574 return is_binary;
7575}
7576
7577/**
7578 * caja_file_is_executable
7579 *
7580 * Check if this file is executable at all.
7581 * @file: CajaFile representing the file in question.
7582 *
7583 * Returns: TRUE if any of the execute bits are set. FALSE if
7584 * not, or if the permissions are unknown.
7585 *
7586 **/
7587gboolean
7588caja_file_is_executable (CajaFile *file)
7589{
7590 if (!file->details->has_permissions) {
7591 /* File's permissions field is not valid.
7592 * Can't access specific permissions, so return FALSE.
7593 */
7594 return FALSE(0);
7595 }
7596
7597 return file->details->can_execute;
7598}
7599
7600/**
7601 * caja_file_peek_top_left_text
7602 *
7603 * Peek at the text from the top left of the file.
7604 * @file: CajaFile representing the file in question.
7605 *
7606 * Returns: NULL if there is no text readable, otherwise, the text.
7607 * This string is owned by the file object and should not
7608 * be kept around or freed.
7609 *
7610 **/
7611char *
7612caja_file_peek_top_left_text (CajaFile *file,
7613 gboolean need_large_text,
7614 gboolean *needs_loading)
7615{
7616 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_817
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_817
= 1; else _g_boolean_var_817 = 0; _g_boolean_var_817; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7617
7618 if (!caja_file_should_get_top_left_text (file)) {
7619 if (needs_loading) {
7620 *needs_loading = FALSE(0);
7621 }
7622 return NULL((void*)0);
7623 }
7624
7625 if (needs_loading) {
7626 *needs_loading = !file->details->top_left_text_is_up_to_date;
7627 if (need_large_text) {
7628 *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text;
7629 }
7630 }
7631
7632 /* Show " ..." in the file until we read the contents in. */
7633 if (!file->details->got_top_left_text) {
7634
7635 if (caja_file_contains_text (file)) {
7636 return " ...";
7637 }
7638 return NULL((void*)0);
7639 }
7640
7641 /* Show what we read in. */
7642 return file->details->top_left_text;
7643}
7644
7645/**
7646 * caja_file_get_top_left_text
7647 *
7648 * Get the text from the top left of the file.
7649 * @file: CajaFile representing the file in question.
7650 *
7651 * Returns: NULL if there is no text readable, otherwise, the text.
7652 *
7653 **/
7654char *
7655caja_file_get_top_left_text (CajaFile *file)
7656{
7657 return g_strdup (caja_file_peek_top_left_text (file, FALSE, NULL))g_strdup_inline (caja_file_peek_top_left_text (file, (0), ((void
*)0)))
;
7658}
7659
7660char *
7661caja_file_get_filesystem_id (CajaFile *file)
7662{
7663 return g_strdup (file->details->filesystem_id)g_strdup_inline (file->details->filesystem_id);
7664}
7665
7666CajaFile *
7667caja_file_get_trash_original_file (CajaFile *file)
7668{
7669 CajaFile *original_file;
7670
7671 original_file = NULL((void*)0);
7672
7673 if (file->details->trash_orig_path != NULL((void*)0)) {
7674 GFile *location;
7675
7676 location = g_file_new_for_path (file->details->trash_orig_path);
7677 original_file = caja_file_get (location);
7678 g_object_unref (location);
7679 }
7680
7681 return original_file;
7682
7683}
7684
7685void
7686caja_file_mark_gone (CajaFile *file)
7687{
7688 CajaDirectory *directory;
7689
7690 if (file->details->is_gone)
7691 return;
7692
7693 file->details->is_gone = TRUE(!(0));
7694
7695 update_links_if_target (file);
7696
7697 /* Drop it from the symlink hash ! */
7698 remove_from_link_hash_table (file);
7699
7700 /* Let the directory know it's gone. */
7701 directory = file->details->directory;
7702 if (!caja_file_is_self_owned (file)) {
7703 caja_directory_remove_file (directory, file);
7704 }
7705
7706 caja_file_clear_info (file);
7707
7708 /* FIXME bugzilla.gnome.org 42429:
7709 * Maybe we can get rid of the name too eventually, but
7710 * for now that would probably require too many if statements
7711 * everywhere anyone deals with the name. Maybe we can give it
7712 * a hard-coded "<deleted>" name or something.
7713 */
7714}
7715
7716/**
7717 * caja_file_changed
7718 *
7719 * Notify the user that this file has changed.
7720 * @file: CajaFile representing the file in question.
7721 **/
7722void
7723caja_file_changed (CajaFile *file)
7724{
7725 GList fake_list;
7726
7727 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_818
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_818
= 1; else _g_boolean_var_818 = 0; _g_boolean_var_818; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7728
7729 if (caja_file_is_self_owned (file)) {
7730 caja_file_emit_changed (file);
7731 } else {
7732 fake_list.data = file;
7733 fake_list.next = NULL((void*)0);
7734 fake_list.prev = NULL((void*)0);
7735 caja_directory_emit_change_signals
7736 (file->details->directory, &fake_list);
7737 }
7738}
7739
7740/**
7741 * caja_file_updated_deep_count_in_progress
7742 *
7743 * Notify clients that a newer deep count is available for
7744 * the directory in question.
7745 */
7746void
7747caja_file_updated_deep_count_in_progress (CajaFile *file) {
7748 GList *link_files, *node;
7749
7750 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_819
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_819
= 1; else _g_boolean_var_819 = 0; _g_boolean_var_819; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7750, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7751 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_820
; if (caja_file_is_directory (file)) _g_boolean_var_820 = 1; else
_g_boolean_var_820 = 0; _g_boolean_var_820; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 7751, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
7752
7753 /* Send out a signal. */
7754 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
7755
7756 /* Tell link files pointing to this object about the change. */
7757 link_files = get_link_files (file);
7758 for (node = link_files; node != NULL((void*)0); node = node->next) {
7759 caja_file_updated_deep_count_in_progress (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))));
7760 }
7761 caja_file_list_free (link_files);
7762}
7763
7764/**
7765 * caja_file_emit_changed
7766 *
7767 * Emit a file changed signal.
7768 * This can only be called by the directory, since the directory
7769 * also has to emit a files_changed signal.
7770 *
7771 * @file: CajaFile representing the file in question.
7772 **/
7773void
7774caja_file_emit_changed (CajaFile *file)
7775{
7776 GList *link_files, *p;
7777
7778 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_821
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_821
= 1; else _g_boolean_var_821 = 0; _g_boolean_var_821; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7778, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7779
7780
7781 /* Invalidate the emblem compare cache. -- This is not the cleanest
7782 * place to do it but it is the one guaranteed bottleneck through
7783 * which all change notifications pass.
7784 */
7785 g_free (file->details->compare_by_emblem_cache);
7786 file->details->compare_by_emblem_cache = NULL((void*)0);
7787
7788 /* Send out a signal. */
7789 g_signal_emit (file, signals[CHANGED], 0, file);
7790
7791 /* Tell link files pointing to this object about the change. */
7792 link_files = get_link_files (file);
7793 for (p = link_files; p != NULL((void*)0); p = p->next) {
7794 if (p->data != file) {
7795 caja_file_changed (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
7796 }
7797 }
7798 caja_file_list_free (link_files);
7799}
7800
7801/**
7802 * caja_file_is_gone
7803 *
7804 * Check if a file has already been deleted.
7805 * @file: CajaFile representing the file in question.
7806 *
7807 * Returns: TRUE if the file is already gone.
7808 **/
7809gboolean
7810caja_file_is_gone (CajaFile *file)
7811{
7812 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_822
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_822
= 1; else _g_boolean_var_822 = 0; _g_boolean_var_822; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7813
7814 return file->details->is_gone;
7815}
7816
7817/**
7818 * caja_file_is_not_yet_confirmed
7819 *
7820 * Check if we're in a state where we don't know if a file really
7821 * exists or not, before the initial I/O is complete.
7822 * @file: CajaFile representing the file in question.
7823 *
7824 * Returns: TRUE if the file is already gone.
7825 **/
7826gboolean
7827caja_file_is_not_yet_confirmed (CajaFile *file)
7828{
7829 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_823
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_823
= 1; else _g_boolean_var_823 = 0; _g_boolean_var_823; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7830
7831 return !file->details->got_file_info;
7832}
7833
7834/**
7835 * caja_file_check_if_ready
7836 *
7837 * Check whether the values for a set of file attributes are
7838 * currently available, without doing any additional work. This
7839 * is useful for callers that want to reflect updated information
7840 * when it is ready but don't want to force the work required to
7841 * obtain the information, which might be slow network calls, e.g.
7842 *
7843 * @file: The file being queried.
7844 * @file_attributes: A bit-mask with the desired information.
7845 *
7846 * Return value: TRUE if all of the specified attributes are currently readable.
7847 */
7848gboolean
7849caja_file_check_if_ready (CajaFile *file,
7850 CajaFileAttributes file_attributes)
7851{
7852 /* To be parallel with call_when_ready, return
7853 * TRUE for NULL file.
7854 */
7855 if (file == NULL((void*)0)) {
7856 return TRUE(!(0));
7857 }
7858
7859 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_824
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_824
= 1; else _g_boolean_var_824 = 0; _g_boolean_var_824; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7860
7861 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7862 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7863 check_if_ready, (file, file_attributes))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
;
7864}
7865
7866void
7867caja_file_call_when_ready (CajaFile *file,
7868 CajaFileAttributes file_attributes,
7869 CajaFileCallback callback,
7870 gpointer callback_data)
7871
7872{
7873 if (file == NULL((void*)0)) {
7874 (* callback) (file, callback_data);
7875 return;
7876 }
7877
7878 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_825
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_825
= 1; else _g_boolean_var_825 = 0; _g_boolean_var_825; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7879
7880 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7881 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7882 call_when_ready, (file, file_attributes,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7883 callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
;
7884}
7885
7886void
7887caja_file_cancel_call_when_ready (CajaFile *file,
7888 CajaFileCallback callback,
7889 gpointer callback_data)
7890{
7891 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_826
; if (callback != ((void*)0)) _g_boolean_var_826 = 1; else _g_boolean_var_826
= 0; _g_boolean_var_826; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
7892
7893 if (file == NULL((void*)0)) {
7894 return;
7895 }
7896
7897 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_827
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_827
= 1; else _g_boolean_var_827 = 0; _g_boolean_var_827; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7898
7899 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7900 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7901 cancel_call_when_ready, (file, callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
;
7902}
7903
7904static void
7905invalidate_directory_count (CajaFile *file)
7906{
7907 file->details->directory_count_is_up_to_date = FALSE(0);
7908}
7909
7910static void
7911invalidate_deep_counts (CajaFile *file)
7912{
7913 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
7914}
7915
7916static void
7917invalidate_mime_list (CajaFile *file)
7918{
7919 file->details->mime_list_is_up_to_date = FALSE(0);
7920}
7921
7922static void
7923invalidate_top_left_text (CajaFile *file)
7924{
7925 file->details->top_left_text_is_up_to_date = FALSE(0);
7926}
7927
7928static void
7929invalidate_file_info (CajaFile *file)
7930{
7931 file->details->file_info_is_up_to_date = FALSE(0);
7932}
7933
7934static void
7935invalidate_link_info (CajaFile *file)
7936{
7937 file->details->link_info_is_up_to_date = FALSE(0);
7938}
7939
7940static void
7941invalidate_thumbnail (CajaFile *file)
7942{
7943 file->details->thumbnail_is_up_to_date = FALSE(0);
7944}
7945
7946static void
7947invalidate_mount (CajaFile *file)
7948{
7949 file->details->mount_is_up_to_date = FALSE(0);
7950}
7951
7952void
7953caja_file_invalidate_extension_info_internal (CajaFile *file)
7954{
7955 if (file->details->pending_info_providers)
7956 g_list_free_full (file->details->pending_info_providers, g_object_unref);
7957
7958 file->details->pending_info_providers =
7959 caja_extensions_get_for_type (CAJA_TYPE_INFO_PROVIDER(caja_info_provider_get_type ()));
7960}
7961
7962void
7963caja_file_invalidate_attributes_internal (CajaFile *file,
7964 CajaFileAttributes file_attributes)
7965{
7966 Request request;
7967
7968 if (file == NULL((void*)0)) {
7969 return;
7970 }
7971
7972 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
7973 /* Desktop icon files are always up to date.
7974 * If we invalidate their attributes they
7975 * will lose data, so we just ignore them.
7976 */
7977 return;
7978 }
7979
7980 request = caja_directory_set_up_request (file_attributes);
7981
7982 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)((request) & (1<<(REQUEST_DIRECTORY_COUNT)))) {
7983 invalidate_directory_count (file);
7984 }
7985 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)((request) & (1<<(REQUEST_DEEP_COUNT)))) {
7986 invalidate_deep_counts (file);
7987 }
7988 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)((request) & (1<<(REQUEST_MIME_LIST)))) {
7989 invalidate_mime_list (file);
7990 }
7991 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)((request) & (1<<(REQUEST_FILE_INFO)))) {
7992 invalidate_file_info (file);
7993 }
7994 if (REQUEST_WANTS_TYPE (request, REQUEST_TOP_LEFT_TEXT)((request) & (1<<(REQUEST_TOP_LEFT_TEXT)))) {
7995 invalidate_top_left_text (file);
7996 }
7997 if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)((request) & (1<<(REQUEST_LINK_INFO)))) {
7998 invalidate_link_info (file);
7999 }
8000 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)((request) & (1<<(REQUEST_EXTENSION_INFO)))) {
8001 caja_file_invalidate_extension_info_internal (file);
8002 }
8003 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)((request) & (1<<(REQUEST_THUMBNAIL)))) {
8004 invalidate_thumbnail (file);
8005 }
8006 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)((request) & (1<<(REQUEST_MOUNT)))) {
8007 invalidate_mount (file);
8008 }
8009
8010 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
8011}
8012
8013gboolean
8014caja_file_has_open_window (CajaFile *file)
8015{
8016 return file->details->has_open_window;
8017}
8018
8019void
8020caja_file_set_has_open_window (CajaFile *file,
8021 gboolean has_open_window)
8022{
8023 has_open_window = (has_open_window != FALSE(0));
8024
8025 if (file->details->has_open_window != has_open_window) {
8026 file->details->has_open_window = has_open_window;
8027 caja_file_changed (file);
8028 }
8029}
8030
8031
8032gboolean
8033caja_file_is_thumbnailing (CajaFile *file)
8034{
8035 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_828
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_828
= 1; else _g_boolean_var_828 = 0; _g_boolean_var_828; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
8036
8037 return file->details->is_thumbnailing;
8038}
8039
8040void
8041caja_file_set_is_thumbnailing (CajaFile *file,
8042 gboolean is_thumbnailing)
8043{
8044 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_829
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_829
= 1; else _g_boolean_var_829 = 0; _g_boolean_var_829; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
8045
8046 file->details->is_thumbnailing = is_thumbnailing;
8047}
8048
8049
8050/**
8051 * caja_file_invalidate_attributes
8052 *
8053 * Invalidate the specified attributes and force a reload.
8054 * @file: CajaFile representing the file in question.
8055 * @file_attributes: attributes to froget.
8056 **/
8057
8058void
8059caja_file_invalidate_attributes (CajaFile *file,
8060 CajaFileAttributes file_attributes)
8061{
8062 /* Cancel possible in-progress loads of any of these attributes */
8063 caja_directory_cancel_loading_file_attributes (file->details->directory,
8064 file,
8065 file_attributes);
8066
8067 /* Actually invalidate the values */
8068 caja_file_invalidate_attributes_internal (file, file_attributes);
8069
8070 caja_directory_add_file_to_work_queue (file->details->directory, file);
8071
8072 /* Kick off I/O if necessary */
8073 caja_directory_async_state_changed (file->details->directory);
8074}
8075
8076CajaFileAttributes
8077caja_file_get_all_attributes (void)
8078{
8079 return CAJA_FILE_ATTRIBUTE_INFO |
8080 CAJA_FILE_ATTRIBUTE_LINK_INFO |
8081 CAJA_FILE_ATTRIBUTE_DEEP_COUNTS |
8082 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8083 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8084 CAJA_FILE_ATTRIBUTE_TOP_LEFT_TEXT |
8085 CAJA_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
8086 CAJA_FILE_ATTRIBUTE_EXTENSION_INFO |
8087 CAJA_FILE_ATTRIBUTE_THUMBNAIL |
8088 CAJA_FILE_ATTRIBUTE_MOUNT;
8089}
8090
8091void
8092caja_file_invalidate_all_attributes (CajaFile *file)
8093{
8094 CajaFileAttributes all_attributes;
8095
8096 all_attributes = caja_file_get_all_attributes ();
8097 caja_file_invalidate_attributes (file, all_attributes);
8098}
8099
8100
8101/**
8102 * caja_file_dump
8103 *
8104 * Debugging call, prints out the contents of the file
8105 * fields.
8106 *
8107 * @file: file to dump.
8108 **/
8109void
8110caja_file_dump (CajaFile *file)
8111{
8112 long size = file->details->deep_size;
8113 long size_on_disk = file->details->deep_size_on_disk;
8114 char *uri;
8115 const char *file_kind;
8116
8117 uri = caja_file_get_uri (file);
8118 g_print ("uri: %s \n", uri);
8119 if (!file->details->got_file_info) {
8120 g_print ("no file info \n");
8121 } else if (file->details->get_info_failed) {
8122 g_print ("failed to get file info \n");
8123 } else {
8124 g_print ("size: %ld \n", size);
8125 g_print ("disk size: %ld \n", size_on_disk);
8126 switch (file->details->type) {
8127 case G_FILE_TYPE_REGULAR:
8128 file_kind = "regular file";
8129 break;
8130 case G_FILE_TYPE_DIRECTORY:
8131 file_kind = "folder";
8132 break;
8133 case G_FILE_TYPE_SPECIAL:
8134 file_kind = "special";
8135 break;
8136 case G_FILE_TYPE_SYMBOLIC_LINK:
8137 file_kind = "symbolic link";
8138 break;
8139 case G_FILE_TYPE_UNKNOWN:
8140 default:
8141 file_kind = "unknown";
8142 break;
8143 }
8144 g_print ("kind: %s \n", file_kind);
8145 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) {
8146 g_print ("link to %s \n", file->details->symlink_name);
8147 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8148 }
8149 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8150 }
8151 g_free (uri);
8152}
8153
8154/**
8155 * caja_file_list_ref
8156 *
8157 * Ref all the files in a list.
8158 * @list: GList of files.
8159 **/
8160GList *
8161caja_file_list_ref (GList *list)
8162{
8163 g_list_foreach (list, (GFunc) caja_file_ref, NULL((void*)0));
8164 return list;
8165}
8166
8167/**
8168 * caja_file_list_unref
8169 *
8170 * Unref all the files in a list.
8171 * @list: GList of files.
8172 **/
8173void
8174caja_file_list_unref (GList *list)
8175{
8176 g_list_foreach (list, (GFunc) caja_file_unref, NULL((void*)0));
8177}
8178
8179/**
8180 * caja_file_list_free
8181 *
8182 * Free a list of files after unrefing them.
8183 * @list: GList of files.
8184 **/
8185void
8186caja_file_list_free (GList *list)
8187{
8188 caja_file_list_unref (list);
8189 g_list_free (list);
8190}
8191
8192/**
8193 * caja_file_list_copy
8194 *
8195 * Copy the list of files, making a new ref of each,
8196 * @list: GList of files.
8197 **/
8198GList *
8199caja_file_list_copy (GList *list)
8200{
8201 return g_list_copy (caja_file_list_ref (list));
8202}
8203
8204static gboolean
8205get_attributes_for_default_sort_type (CajaFile *file,
8206 gboolean *is_download,
8207 gboolean *is_trash)
8208{
8209 gboolean is_download_dir, is_desktop_dir, is_trash_dir, retval;
8210
8211 *is_download = FALSE(0);
8212 *is_trash = FALSE(0);
8213 retval = FALSE(0);
8214
8215 /* special handling for certain directories */
8216 if (file && caja_file_is_directory (file)) {
8217 is_download_dir =
8218 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8219 is_desktop_dir =
8220 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP);
8221 is_trash_dir =
8222 caja_file_is_in_trash (file);
8223
8224 if (is_download_dir && !is_desktop_dir) {
8225 *is_download = TRUE(!(0));
8226 retval = TRUE(!(0));
8227 } else if (is_trash_dir) {
8228 *is_trash = TRUE(!(0));
8229 retval = TRUE(!(0));
8230 }
8231 }
8232
8233 return retval;
8234}
8235
8236CajaFileSortType
8237caja_file_get_default_sort_type (CajaFile *file,
8238 gboolean *reversed)
8239{
8240 CajaFileSortType retval;
8241 gboolean is_download, is_trash, res;
8242
8243 retval = CAJA_FILE_SORT_NONE;
8244 is_download = is_trash = FALSE(0);
8245 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8246
8247 if (res) {
8248 if (is_download) {
8249 retval = CAJA_FILE_SORT_BY_MTIME;
8250 } else if (is_trash) {
8251 retval = CAJA_FILE_SORT_BY_TRASHED_TIME;
8252 }
8253
8254 if (reversed != NULL((void*)0)) {
8255 *reversed = res;
8256 }
8257 }
8258
8259 return retval;
8260}
8261
8262const gchar *
8263caja_file_get_default_sort_attribute (CajaFile *file,
8264 gboolean *reversed)
8265{
8266 const gchar *retval;
8267 gboolean is_download, is_trash, res;
8268
8269 retval = NULL((void*)0);
8270 is_download = is_trash = FALSE(0);
8271 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8272
8273 if (res) {
8274 if (is_download) {
8275 retval = g_quark_to_string (attribute_date_modified_q);
8276 } else if (is_trash) {
8277 retval = g_quark_to_string (attribute_trashed_on_q);
8278 }
8279
8280 if (reversed != NULL((void*)0)) {
8281 *reversed = res;
8282 }
8283 }
8284
8285 return retval;
8286}
8287
8288static int
8289compare_by_display_name_cover (gconstpointer a, gconstpointer b)
8290{
8291 return compare_by_display_name (CAJA_FILE (a)((((CajaFile*) (void *) ((a))))), CAJA_FILE (b)((((CajaFile*) (void *) ((b))))));
8292}
8293
8294/**
8295 * caja_file_list_sort_by_display_name
8296 *
8297 * Sort the list of files by file name.
8298 * @list: GList of files.
8299 **/
8300GList *
8301caja_file_list_sort_by_display_name (GList *list)
8302{
8303 return g_list_sort (list, compare_by_display_name_cover);
8304}
8305
8306static GList *ready_data_list = NULL((void*)0);
8307
8308typedef struct
8309{
8310 GList *file_list;
8311 GList *remaining_files;
8312 CajaFileListCallback callback;
8313 gpointer callback_data;
8314} FileListReadyData;
8315
8316static void
8317file_list_ready_data_free (FileListReadyData *data)
8318{
8319 GList *l;
8320
8321 l = g_list_find (ready_data_list, data);
8322 if (l != NULL((void*)0)) {
8323 ready_data_list = g_list_delete_link (ready_data_list, l);
8324
8325 caja_file_list_free (data->file_list);
8326 g_list_free (data->remaining_files);
8327 g_free (data);
8328 }
8329}
8330
8331static FileListReadyData *
8332file_list_ready_data_new (GList *file_list,
8333 CajaFileListCallback callback,
8334 gpointer callback_data)
8335{
8336 FileListReadyData *data;
8337
8338 data = g_new0 (FileListReadyData, 1)(FileListReadyData *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (FileListReadyData); 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; }))
;
8339 data->file_list = caja_file_list_copy (file_list);
8340 data->remaining_files = g_list_copy (file_list);
8341 data->callback = callback;
8342 data->callback_data = callback_data;
8343
8344 ready_data_list = g_list_prepend (ready_data_list, data);
8345
8346 return data;
8347}
8348
8349static void
8350file_list_file_ready_callback (CajaFile *file,
8351 gpointer user_data)
8352{
8353 FileListReadyData *data;
8354
8355 data = user_data;
8356 data->remaining_files = g_list_remove (data->remaining_files, file);
8357
8358 if (data->remaining_files == NULL((void*)0)) {
8359 if (data->callback) {
8360 (*data->callback) (data->file_list, data->callback_data);
8361 }
8362
8363 file_list_ready_data_free (data);
8364 }
8365}
8366
8367void
8368caja_file_list_call_when_ready (GList *file_list,
8369 CajaFileAttributes attributes,
8370 CajaFileListHandle **handle,
8371 CajaFileListCallback callback,
8372 gpointer callback_data)
8373{
8374 GList *l;
8375 FileListReadyData *data;
8376 CajaFile *file = NULL((void*)0);
8377
8378 g_return_if_fail (file_list != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_830
; if (file_list != ((void*)0)) _g_boolean_var_830 = 1; else _g_boolean_var_830
= 0; _g_boolean_var_830; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_list != NULL"
); return; } } while (0)
;
8379
8380 data = file_list_ready_data_new
8381 (file_list, callback, callback_data);
8382
8383 if (handle) {
8384 *handle = (CajaFileListHandle *) data;
8385 }
8386
8387
8388 l = file_list;
8389 while (l != NULL((void*)0)) {
8390 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8391 /* Need to do this here, as the list can be modified by this call */
8392 l = l->next;
8393
8394 if (file)
8395 caja_file_call_when_ready (file,
8396 attributes,
8397 file_list_file_ready_callback,
8398 data);
8399 }
8400}
8401
8402void
8403caja_file_list_cancel_call_when_ready (CajaFileListHandle *handle)
8404{
8405 GList *l;
8406 FileListReadyData *data;
8407
8408 g_return_if_fail (handle != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_831
; if (handle != ((void*)0)) _g_boolean_var_831 = 1; else _g_boolean_var_831
= 0; _g_boolean_var_831; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "handle != NULL")
; return; } } while (0)
;
8409
8410 data = (FileListReadyData *) handle;
8411
8412 l = g_list_find (ready_data_list, data);
8413 if (l != NULL((void*)0)) {
8414 CajaFile *file = NULL((void*)0);
8415
8416 for (l = data->remaining_files; l != NULL((void*)0); l = l->next) {
8417 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8418
8419 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8420 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8421 cancel_call_when_ready, (file, file_list_file_ready_callback, data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
;
8422 }
8423
8424 file_list_ready_data_free (data);
8425 }
8426}
8427
8428static char *
8429try_to_make_utf8 (const char *text, int *length)
8430{
8431 static const char *encodings_to_try[2];
8432 static int n_encodings_to_try = 0;
8433 gsize converted_length;
8434 GError *conversion_error;
8435 char *utf8_text;
8436 int i;
8437
8438 if (n_encodings_to_try == 0) {
8439 const char *charset;
8440 gboolean charset_is_utf8;
8441
8442 charset_is_utf8 = g_get_charset (&charset);
8443 if (!charset_is_utf8) {
8444 encodings_to_try[n_encodings_to_try++] = charset;
8445 }
8446
8447 if (g_ascii_strcasecmp (charset, "ISO-8859-1") != 0) {
8448 encodings_to_try[n_encodings_to_try++] = "ISO-8859-1";
8449 }
8450 }
8451
8452 utf8_text = NULL((void*)0);
8453 for (i = 0; i < n_encodings_to_try; i++) {
8454 conversion_error = NULL((void*)0);
8455 utf8_text = g_convert (text, *length,
8456 "UTF-8", encodings_to_try[i],
8457 NULL((void*)0), &converted_length, &conversion_error);
8458 if (utf8_text != NULL((void*)0)) {
8459 *length = converted_length;
8460 break;
8461 }
8462 g_error_free (conversion_error);
8463 }
8464
8465 return utf8_text;
8466}
8467
8468
8469
8470/* Extract the top left part of the read-in text. */
8471char *
8472caja_extract_top_left_text (const char *text,
8473 gboolean large,
8474 int length)
8475{
8476 GString* buffer;
8477 const gchar *in;
8478 const gchar *end;
8479 int line, i;
8480 gunichar c;
8481 char *text_copy;
8482 const char *utf8_end;
8483 gboolean validated;
8484 int max_bytes, max_lines, max_cols;
8485
8486 if (large) {
8487 max_bytes = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES10000;
8488 max_lines = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES24;
8489 max_cols = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE80;
8490 } else {
8491 max_bytes = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES1024;
8492 max_lines = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES5;
8493 max_cols = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE10;
8494 }
8495
8496
8497
8498 text_copy = NULL((void*)0);
8499 if (text != NULL((void*)0)) {
8500 /* Might be a partial utf8 character at the end if we didn't read whole file */
8501 validated = g_utf8_validate (text, length, &utf8_end);
8502 if (!validated &&
8503 !(length >= max_bytes &&
8504 text + length - utf8_end < 6)) {
8505 text_copy = try_to_make_utf8 (text, &length);
8506 text = text_copy;
8507 } else if (!validated) {
8508 length = utf8_end - text;
8509 }
8510 }
8511
8512 if (text == NULL((void*)0) || length == 0) {
8513 return NULL((void*)0);
8514 }
8515
8516 buffer = g_string_new ("");
8517 end = text + length; in = text;
8518
8519 for (line = 0; line < max_lines; line++) {
8520 /* Extract one line. */
8521 for (i = 0; i < max_cols; ) {
8522 if (*in == '\n') {
8523 break;
8524 }
8525
8526 c = g_utf8_get_char (in);
8527
8528 if (g_unichar_isprint (c)) {
8529 g_string_append_unichar (buffer, c);
8530 i++;
8531 }
8532
8533 in = g_utf8_next_char (in)(char *)((in) + g_utf8_skip[*(const guchar *)(in)]);
8534 if (in == end) {
8535 goto done;
8536 }
8537 }
8538
8539 /* Skip the rest of the line. */
8540 while (*in != '\n') {
8541 if (++in == end) {
8542 goto done;
8543 }
8544 }
8545 if (++in == end) {
8546 goto done;
8547 }
8548
8549 /* Put a new-line separator in. */
8550 g_string_append_c(buffer, '\n')g_string_append_c_inline (buffer, '\n');
8551 }
8552 done:
8553 g_free (text_copy);
8554
8555 return g_string_free(buffer, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((buffer
), ((0))) : g_string_free_and_steal (buffer)) : (g_string_free
) ((buffer), ((0))))
;
8556}
8557
8558static void
8559thumbnail_limit_changed_callback (gpointer user_data)
8560{
8561 g_settings_get (caja_preferences,
8562 CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT"thumbnail-limit",
8563 "t", &cached_thumbnail_limit);
8564
8565 /* Tell the world that icons might have changed. We could invent a narrower-scope
8566 * signal to mean only "thumbnails might have changed" if this ends up being slow
8567 * for some reason.
8568 */
8569 emit_change_signals_for_all_files_in_all_directories ();
8570}
8571
8572static void
8573thumbnail_size_changed_callback (gpointer user_data)
8574{
8575 cached_thumbnail_size = g_settings_get_int (caja_icon_view_preferences, CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE"thumbnail-size");
8576
8577 /* Tell the world that icons might have changed. We could invent a narrower-scope
8578 * signal to mean only "thumbnails might have changed" if this ends up being slow
8579 * for some reason.
8580 */
8581 emit_change_signals_for_all_files_in_all_directories ();
8582}
8583
8584static void
8585show_thumbnails_changed_callback (gpointer user_data)
8586{
8587 show_image_thumbs = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS"show-image-thumbnails");
8588
8589 /* Tell the world that icons might have changed. We could invent a narrower-scope
8590 * signal to mean only "thumbnails might have changed" if this ends up being slow
8591 * for some reason.
8592 */
8593 emit_change_signals_for_all_files_in_all_directories ();
8594}
8595
8596static void
8597mime_type_data_changed_callback (GObject *signaller, gpointer user_data)
8598{
8599 /* Tell the world that icons might have changed. We could invent a narrower-scope
8600 * signal to mean only "thumbnails might have changed" if this ends up being slow
8601 * for some reason.
8602 */
8603 emit_change_signals_for_all_files_in_all_directories ();
8604}
8605
8606static void
8607icon_theme_changed_callback (GtkIconTheme *icon_theme,
8608 gpointer user_data)
8609{
8610 /* Clear all pixmap caches as the icon => pixmap lookup changed */
8611 caja_icon_info_clear_caches ();
8612
8613 /* Tell the world that icons might have changed. We could invent a narrower-scope
8614 * signal to mean only "thumbnails might have changed" if this ends up being slow
8615 * for some reason.
8616 */
8617 emit_change_signals_for_all_files_in_all_directories ();
8618}
8619
8620static void
8621caja_file_class_init (CajaFileClass *class)
8622{
8623 GtkIconTheme *icon_theme;
8624
8625 caja_file_info_getter = caja_file_get_internal;
8626
8627 attribute_name_q = g_quark_from_static_string ("name");
8628 attribute_size_q = g_quark_from_static_string ("size");
8629 attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
8630 attribute_type_q = g_quark_from_static_string ("type");
8631 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
8632 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
8633 attribute_creation_date_q = g_quark_from_static_string ("creation_date");
8634 attribute_date_created_q = g_quark_from_static_string ("date_created");
8635 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
8636 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
8637 attribute_emblems_q = g_quark_from_static_string ("emblems");
8638 attribute_extension_q = g_quark_from_static_string ("extension");
8639 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
8640 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
8641 attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
8642 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
8643 attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
8644 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
8645 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
8646 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
8647 attribute_date_changed_q = g_quark_from_static_string ("date_changed");
8648 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
8649 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
8650 attribute_date_permissions_q = g_quark_from_static_string ("date_permissions");
8651 attribute_permissions_q = g_quark_from_static_string ("permissions");
8652 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
8653 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
8654 attribute_owner_q = g_quark_from_static_string ("owner");
8655 attribute_group_q = g_quark_from_static_string ("group");
8656 attribute_uri_q = g_quark_from_static_string ("uri");
8657 attribute_where_q = g_quark_from_static_string ("where");
8658 attribute_link_target_q = g_quark_from_static_string ("link_target");
8659 attribute_volume_q = g_quark_from_static_string ("volume");
8660 attribute_free_space_q = g_quark_from_static_string ("free_space");
8661
8662 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = finalize;
8663 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->constructor = caja_file_constructor;
8664
8665 signals[CHANGED] =
8666 g_signal_new ("changed",
8667 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8668 G_SIGNAL_RUN_LAST,
8669 G_STRUCT_OFFSET (CajaFileClass, changed)((glong) __builtin_offsetof(CajaFileClass, changed)),
8670 NULL((void*)0), NULL((void*)0),
8671 g_cclosure_marshal_VOID__VOID,
8672 G_TYPE_NONE((GType) ((1) << (2))), 0);
8673
8674 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
8675 g_signal_new ("updated_deep_count_in_progress",
8676 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8677 G_SIGNAL_RUN_LAST,
8678 G_STRUCT_OFFSET (CajaFileClass, updated_deep_count_in_progress)((glong) __builtin_offsetof(CajaFileClass, updated_deep_count_in_progress
))
,
8679 NULL((void*)0), NULL((void*)0),
8680 g_cclosure_marshal_VOID__VOID,
8681 G_TYPE_NONE((GType) ((1) << (2))), 0);
8682
8683 eel_g_settings_add_auto_enum (caja_preferences,
8684 CAJA_PREFERENCES_DATE_FORMAT"date-format",
8685 &date_format_pref);
8686
8687 thumbnail_limit_changed_callback (NULL((void*)0));
8688 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8689 "changed::" CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8690 G_CALLBACK (thumbnail_limit_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8691 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8692 thumbnail_size_changed_callback (NULL((void*)0));
8693 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8694 "changed::" CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8695 G_CALLBACK (thumbnail_size_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8696 NULL)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8697 show_thumbnails_changed_callback (NULL((void*)0));
8698 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8699 "changed::" CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8700 G_CALLBACK (show_thumbnails_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8701 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8702
8703 icon_theme = gtk_icon_theme_get_default ();
8704 g_signal_connect_object (icon_theme,
8705 "changed",
8706 G_CALLBACK (icon_theme_changed_callback)((GCallback) (icon_theme_changed_callback)),
8707 NULL((void*)0), 0);
8708
8709 g_signal_connect (caja_signaller_get_current (),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8710 "mime_data_changed",g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8711 G_CALLBACK (mime_type_data_changed_callback),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8712 NULL)g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
8713}
8714
8715static void
8716caja_file_add_emblem (CajaFile *file,
8717 const char *emblem_name)
8718{
8719 if (file->details->pending_info_providers) {
8720 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
8721 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8722 } else {
8723 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
8724 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8725 }
8726
8727 caja_file_changed (file);
8728}
8729
8730static void
8731caja_file_add_string_attribute (CajaFile *file,
8732 const char *attribute_name,
8733 const char *value)
8734{
8735 if (file->details->pending_info_providers) {
8736 /* Lazily create hashtable */
8737 if (!file->details->pending_extension_attributes) {
8738 file->details->pending_extension_attributes =
8739 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8740 NULL((void*)0),
8741 (GDestroyNotify)g_free);
8742 }
8743 g_hash_table_insert (file->details->pending_extension_attributes,
8744 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8745 g_strdup (value)g_strdup_inline (value));
8746 } else {
8747 if (!file->details->extension_attributes) {
8748 file->details->extension_attributes =
8749 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8750 NULL((void*)0),
8751 (GDestroyNotify)g_free);
8752 }
8753 g_hash_table_insert (file->details->extension_attributes,
8754 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8755 g_strdup (value)g_strdup_inline (value));
8756 }
8757
8758 caja_file_changed (file);
8759}
8760
8761static void
8762caja_file_invalidate_extension_info (CajaFile *file)
8763{
8764 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_EXTENSION_INFO);
8765}
8766
8767void
8768caja_file_info_providers_done (CajaFile *file)
8769{
8770 g_list_free_full (file->details->extension_emblems, g_free);
8771 file->details->extension_emblems = file->details->pending_extension_emblems;
8772 file->details->pending_extension_emblems = NULL((void*)0);
8773
8774 if (file->details->extension_attributes) {
8775 g_hash_table_destroy (file->details->extension_attributes);
8776 }
8777
8778 file->details->extension_attributes = file->details->pending_extension_attributes;
8779 file->details->pending_extension_attributes = NULL((void*)0);
8780
8781 caja_file_changed (file);
8782}
8783
8784static void
8785caja_file_info_iface_init (CajaFileInfoIface *iface)
8786{
8787 iface->is_gone = caja_file_is_gone;
8788 iface->get_name = caja_file_get_name;
8789 iface->get_file_type = caja_file_get_file_type;
8790 iface->get_location = caja_file_get_location;
8791 iface->get_uri = caja_file_get_uri;
8792 iface->get_parent_location = caja_file_get_parent_location;
8793 iface->get_parent_uri = caja_file_get_parent_uri;
8794 iface->get_parent_info = caja_file_get_parent;
8795 iface->get_mount = caja_file_get_mount;
8796 iface->get_uri_scheme = caja_file_get_uri_scheme;
8797 iface->get_activation_uri = caja_file_get_activation_uri;
8798 iface->get_mime_type = caja_file_get_mime_type;
8799 iface->is_mime_type = caja_file_is_mime_type;
8800 iface->is_directory = caja_file_is_directory;
8801 iface->can_write = caja_file_can_write;
8802 iface->add_emblem = caja_file_add_emblem;
8803 iface->get_string_attribute = caja_file_get_string_attribute;
8804 iface->add_string_attribute = caja_file_add_string_attribute;
8805 iface->invalidate_extension_info = caja_file_invalidate_extension_info;
8806}
8807
8808#if !defined (CAJA_OMIT_SELF_CHECK)
8809
8810void
8811caja_self_check_file (void)
8812{
8813 CajaFile *file_1;
8814 CajaFile *file_2;
8815 GList *list;
8816
8817 /* refcount checks */
8818
8819 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8819); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8820
8821 file_1 = caja_file_get_by_uri ("file:///home/");
8822
8823 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8823); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8824 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1->details->directory)))))->ref_count"
, "caja-file.c", 8824); eel_check_integer_result (((((GObject
*) (void *) ((file_1->details->directory)))))->ref_count
, 1); } while (0)
;
8825 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 1)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8825); eel_check_integer_result (caja_directory_number_outstanding
(), 1); } while (0)
;
8826
8827 caja_file_unref (file_1);
8828
8829 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8829); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8830
8831 file_1 = caja_file_get_by_uri ("file:///etc");
8832 file_2 = caja_file_get_by_uri ("file:///usr");
8833
8834 list = NULL((void*)0);
8835 list = g_list_prepend (list, file_1);
8836 list = g_list_prepend (list, file_2);
8837
8838 caja_file_list_ref (list);
8839
8840 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8840); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 2); } while (0)
;
8841 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8841); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 2); } while (0)
;
8842
8843 caja_file_list_unref (list);
8844
8845 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8845); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8846 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8846); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8847
8848 caja_file_list_free (list);
8849
8850 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8850); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8851
8852
8853 /* name checks */
8854 file_1 = caja_file_get_by_uri ("file:///home/");
8855
8856 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8856); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8857
8858 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home/") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home/\") == file_1"
, "caja-file.c", 8858); eel_check_boolean_result (caja_file_get_by_uri
("file:///home/") == file_1, (!(0))); } while (0)
;
8859 caja_file_unref (file_1);
8860
8861 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home\") == file_1"
, "caja-file.c", 8861); eel_check_boolean_result (caja_file_get_by_uri
("file:///home") == file_1, (!(0))); } while (0)
;
8862 caja_file_unref (file_1);
8863
8864 caja_file_unref (file_1);
8865
8866 file_1 = caja_file_get_by_uri ("file:///home");
8867 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8867); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8868 caja_file_unref (file_1);
8869
8870#if 0
8871 /* ALEX: I removed this, because it was breaking distchecks.
8872 * It used to work, but when canonical uris changed from
8873 * foo: to foo:/// it broke. I don't expect it to matter
8874 * in real life */
8875 file_1 = caja_file_get_by_uri (":");
8876 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), ":")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8876); eel_check_string_result (caja_file_get_name (file_1)
, ":"); } while (0)
;
8877 caja_file_unref (file_1);
8878#endif
8879
8880 file_1 = caja_file_get_by_uri ("eazel:");
8881 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "eazel")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8881); eel_check_string_result (caja_file_get_name (file_1)
, "eazel"); } while (0)
;
8882 caja_file_unref (file_1);
8883
8884 /* sorting */
8885 file_1 = caja_file_get_by_uri ("file:///etc");
8886 file_2 = caja_file_get_by_uri ("file:///usr");
8887
8888 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8888); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8889 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8889); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8890
8891 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) < 0"
, "caja-file.c", 8891); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) <
0, (!(0))); } while (0)
;
8892 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) > 0"
, "caja-file.c", 8892); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) > 0, (!(0))); } while (0)
;
8893 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) == 0"
, "caja-file.c", 8893); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) ==
0, (!(0))); } while (0)
;
8894 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)) == 0"
, "caja-file.c", 8894); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)
) == 0, (!(0))); } while (0)
;
8895 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) == 0"
, "caja-file.c", 8895); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) == 0, (!(0))); } while (0)
;
8896 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(0))) == 0"
, "caja-file.c", 8896); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(
0))) == 0, (!(0))); } while (0)
;
8897
8898 caja_file_unref (file_1);
8899 caja_file_unref (file_2);
8900}
8901
8902#endif /* !CAJA_OMIT_SELF_CHECK */
diff --git a/2024-07-29-023715-6438-1/report-89fe06.html b/2024-07-29-023715-6438-1/report-89fe06.html new file mode 100644 index 000000000..667226db1 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-89fe06.html @@ -0,0 +1,3283 @@ + + + +caja-mime-actions.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-mime-actions.c
Warning:line 1615, column 9
Value stored to 'show_install_mime' 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 caja-mime-actions.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-mime-actions.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* caja-mime-actions.c - uri-specific versions of mime action functions
4
5 Copyright (C) 2000, 2001 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Maciej Stachowiak <mjs@eazel.com>
23*/
24
25#include <config.h>
26#include <string.h>
27
28#include <glib/gi18n.h>
29#include <glib/gstdio.h>
30#include <gdk/gdkx.h>
31
32#include <eel/eel-glib-extensions.h>
33#include <eel/eel-stock-dialogs.h>
34#include <eel/eel-string.h>
35
36#include "caja-mime-actions.h"
37#include "caja-file-attributes.h"
38#include "caja-file.h"
39#include "caja-autorun.h"
40#include "caja-file-operations.h"
41#include "caja-metadata.h"
42#include "caja-program-choosing.h"
43#include "caja-desktop-icon-file.h"
44#include "caja-global-preferences.h"
45#include "caja-debug-log.h"
46#include "caja-open-with-dialog.h"
47
48typedef enum
49{
50 ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE,
51 ACTIVATION_ACTION_ASK,
52 ACTIVATION_ACTION_LAUNCH,
53 ACTIVATION_ACTION_LAUNCH_IN_TERMINAL,
54 ACTIVATION_ACTION_OPEN_IN_VIEW,
55 ACTIVATION_ACTION_OPEN_IN_APPLICATION,
56 ACTIVATION_ACTION_DO_NOTHING,
57} ActivationAction;
58
59typedef struct
60{
61 CajaFile *file;
62 char *uri;
63} LaunchLocation;
64
65typedef struct
66{
67 GAppInfo *application;
68 GList *uris;
69} ApplicationLaunchParameters;
70
71typedef struct
72{
73 CajaWindowSlotInfo *slot_info;
74 gpointer window_info;
75 GtkWindow *parent_window;
76 GCancellable *cancellable;
77 GList *locations;
78 GList *mountables;
79 GList *start_mountables;
80 GList *not_mounted;
81 CajaWindowOpenMode mode;
82 CajaWindowOpenFlags flags;
83 char *timed_wait_prompt;
84 gboolean timed_wait_active;
85 CajaFileListHandle *files_handle;
86 gboolean tried_mounting;
87 char *activation_directory;
88 gboolean user_confirmation;
89} ActivateParameters;
90
91/* Number of seconds until cancel dialog shows up */
92#define DELAY_UNTIL_CANCEL_MSECS5000 5000
93
94#define RESPONSE_RUN1000 1000
95#define RESPONSE_DISPLAY1001 1001
96#define RESPONSE_RUN_IN_TERMINAL1002 1002
97#define RESPONSE_MARK_TRUSTED1003 1003
98
99#define SILENT_WINDOW_OPEN_LIMIT5 5
100
101/* This number controls a maximum character count for a URL that is
102 * displayed as part of a dialog. It's fairly arbitrary -- big enough
103 * to allow most "normal" URIs to display in full, but small enough to
104 * prevent the dialog from getting insanely wide.
105 */
106#define MAX_URI_IN_DIALOG_LENGTH60 60
107
108static void cancel_activate_callback (gpointer callback_data);
109static void activate_activation_uris_ready_callback (GList *files,
110 gpointer callback_data);
111static void activation_mount_mountables (ActivateParameters *parameters);
112static void activation_start_mountables (ActivateParameters *parameters);
113static void activate_callback (GList *files,
114 gpointer callback_data);
115static void activation_mount_not_mounted (ActivateParameters *parameters);
116
117
118static void
119launch_location_free (LaunchLocation *location)
120{
121 caja_file_unref (location->file);
122 g_free (location->uri);
123 g_free (location);
124}
125
126static void
127launch_location_list_free (GList *list)
128{
129 g_list_foreach (list, (GFunc)launch_location_free, NULL((void*)0));
130 g_list_free (list);
131}
132
133static GList *
134get_file_list_for_launch_locations (GList *locations)
135{
136 GList *files, *l;
137 LaunchLocation *location = NULL((void*)0);
138
139 files = NULL((void*)0);
140 for (l = locations; l != NULL((void*)0); l = l->next)
141 {
142 location = l->data;
143
144 files = g_list_prepend (files,
145 caja_file_ref (location->file));
146 }
147 return g_list_reverse (files);
148}
149
150
151static LaunchLocation *
152launch_location_from_file (CajaFile *file)
153{
154 LaunchLocation *location;
155 location = g_new (LaunchLocation, 1)(LaunchLocation *) (__extension__ ({ gsize __n = (gsize) (1);
gsize __s = sizeof (LaunchLocation); 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; }))
;
156 location->file = caja_file_ref (file);
157 location->uri = caja_file_get_uri (file);
158
159 return location;
160}
161
162static void
163launch_location_update_from_file (LaunchLocation *location,
164 CajaFile *file)
165{
166 caja_file_unref (location->file);
167 g_free (location->uri);
168 location->file = caja_file_ref (file);
169 location->uri = caja_file_get_uri (file);
170}
171
172static void
173launch_location_update_from_uri (LaunchLocation *location,
174 const char *uri)
175{
176 caja_file_unref (location->file);
177 g_free (location->uri);
178 location->file = caja_file_get_by_uri (uri);
179 location->uri = g_strdup (uri)g_strdup_inline (uri);
180}
181
182static LaunchLocation *
183find_launch_location_for_file (GList *list,
184 CajaFile *file)
185{
186 GList *l;
187 LaunchLocation *location = NULL((void*)0);
188
189 for (l = list; l != NULL((void*)0); l = l->next)
190 {
191 location = l->data;
192
193 if (location->file == file)
194 {
195 return location;
196 }
197 }
198 return NULL((void*)0);
199}
200
201static GList *
202launch_locations_from_file_list (GList *list)
203{
204 GList *new;
205
206 new = NULL((void*)0);
207 while (list)
208 {
209 new = g_list_prepend (new,
210 launch_location_from_file (list->data));
211 list = list->next;
212 }
213 new = g_list_reverse (new);
214 return new;
215}
216
217static ApplicationLaunchParameters *
218application_launch_parameters_new (GAppInfo *application,
219 GList *uris)
220{
221 ApplicationLaunchParameters *result;
222
223 result = g_new0 (ApplicationLaunchParameters, 1)(ApplicationLaunchParameters *) (__extension__ ({ gsize __n =
(gsize) (1); gsize __s = sizeof (ApplicationLaunchParameters
); 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; }))
;
224 result->application = g_object_ref (application)((__typeof__ (application)) (g_object_ref) (application));
225 result->uris = g_list_copy_deep (uris, (GCopyFunc) g_strdup, NULL((void*)0));
226
227 return result;
228}
229
230static void
231application_launch_parameters_free (ApplicationLaunchParameters *parameters)
232{
233 g_object_unref (parameters->application);
234 g_list_free_full (parameters->uris, g_free);
235
236 g_free (parameters);
237}
238
239static GList*
240filter_caja_handler (GList *apps)
241{
242 GList *l, *next;
243 GAppInfo *application = NULL((void*)0);
244
245 l = apps;
246 while (l != NULL((void*)0))
247 {
248 const char *id;
249
250 application = (GAppInfo *) l->data;
251 next = l->next;
252
253 id = g_app_info_get_id (application);
254 if (id != NULL((void*)0) &&
255 strcmp (id,
256 "caja-folder-handler.desktop") == 0)
257 {
258 g_object_unref (application);
259 apps = g_list_delete_link (apps, l);
260 }
261
262 l = next;
263 }
264
265 return apps;
266}
267
268static GList*
269filter_non_uri_apps (GList *apps)
270{
271 GList *l, *next;
272 GAppInfo *app = NULL((void*)0);
273
274 for (l = apps; l != NULL((void*)0); l = next)
275 {
276 app = l->data;
277 next = l->next;
278
279 if (!g_app_info_supports_uris (app))
280 {
281 apps = g_list_delete_link (apps, l);
282 g_object_unref (app);
283 }
284 }
285 return apps;
286}
287
288
289static gboolean
290caja_mime_actions_check_if_required_attributes_ready (CajaFile *file)
291{
292 CajaFileAttributes attributes;
293 gboolean ready;
294
295 attributes = caja_mime_actions_get_required_file_attributes ();
296 ready = caja_file_check_if_ready (file, attributes);
297
298 return ready;
299}
300
301CajaFileAttributes
302caja_mime_actions_get_required_file_attributes (void)
303{
304 return CAJA_FILE_ATTRIBUTE_INFO |
305 CAJA_FILE_ATTRIBUTE_LINK_INFO;
306}
307
308static gboolean
309file_has_local_path (CajaFile *file)
310{
311 GFile *location;
312 char *path;
313 gboolean res;
314
315
316 /* Don't only check _is_native, because we want to support
317 using the fuse path */
318 location = caja_file_get_location (file);
319 if (g_file_is_native (location))
320 {
321 res = TRUE(!(0));
322 }
323 else
324 {
325 path = g_file_get_path (location);
326
327 res = path != NULL((void*)0);
328
329 g_free (path);
330 }
331 g_object_unref (location);
332
333 return res;
334}
335
336GAppInfo *
337caja_mime_get_default_application_for_file (CajaFile *file)
338{
339 GAppInfo *app;
340 char *mime_type;
341
342 if (!caja_mime_actions_check_if_required_attributes_ready (file))
343 {
344 return NULL((void*)0);
345 }
346
347 mime_type = caja_file_get_mime_type (file);
348 app = g_app_info_get_default_for_type (mime_type, !file_has_local_path (file));
349 g_free (mime_type);
350
351 if (app == NULL((void*)0))
352 {
353 char *uri_scheme;
354
355 uri_scheme = caja_file_get_uri_scheme (file);
356 if (uri_scheme != NULL((void*)0))
357 {
358 app = g_app_info_get_default_for_uri_scheme (uri_scheme);
359 g_free (uri_scheme);
360 }
361 }
362
363 return app;
364}
365
366static int
367file_compare_by_mime_type (CajaFile *file_a,
368 CajaFile *file_b)
369{
370 char *mime_type_a, *mime_type_b;
371 int ret;
372
373 mime_type_a = caja_file_get_mime_type (file_a);
374 mime_type_b = caja_file_get_mime_type (file_b);
375
376 ret = strcmp (mime_type_a, mime_type_b);
377
378 g_free (mime_type_a);
379 g_free (mime_type_b);
380
381 return ret;
382}
383
384static int
385file_compare_by_parent_uri (CajaFile *file_a,
386 CajaFile *file_b)
387{
388 char *parent_uri_a, *parent_uri_b;
389 int ret;
390
391 parent_uri_a = caja_file_get_parent_uri (file_a);
392 parent_uri_b = caja_file_get_parent_uri (file_b);
393
394 ret = strcmp (parent_uri_a, parent_uri_b);
395
396 g_free (parent_uri_a);
397 g_free (parent_uri_b);
398
399 return ret;
400}
401
402static int
403application_compare_by_name (const GAppInfo *app_a,
404 const GAppInfo *app_b)
405{
406 return g_utf8_collate (g_app_info_get_display_name ((GAppInfo *)app_a),
407 g_app_info_get_display_name ((GAppInfo *)app_b));
408}
409
410static int
411application_compare_by_id (const GAppInfo *app_a,
412 const GAppInfo *app_b)
413{
414 const char *id_a, *id_b;
415
416 id_a = g_app_info_get_id ((GAppInfo *)app_a);
417 id_b = g_app_info_get_id ((GAppInfo *)app_b);
418
419 if (id_a == NULL((void*)0) && id_b == NULL((void*)0))
420 {
421 if (g_app_info_equal ((GAppInfo *)app_a, (GAppInfo *)app_b))
422 {
423 return 0;
424 }
425 if ((gsize)app_a < (gsize) app_b)
426 {
427 return -1;
428 }
429 return 1;
430 }
431
432 if (id_a == NULL((void*)0))
433 {
434 return -1;
435 }
436
437 if (id_b == NULL((void*)0))
438 {
439 return 1;
440 }
441
442
443 return strcmp (id_a, id_b);
444}
445
446GList *
447caja_mime_get_applications_for_file (CajaFile *file)
448{
449 char *mime_type;
450 char *uri_scheme;
451 GList *result;
452
453 if (!caja_mime_actions_check_if_required_attributes_ready (file))
454 {
455 return NULL((void*)0);
456 }
457 mime_type = caja_file_get_mime_type (file);
458 result = g_app_info_get_all_for_type (mime_type);
459
460 uri_scheme = caja_file_get_uri_scheme (file);
461 if (uri_scheme != NULL((void*)0))
462 {
463 GAppInfo *uri_handler;
464
465 uri_handler = g_app_info_get_default_for_uri_scheme (uri_scheme);
466 if (uri_handler)
467 {
468 result = g_list_prepend (result, uri_handler);
469 }
470 g_free (uri_scheme);
471 }
472
473 if (!file_has_local_path (file))
474 {
475 /* Filter out non-uri supporting apps */
476 result = filter_non_uri_apps (result);
477 }
478
479 result = g_list_sort (result, (GCompareFunc) application_compare_by_name);
480 g_free (mime_type);
481
482 return filter_caja_handler (result);
483}
484
485gboolean
486caja_mime_has_any_applications_for_file (CajaFile *file)
487{
488 GList *apps;
489 char *mime_type;
490 gboolean result;
491 char *uri_scheme;
492
493 mime_type = caja_file_get_mime_type (file);
494
495 apps = g_app_info_get_all_for_type (mime_type);
496
497 uri_scheme = caja_file_get_uri_scheme (file);
498 if (uri_scheme != NULL((void*)0))
499 {
500 GAppInfo *uri_handler;
501
502 uri_handler = g_app_info_get_default_for_uri_scheme (uri_scheme);
503 if (uri_handler)
504 {
505 apps = g_list_prepend (apps, uri_handler);
506 }
507 g_free (uri_scheme);
508 }
509
510 if (!file_has_local_path (file))
511 {
512 /* Filter out non-uri supporting apps */
513 apps = filter_non_uri_apps (apps);
514 }
515 apps = filter_caja_handler (apps);
516
517 if (apps)
518 {
519 result = TRUE(!(0));
520 g_list_free_full (apps, g_object_unref);
521 }
522 else
523 {
524 result = FALSE(0);
525 }
526
527 g_free (mime_type);
528
529 return result;
530}
531
532GAppInfo *
533caja_mime_get_default_application_for_files (GList *files)
534{
535 GList *l, *sorted_files;
536 GAppInfo *app, *one_app;
537 CajaFile *file = NULL((void*)0);
538
539 g_assert (files != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (files != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-mime-actions.c", 539, ((const char*) (__func__
)), "files != NULL"); } while (0)
;
540
541 sorted_files = g_list_sort (g_list_copy (files), (GCompareFunc) file_compare_by_mime_type);
542
543 app = NULL((void*)0);
544 for (l = sorted_files; l != NULL((void*)0); l = l->next)
545 {
546 file = l->data;
547
548 if (l->prev &&
549 file_compare_by_mime_type (file, l->prev->data) == 0 &&
550 file_compare_by_parent_uri (file, l->prev->data) == 0)
551 {
552 continue;
553 }
554
555 one_app = caja_mime_get_default_application_for_file (file);
556 if (one_app == NULL((void*)0) || (app != NULL((void*)0) && !g_app_info_equal (app, one_app)))
557 {
558 if (app)
559 {
560 g_object_unref (app);
561 }
562 if (one_app)
563 {
564 g_object_unref (one_app);
565 }
566 app = NULL((void*)0);
567 break;
568 }
569
570 if (app == NULL((void*)0))
571 {
572 app = one_app;
573 }
574 else
575 {
576 g_object_unref (one_app);
577 }
578 }
579
580 g_list_free (sorted_files);
581
582 return app;
583}
584
585/* returns an intersection of two mime application lists,
586 * and returns a new list, freeing a, b and all applications
587 * that are not in the intersection set.
588 * The lists are assumed to be pre-sorted by their IDs */
589static GList *
590intersect_application_lists (GList *a,
591 GList *b)
592{
593 GList *l, *m;
594 GList *ret;
595 GAppInfo *a_app = NULL((void*)0);
596 GAppInfo *b_app = NULL((void*)0);
597
598 ret = NULL((void*)0);
599
600 l = a;
601 m = b;
602
603 while (l != NULL((void*)0) && m != NULL((void*)0))
604 {
605 int cmp;
606
607 a_app = (GAppInfo *) l->data;
608 b_app = (GAppInfo *) m->data;
609
610 cmp = application_compare_by_id (a_app, b_app);
611 if (cmp > 0)
612 {
613 g_object_unref (b_app);
614 m = m->next;
615 }
616 else if (cmp < 0)
617 {
618 g_object_unref (a_app);
619 l = l->next;
620 }
621 else
622 {
623 g_object_unref (b_app);
624 ret = g_list_prepend (ret, a_app);
625 l = l->next;
626 m = m->next;
627 }
628 }
629
630 g_list_foreach (l, (GFunc) g_object_unref, NULL((void*)0));
631 g_list_foreach (m, (GFunc) g_object_unref, NULL((void*)0));
632
633 g_list_free (a);
634 g_list_free (b);
635
636 return g_list_reverse (ret);
637}
638
639GList *
640caja_mime_get_applications_for_files (GList *files)
641{
642 GList *l, *sorted_files;
643 GList *one_ret, *ret;
644 CajaFile *file = NULL((void*)0);
645
646 g_assert (files != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (files != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-mime-actions.c", 646, ((const char*) (__func__
)), "files != NULL"); } while (0)
;
647
648 sorted_files = g_list_sort (g_list_copy (files), (GCompareFunc) file_compare_by_mime_type);
649
650 ret = NULL((void*)0);
651 for (l = sorted_files; l != NULL((void*)0); l = l->next)
652 {
653 file = l->data;
654
655 if (l->prev &&
656 file_compare_by_mime_type (file, l->prev->data) == 0 &&
657 file_compare_by_parent_uri (file, l->prev->data) == 0)
658 {
659 continue;
660 }
661
662 one_ret = caja_mime_get_applications_for_file (file);
663 one_ret = g_list_sort (one_ret, (GCompareFunc) application_compare_by_id);
664 if (ret != NULL((void*)0))
665 {
666 ret = intersect_application_lists (ret, one_ret);
667 }
668 else
669 {
670 ret = one_ret;
671 }
672
673 if (ret == NULL((void*)0))
674 {
675 break;
676 }
677 }
678
679 g_list_free (sorted_files);
680
681 ret = g_list_sort (ret, (GCompareFunc) application_compare_by_name);
682
683 return ret;
684}
685
686static void
687trash_or_delete_files (GtkWindow *parent_window,
688 const GList *files,
689 gboolean delete_if_all_already_in_trash)
690{
691 GList *locations;
692 const GList *node;
693
694 locations = NULL((void*)0);
695 for (node = files; node != NULL((void*)0); node = node->next)
696 {
697 locations = g_list_prepend (locations,
698 caja_file_get_location ((CajaFile *) node->data));
699 }
700
701 locations = g_list_reverse (locations);
702
703 caja_file_operations_trash_or_delete (locations,
704 parent_window,
705 NULL((void*)0), NULL((void*)0));
706 g_list_free_full (locations, g_object_unref);
707}
708
709static void
710report_broken_symbolic_link (GtkWindow *parent_window, CajaFile *file)
711{
712 char *target_path;
713 char *display_name;
714 char *prompt;
715 char *detail;
716 GtkDialog *dialog;
717 GList file_as_list;
718 int response;
719
720 g_assert (caja_file_is_broken_symbolic_link (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (caja_file_is_broken_symbolic_link (file)) _g_boolean_var_20
= 1; else _g_boolean_var_20 = 0; _g_boolean_var_20; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-mime-actions.c"
, 720, ((const char*) (__func__)), "caja_file_is_broken_symbolic_link (file)"
); } while (0)
;
721
722 display_name = caja_file_get_display_name (file);
723 if (caja_file_is_in_trash (file))
724 {
725 prompt = g_strdup_printf (_("The Link \"%s\" is Broken.")dcgettext (((void*)0), "The Link \"%s\" is Broken.", 5), display_name);
726 }
727 else
728 {
729 prompt = g_strdup_printf (_("The Link \"%s\" is Broken. Move it to Trash?")dcgettext (((void*)0), "The Link \"%s\" is Broken. Move it to Trash?"
, 5)
, display_name);
730 }
731 g_free (display_name);
732
733 target_path = caja_file_get_symbolic_link_target_path (file);
734 if (target_path == NULL((void*)0))
735 {
736 detail = g_strdup (_("This link cannot be used, because it has no target."))g_strdup_inline (dcgettext (((void*)0), "This link cannot be used, because it has no target."
, 5))
;
737 }
738 else
739 {
740 detail = g_strdup_printf (_("This link cannot be used, because its target "dcgettext (((void*)0), "This link cannot be used, because its target "
"\"%s\" doesn't exist.", 5)
741 "\"%s\" doesn't exist.")dcgettext (((void*)0), "This link cannot be used, because its target "
"\"%s\" doesn't exist.", 5)
, target_path);
742 }
743
744 if (caja_file_is_in_trash (file))
745 {
746 eel_run_simple_dialog (GTK_WIDGET (parent_window)((((GtkWidget*) (void *) ((parent_window))))), FALSE(0), GTK_MESSAGE_WARNING,
747 prompt, detail, "process-stop", NULL((void*)0));
748 goto out;
749 }
750
751 dialog = eel_show_yes_no_dialog (prompt, detail, _("Mo_ve to Trash")dcgettext (((void*)0), "Mo_ve to Trash", 5), "process-stop",
752 parent_window);
753
754 gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL);
755
756 /* Make this modal to avoid problems with reffing the view & file
757 * to keep them around in case the view changes, which would then
758 * cause the old view not to be destroyed, which would cause its
759 * merged MateComponent items not to be un-merged. Maybe we need to unmerge
760 * explicitly when disconnecting views instead of relying on the
761 * unmerge in Destroy. But since MateComponentUIHandler is probably going
762 * to change wildly, I don't want to mess with this now.
763 */
764
765 response = gtk_dialog_run (dialog);
766 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
767
768 if (response == GTK_RESPONSE_YES)
769 {
770 file_as_list.data = file;
771 file_as_list.next = NULL((void*)0);
772 file_as_list.prev = NULL((void*)0);
773 trash_or_delete_files (parent_window, &file_as_list, TRUE(!(0)));
774 }
775
776out:
777 g_free (prompt);
778 g_free (target_path);
779 g_free (detail);
780}
781
782static ActivationAction
783get_executable_text_file_action (GtkWindow *parent_window, CajaFile *file)
784{
785 GtkDialog *dialog;
786 char *file_name;
787 char *prompt;
788 char *detail;
789 int preferences_value;
790 int response;
791
792 g_assert (caja_file_contains_text (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (caja_file_contains_text (file)) _g_boolean_var_21 = 1; else
_g_boolean_var_21 = 0; _g_boolean_var_21; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-mime-actions.c", 792, ((const char*) (__func__
)), "caja_file_contains_text (file)"); } while (0)
;
793
794 preferences_value = g_settings_get_enum (caja_preferences,
795 CAJA_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION"executable-text-activation");
796 switch (preferences_value)
797 {
798 case CAJA_EXECUTABLE_TEXT_LAUNCH:
799 return ACTIVATION_ACTION_LAUNCH;
800 case CAJA_EXECUTABLE_TEXT_DISPLAY:
801 return ACTIVATION_ACTION_OPEN_IN_APPLICATION;
802 case CAJA_EXECUTABLE_TEXT_ASK:
803 break;
804 default:
805 /* Complain non-fatally, since preference data can't be trusted */
806 g_warning ("Unknown value %d for CAJA_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION",
807 preferences_value);
808
809 }
810
811
812 file_name = caja_file_get_display_name (file);
813 prompt = g_strdup_printf (_("Do you want to run \"%s\", or display its contents?")dcgettext (((void*)0), "Do you want to run \"%s\", or display its contents?"
, 5)
,
814 file_name);
815 detail = g_strdup_printf (_("\"%s\" is an executable text file.")dcgettext (((void*)0), "\"%s\" is an executable text file.", 5
)
,
816 file_name);
817 g_free (file_name);
818
819 dialog = eel_create_question_dialog (prompt,
820 detail,
821 _("Run in _Terminal")dcgettext (((void*)0), "Run in _Terminal", 5), RESPONSE_RUN_IN_TERMINAL1002,
822 _("_Display")dcgettext (((void*)0), "_Display", 5), RESPONSE_DISPLAY1001,
823 parent_window);
824
825 eel_dialog_add_button (dialog,
826 _("_Cancel")dcgettext (((void*)0), "_Cancel", 5),
827 "process-stop",
828 GTK_RESPONSE_CANCEL);
829
830 gtk_dialog_add_button (dialog, _("_Run")dcgettext (((void*)0), "_Run", 5), RESPONSE_RUN1000);
831 gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CANCEL);
832 gtk_widget_show (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
833
834 g_free (prompt);
835 g_free (detail);
836
837 response = gtk_dialog_run (dialog);
838 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
839
840 switch (response)
841 {
842 case RESPONSE_RUN1000:
843 return ACTIVATION_ACTION_LAUNCH;
844 case RESPONSE_RUN_IN_TERMINAL1002:
845 return ACTIVATION_ACTION_LAUNCH_IN_TERMINAL;
846 case RESPONSE_DISPLAY1001:
847 return ACTIVATION_ACTION_OPEN_IN_APPLICATION;
848 default:
849 return ACTIVATION_ACTION_DO_NOTHING;
850 }
851}
852
853static ActivationAction
854get_default_executable_text_file_action (void)
855{
856 int preferences_value;
857
858 preferences_value = g_settings_get_enum (caja_preferences,
859 CAJA_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION"executable-text-activation");
860 switch (preferences_value)
861 {
862 case CAJA_EXECUTABLE_TEXT_LAUNCH:
863 return ACTIVATION_ACTION_LAUNCH;
864 case CAJA_EXECUTABLE_TEXT_DISPLAY:
865 return ACTIVATION_ACTION_OPEN_IN_APPLICATION;
866 case CAJA_EXECUTABLE_TEXT_ASK:
867 default:
868 return ACTIVATION_ACTION_ASK;
869 }
870}
871
872gboolean
873caja_mime_file_opens_in_view (CajaFile *file)
874{
875 return (caja_file_is_directory (file));
876}
877
878static ActivationAction
879get_activation_action (CajaFile *file)
880{
881 ActivationAction action;
882 char *activation_uri;
883
884 if (caja_file_is_caja_link (file))
885 {
886 return ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE;
887 }
888
889 activation_uri = caja_file_get_activation_uri (file);
890 if (activation_uri == NULL((void*)0))
891 {
892 activation_uri = caja_file_get_uri (file);
893 }
894
895 action = ACTIVATION_ACTION_DO_NOTHING;
896 if (caja_file_is_launchable (file))
897 {
898 char *executable_path;
899
900 action = ACTIVATION_ACTION_LAUNCH;
901
902 executable_path = g_filename_from_uri (activation_uri, NULL((void*)0), NULL((void*)0));
903 if (!executable_path)
904 {
905 action = ACTIVATION_ACTION_DO_NOTHING;
906 }
907 else if (caja_file_contains_text (file))
908 {
909 action = get_default_executable_text_file_action ();
910 }
911 g_free (executable_path);
912 }
913
914 if (action == ACTIVATION_ACTION_DO_NOTHING)
915 {
916 if (caja_mime_file_opens_in_view (file))
917 {
918 action = ACTIVATION_ACTION_OPEN_IN_VIEW;
919 }
920 else
921 {
922 action = ACTIVATION_ACTION_OPEN_IN_APPLICATION;
923 }
924 }
925 g_free (activation_uri);
926
927 return action;
928}
929
930gboolean
931caja_mime_file_opens_in_external_app (CajaFile *file)
932{
933 ActivationAction activation_action;
934
935 activation_action = get_activation_action (file);
936
937 return (activation_action == ACTIVATION_ACTION_OPEN_IN_APPLICATION);
938}
939
940
941static unsigned int
942mime_application_hash (GAppInfo *app)
943{
944 const char *id;
945
946 id = g_app_info_get_id (app);
947
948 if (id == NULL((void*)0))
949 {
950 return GPOINTER_TO_UINT(app)((guint) (gulong) (app));
951 }
952
953 return g_str_hash (id);
954}
955
956static void
957list_to_parameters_foreach (GAppInfo *application,
958 GList *uris,
959 GList **ret)
960{
961 ApplicationLaunchParameters *parameters;
962
963 uris = g_list_reverse (uris);
964
965 parameters = application_launch_parameters_new
966 (application, uris);
967 *ret = g_list_prepend (*ret, parameters);
968}
969
970
971/**
972 * make_activation_parameters
973 *
974 * Construct a list of ApplicationLaunchParameters from a list of CajaFiles,
975 * where files that have the same default application are put into the same
976 * launch parameter, and others are put into the unhandled_files list.
977 *
978 * @files: Files to use for construction.
979 * @unhandled_files: Files without any default application will be put here.
980 *
981 * Return value: Newly allocated list of ApplicationLaunchParameters.
982 **/
983static GList *
984make_activation_parameters (GList *uris,
985 GList **unhandled_uris)
986{
987 GList *ret, *l, *app_uris;
988 GHashTable *app_table;
989 GAppInfo *old_app;
990 GAppInfo *app = NULL((void*)0);
991 CajaFile *file = NULL((void*)0);
992
993 ret = NULL((void*)0);
994 *unhandled_uris = NULL((void*)0);
995
996 app_table = g_hash_table_new_full
997 ((GHashFunc) mime_application_hash,
998 (GEqualFunc) g_app_info_equal,
999 (GDestroyNotify) g_object_unref,
1000 (GDestroyNotify) g_list_free);
1001
1002 for (l = uris; l != NULL((void*)0); l = l->next)
1003 {
1004 char *uri;
1005
1006 uri = l->data;
1007 file = caja_file_get_by_uri (uri);
1008
1009 /* Double-check if a file's MIME type has changed before we commit to a
1010 choice of application for it. This can happen if, for instance, file
1011 was originally created with 0 bytes and then content was added to it
1012 later-- it will change from plaintext to something else. */
1013 caja_file_refresh_info (file);
1014
1015 app = caja_mime_get_default_application_for_file (file);
1016 if (app != NULL((void*)0))
1017 {
1018 app_uris = NULL((void*)0);
1019
1020 if (g_hash_table_lookup_extended (app_table, app,
1021 (gpointer *) &old_app,
1022 (gpointer *) &app_uris))
1023 {
1024 g_hash_table_steal (app_table, old_app);
1025
1026 app_uris = g_list_prepend (app_uris, uri);
1027
1028 g_object_unref (app);
1029 app = old_app;
1030 }
1031 else
1032 {
1033 app_uris = g_list_prepend (NULL((void*)0), uri);
1034 }
1035
1036 g_hash_table_insert (app_table, app, app_uris);
1037 }
1038 else
1039 {
1040 *unhandled_uris = g_list_prepend (*unhandled_uris, uri);
1041 }
1042 caja_file_unref (file);
1043 }
1044
1045 g_hash_table_foreach (app_table,
1046 (GHFunc) list_to_parameters_foreach,
1047 &ret);
1048
1049 g_hash_table_destroy (app_table);
1050
1051 *unhandled_uris = g_list_reverse (*unhandled_uris);
1052
1053 return g_list_reverse (ret);
1054}
1055
1056static gboolean
1057file_was_cancelled (CajaFile *file)
1058{
1059 GError *error;
1060
1061 error = caja_file_get_file_info_error (file);
1062 return
1063 error != NULL((void*)0) &&
1064 error->domain == G_IO_ERRORg_io_error_quark() &&
1065 error->code == G_IO_ERROR_CANCELLED;
1066}
1067
1068static gboolean
1069file_was_not_mounted (CajaFile *file)
1070{
1071 GError *error;
1072
1073 error = caja_file_get_file_info_error (file);
1074 return
1075 error != NULL((void*)0) &&
1076 error->domain == G_IO_ERRORg_io_error_quark() &&
1077 error->code == G_IO_ERROR_NOT_MOUNTED;
1078}
1079
1080static void
1081activation_parameters_free (ActivateParameters *parameters)
1082{
1083 if (parameters->timed_wait_active)
1084 {
1085 eel_timed_wait_stop (cancel_activate_callback, parameters);
1086 }
1087
1088 if (parameters->slot_info)
1089 {
1090 g_object_remove_weak_pointer (G_OBJECT (parameters->slot_info)((((GObject*) (void *) ((parameters->slot_info))))), (gpointer *)&parameters->slot_info);
1091 }
1092 if (parameters->parent_window)
1093 {
1094 g_object_remove_weak_pointer (G_OBJECT (parameters->parent_window)((((GObject*) (void *) ((parameters->parent_window))))), (gpointer *)&parameters->parent_window);
1095 }
1096 g_object_unref (parameters->cancellable);
1097 launch_location_list_free (parameters->locations);
1098 caja_file_list_free (parameters->mountables);
1099 caja_file_list_free (parameters->start_mountables);
1100 caja_file_list_free (parameters->not_mounted);
1101 g_free (parameters->activation_directory);
1102 g_free (parameters->timed_wait_prompt);
1103 g_assert (parameters->files_handle == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (parameters->files_handle == ((void*)0)) _g_boolean_var_22
= 1; else _g_boolean_var_22 = 0; _g_boolean_var_22; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-mime-actions.c"
, 1103, ((const char*) (__func__)), "parameters->files_handle == NULL"
); } while (0)
;
1104 g_free (parameters);
1105}
1106
1107static void
1108cancel_activate_callback (gpointer callback_data)
1109{
1110 ActivateParameters *parameters = callback_data;
1111
1112 parameters->timed_wait_active = FALSE(0);
1113
1114 g_cancellable_cancel (parameters->cancellable);
1115
1116 if (parameters->files_handle)
1117 {
1118 caja_file_list_cancel_call_when_ready (parameters->files_handle);
1119 parameters->files_handle = NULL((void*)0);
1120 activation_parameters_free (parameters);
1121 }
1122}
1123
1124static void
1125activation_start_timed_cancel (ActivateParameters *parameters)
1126{
1127 parameters->timed_wait_active = TRUE(!(0));
1128 eel_timed_wait_start_with_duration
1129 (DELAY_UNTIL_CANCEL_MSECS5000,
1130 cancel_activate_callback,
1131 parameters,
1132 parameters->timed_wait_prompt,
1133 parameters->parent_window);
1134}
1135
1136static void
1137pause_activation_timed_cancel (ActivateParameters *parameters)
1138{
1139 if (parameters->timed_wait_active)
1140 {
1141 eel_timed_wait_stop (cancel_activate_callback, parameters);
1142 parameters->timed_wait_active = FALSE(0);
1143 }
1144}
1145
1146static void
1147unpause_activation_timed_cancel (ActivateParameters *parameters)
1148{
1149 if (!parameters->timed_wait_active)
1150 {
1151 activation_start_timed_cancel (parameters);
1152 }
1153}
1154
1155
1156static void
1157activate_mount_op_active (GtkMountOperation *operation,
1158 GParamSpec *pspec,
1159 ActivateParameters *parameters)
1160{
1161 gboolean is_active;
1162
1163 g_object_get (operation, "is-showing", &is_active, NULL((void*)0));
1164
1165 if (is_active)
1166 {
1167 pause_activation_timed_cancel (parameters);
1168 }
1169 else
1170 {
1171 unpause_activation_timed_cancel (parameters);
1172 }
1173}
1174
1175static gboolean
1176confirm_multiple_windows (GtkWindow *parent_window,
1177 int count,
1178 gboolean use_tabs)
1179{
1180 GtkDialog *dialog;
1181 char *prompt;
1182 char *detail;
1183 int response;
1184
1185 if (count <= SILENT_WINDOW_OPEN_LIMIT5)
1186 {
1187 return TRUE(!(0));
1188 }
1189
1190 prompt = _("Are you sure you want to open all files?")dcgettext (((void*)0), "Are you sure you want to open all files?"
, 5)
;
1191 if (use_tabs)
1192 {
1193 detail = g_strdup_printf (ngettext("This will open %d separate tab.",dcngettext (((void*)0), "This will open %d separate tab.", "This will open %d separate tabs."
, count, 5)
1194 "This will open %d separate tabs.", count)dcngettext (((void*)0), "This will open %d separate tab.", "This will open %d separate tabs."
, count, 5)
, count);
1195 }
1196 else
1197 {
1198 detail = g_strdup_printf (ngettext("This will open %d separate window.",dcngettext (((void*)0), "This will open %d separate window.",
"This will open %d separate windows.", count, 5)
1199 "This will open %d separate windows.", count)dcngettext (((void*)0), "This will open %d separate window.",
"This will open %d separate windows.", count, 5)
, count);
1200 }
1201 dialog = eel_show_yes_no_dialog (prompt, detail,
1202 "gtk-ok", "process-stop",
1203 parent_window);
1204 g_free (detail);
1205
1206 response = gtk_dialog_run (dialog);
1207 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1208
1209 return response == GTK_RESPONSE_YES;
1210}
1211
1212typedef struct
1213{
1214 CajaWindowSlotInfo *slot_info;
1215 GtkWindow *parent_window;
1216 CajaFile *file;
1217 GList *files;
1218 CajaWindowOpenMode mode;
1219 CajaWindowOpenFlags flags;
1220 char *activation_directory;
1221 gboolean user_confirmation;
1222 char *uri;
1223 GDBusProxy *proxy;
1224 GtkWidget *dialog;
1225} ActivateParametersInstall;
1226
1227static void
1228activate_parameters_install_free (ActivateParametersInstall *parameters_install)
1229{
1230 if (parameters_install->slot_info)
1231 {
1232 g_object_remove_weak_pointer (G_OBJECT (parameters_install->slot_info)((((GObject*) (void *) ((parameters_install->slot_info))))
)
, (gpointer *)&parameters_install->slot_info);
1233 }
1234 if (parameters_install->parent_window)
1235 {
1236 g_object_remove_weak_pointer (G_OBJECT (parameters_install->parent_window)((((GObject*) (void *) ((parameters_install->parent_window
)))))
, (gpointer *)&parameters_install->parent_window);
1237 }
1238
1239 if (parameters_install->proxy != NULL((void*)0))
1240 {
1241 g_object_unref (parameters_install->proxy);
1242 }
1243
1244 caja_file_unref (parameters_install->file);
1245 caja_file_list_free (parameters_install->files);
1246 g_free (parameters_install->activation_directory);
1247 g_free (parameters_install->uri);
1248 g_free (parameters_install);
1249}
1250
1251static char *
1252get_application_no_mime_type_handler_message (CajaFile *file, char *uri)
1253{
1254 char *uri_for_display;
1255 char *nice_uri;
1256 char *error_message;
1257
1258 /* For local files, we want to use filename if possible */
1259 if (caja_file_is_local (file))
1260 {
1261 GFile *location;
1262
1263 location = caja_file_get_location (file);
1264 nice_uri = g_file_get_parse_name (location);
1265 g_object_unref (location);
1266 }
1267 else
1268 {
1269 nice_uri = g_strdup (uri)g_strdup_inline (uri);
1270 }
1271
1272 /* Truncate the URI so it doesn't get insanely wide. Note that even
1273 * though the dialog uses wrapped text, if the URI doesn't contain
1274 * white space then the text-wrapping code is too stupid to wrap it.
1275 */
1276 uri_for_display = eel_str_middle_truncate (nice_uri, MAX_URI_IN_DIALOG_LENGTH60);
1277 error_message = g_strdup_printf (_("Could not display \"%s\".")dcgettext (((void*)0), "Could not display \"%s\".", 5), uri_for_display);
1278 g_free (nice_uri);
1279 g_free (uri_for_display);
1280 return error_message;
1281}
1282
1283static void
1284application_selected_cb (CajaOpenWithDialog *dialog,
1285 GAppInfo *app,
1286 gpointer user_data)
1287{
1288 GtkWindow *parent_window;
1289 CajaFile *file;
1290 GList files;
1291
1292 parent_window = GTK_WINDOW (user_data)((((GtkWindow*) (void *) ((user_data)))));
1293
1294 file = g_object_get_data (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))), "mime-action:file");
1295
1296 files.next = NULL((void*)0);
1297 files.prev = NULL((void*)0);
1298 files.data = file;
1299 caja_launch_application (app, &files, parent_window);
1300}
1301
1302static void
1303choose_program (GtkDialog *message_dialog, int response, gpointer callback_data)
1304{
1305 GtkWidget *dialog;
1306 char *uri;
1307 char *mime_type;
1308 CajaFile *file;
1309
1310 if (response != GTK_RESPONSE_ACCEPT)
1311 {
1312 gtk_widget_destroy (GTK_WIDGET (message_dialog)((((GtkWidget*) (void *) ((message_dialog))))));
1313 return;
1314 }
1315
1316 file = g_object_get_data (G_OBJECT (message_dialog)((((GObject*) (void *) ((message_dialog))))), "mime-action:file");
1317
1318 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_23
= 1; else _g_boolean_var_23 = 0; _g_boolean_var_23; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-mime-actions.c"
, 1318, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1319
1320 caja_file_ref (file);
1321 uri = caja_file_get_uri (file);
1322 mime_type = caja_file_get_mime_type (file);
1323
1324 dialog = caja_open_with_dialog_new (uri, mime_type, NULL((void*)0));
1325 g_object_set_data_full (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))),
1326 "mime-action:file",
1327 caja_file_ref (file),
1328 (GDestroyNotify)caja_file_unref);
1329
1330 gtk_window_set_screen (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))),
1331 gtk_widget_get_screen (GTK_WIDGET (callback_data)((((GtkWidget*) (void *) ((callback_data)))))));
1332
1333 /* Destroy the message dialog after ref:ing the file */
1334 gtk_widget_destroy (GTK_WIDGET (message_dialog)((((GtkWidget*) (void *) ((message_dialog))))));
1335
1336 gtk_widget_show (dialog);
1337
1338 g_signal_connect_object (dialog,
1339 "application_selected",
1340 G_CALLBACK (application_selected_cb)((GCallback) (application_selected_cb)),
1341 callback_data,
1342 0);
1343
1344 g_free (uri);
1345 g_free (mime_type);
1346 caja_file_unref (file);
1347}
1348
1349static void
1350show_unhandled_type_error (ActivateParametersInstall *parameters)
1351{
1352 GtkWidget *dialog;
1353
1354 char *mime_type = caja_file_get_mime_type (parameters->file);
1355 char *error_message = get_application_no_mime_type_handler_message (parameters->file, parameters->uri);
1356 if (g_content_type_is_unknown (mime_type)) {
1357 dialog = gtk_message_dialog_new (parameters->parent_window,
1358 GTK_DIALOG_DESTROY_WITH_PARENT,
1359 GTK_MESSAGE_ERROR,
1360 0,
1361 NULL((void*)0));
1362 g_object_set (dialog,
1363 "text", error_message,
1364 "secondary-text", _("The file is of an unknown type")dcgettext (((void*)0), "The file is of an unknown type", 5),
1365 NULL((void*)0));
1366 } else {
1367 char *text;
1368 char *description;
1369
1370 description = g_content_type_get_description (mime_type);
1371 text = g_strdup_printf (_("There is no application installed for %s files")dcgettext (((void*)0), "There is no application installed for %s files"
, 5)
, description);
1372 g_free (description);
1373
1374 dialog = gtk_message_dialog_new (parameters->parent_window,
1375 GTK_DIALOG_DESTROY_WITH_PARENT,
1376 GTK_MESSAGE_ERROR,
1377 0,
1378 NULL((void*)0));
1379 g_object_set (dialog,
1380 "text", error_message,
1381 "secondary-text", text,
1382 NULL((void*)0));
1383
1384 g_free (text);
1385 }
1386
1387 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), _("_Select Application")dcgettext (((void*)0), "_Select Application", 5), GTK_RESPONSE_ACCEPT);
1388
1389 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1390 _("_OK")dcgettext (((void*)0), "_OK", 5),
1391 "gtk-ok",
1392 GTK_RESPONSE_OK);
1393
1394 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_OK);
1395
1396 g_object_set_data_full (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))),
1397 "mime-action:file",
1398 caja_file_ref (parameters->file),
1399 (GDestroyNotify)caja_file_unref);
1400
1401 gtk_widget_show (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1402
1403 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
choose_program))), (parameters->parent_window), ((void*)0)
, (GConnectFlags) 0)
1404 G_CALLBACK (choose_program), parameters->parent_window)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
choose_program))), (parameters->parent_window), ((void*)0)
, (GConnectFlags) 0)
;
1405
1406 g_free (error_message);
1407 g_free (mime_type);
1408}
1409
1410static void
1411search_for_application_dbus_call_notify_cb (GDBusProxy *proxy,
1412 GAsyncResult *result,
1413 gpointer user_data)
1414{
1415 ActivateParametersInstall *parameters_install = user_data;
1416 GVariant *variant;
1417 GError *error = NULL((void*)0);
1418
1419 variant = g_dbus_proxy_call_finish (proxy, result, &error);
1420 if (variant == NULL((void*)0))
1421 {
1422 if (!g_dbus_error_is_remote_error (error) ||
1423 g_strcmp0 (g_dbus_error_get_remote_error (error), "org.freedesktop.PackageKit.Modify.Failed") == 0)
1424 {
1425 char *message;
1426
1427 message = g_strdup_printf ("%s\n%s",
1428 _("There was an internal error trying to search for applications:")dcgettext (((void*)0), "There was an internal error trying to search for applications:"
, 5)
,
1429 error->message);
1430 eel_show_error_dialog (_("Unable to search for application")dcgettext (((void*)0), "Unable to search for application", 5), message,
1431 parameters_install->parent_window);
1432 g_free (message);
1433 }
1434
1435 g_error_free (error);
1436 activate_parameters_install_free (parameters_install);
1437 return;
1438 }
1439
1440 g_variant_unref (variant);
1441
1442 /* activate the file again */
1443 caja_mime_activate_files (parameters_install->parent_window,
1444 parameters_install->slot_info,
1445 parameters_install->files,
1446 parameters_install->activation_directory,
1447 parameters_install->mode,
1448 parameters_install->flags,
1449 parameters_install->user_confirmation);
1450
1451 activate_parameters_install_free (parameters_install);
1452}
1453
1454static void
1455search_for_application_mime_type (ActivateParametersInstall *parameters_install, const gchar *mime_type)
1456{
1457 GdkWindow *window;
1458 guint xid = 0;
1459 const char *mime_types[2];
1460
1461 g_assert (parameters_install->proxy != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (parameters_install->proxy != ((void*)0)) _g_boolean_var_24
= 1; else _g_boolean_var_24 = 0; _g_boolean_var_24; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-mime-actions.c"
, 1461, ((const char*) (__func__)), "parameters_install->proxy != NULL"
); } while (0)
;
1462
1463 /* get XID from parent window */
1464 window = gtk_widget_get_window (GTK_WIDGET (parameters_install->parent_window)((((GtkWidget*) (void *) ((parameters_install->parent_window
)))))
);
1465 if (window != NULL((void*)0))
1466 {
1467 xid = GDK_WINDOW_XID (window)(gdk_x11_window_get_xid (window));
1468 }
1469
1470 mime_types[0] = mime_type;
1471 mime_types[1] = NULL((void*)0);
1472
1473 g_dbus_proxy_call (parameters_install->proxy,
1474 "InstallMimeTypes",
1475 g_variant_new ("(u^ass)",
1476 xid,
1477 mime_types,
1478 "hide-confirm-search"),
1479 G_DBUS_CALL_FLAGS_NONE,
1480 G_MAXINT2147483647 /* no timeout */,
1481 NULL((void*)0) /* cancellable */,
1482 (GAsyncReadyCallback) search_for_application_dbus_call_notify_cb,
1483 parameters_install);
1484
1485 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1486 "InstallMimeType method invoked for %s", mime_type);
1487}
1488
1489static void
1490application_unhandled_file_install (GtkDialog *dialog,
1491 gint response_id,
1492 ActivateParametersInstall *parameters_install)
1493{
1494 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1495 parameters_install->dialog = NULL((void*)0);
1496
1497 if (response_id == GTK_RESPONSE_YES)
1498 {
1499 char *mime_type;
1500
1501 mime_type = caja_file_get_mime_type (parameters_install->file);
1502 search_for_application_mime_type (parameters_install, mime_type);
1503 g_free (mime_type);
1504 }
1505 else
1506 {
1507 /* free as we're not going to get the async dbus callback */
1508 activate_parameters_install_free (parameters_install);
1509 }
1510}
1511
1512static gboolean
1513delete_cb (GtkDialog *dialog)
1514{
1515 gtk_dialog_response (dialog, GTK_RESPONSE_DELETE_EVENT);
1516 return TRUE(!(0));
1517}
1518
1519static void
1520pk_proxy_appeared_cb (GObject *source,
1521 GAsyncResult *res,
1522 gpointer user_data)
1523{
1524 ActivateParametersInstall *parameters_install = user_data;
1525 char *mime_type;
1526 char *description;
1527 char *error_message;
1528 GtkWidget *dialog;
1529 GDBusProxy *proxy;
1530 GError *error = NULL((void*)0);
1531
1532 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
1533
1534 if (error != NULL((void*)0))
1535 {
1536 g_warning ("Couldn't call Modify on the PackageKit interface: %s",
1537 error->message);
1538 g_error_free (error);
1539
1540 /* show an unhelpful dialog */
1541 show_unhandled_type_error (parameters_install);
1542 /* The callback wasn't started, so we have to free the parameters */
1543 activate_parameters_install_free (parameters_install);
1544
1545 return;
1546 }
1547
1548 mime_type = caja_file_get_mime_type (parameters_install->file);
1549 error_message = get_application_no_mime_type_handler_message (parameters_install->file,
1550 parameters_install->uri);
1551 /* use a custom dialog to prompt the user to install new software */
1552 dialog = gtk_message_dialog_new (parameters_install->parent_window, 0,
1553 GTK_MESSAGE_ERROR,
1554 GTK_BUTTONS_YES_NO,
1555 "%s", error_message);
1556 description = g_content_type_get_description (mime_type);
1557 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
1558 _("There is no application installed for %s files.\n"dcgettext (((void*)0), "There is no application installed for %s files.\n"
"Do you want to search for an application to open this file?"
, 5)
1559 "Do you want to search for an application to open this file?")dcgettext (((void*)0), "There is no application installed for %s files.\n"
"Do you want to search for an application to open this file?"
, 5)
,
1560 description);
1561 g_free (description);
1562 gtk_window_set_resizable (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), FALSE(0));
1563
1564 parameters_install->dialog = dialog;
1565 parameters_install->proxy = proxy;
1566
1567 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
application_unhandled_file_install))), (parameters_install), (
(void*)0), (GConnectFlags) 0)
1568 G_CALLBACK (application_unhandled_file_install),g_signal_connect_data ((dialog), ("response"), (((GCallback) (
application_unhandled_file_install))), (parameters_install), (
(void*)0), (GConnectFlags) 0)
1569 parameters_install)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
application_unhandled_file_install))), (parameters_install), (
(void*)0), (GConnectFlags) 0)
;
1570 g_signal_connect (dialog, "delete-event",g_signal_connect_data ((dialog), ("delete-event"), (((GCallback
) (delete_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
1571 G_CALLBACK (delete_cb), NULL)g_signal_connect_data ((dialog), ("delete-event"), (((GCallback
) (delete_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
1572 gtk_widget_show_all (dialog);
1573 g_free (mime_type);
1574}
1575
1576static void
1577application_unhandled_uri (ActivateParameters *parameters, char *uri)
1578{
1579 gboolean show_install_mime;
1580 char *mime_type;
1581 CajaFile *file;
1582 ActivateParametersInstall *parameters_install;
1583
1584 file = caja_file_get_by_uri (uri);
1585
1586 mime_type = caja_file_get_mime_type (file);
1587
1588 /* copy the parts of parameters we are interested in as the orignal will be unref'd */
1589 parameters_install = g_new0 (ActivateParametersInstall, 1)(ActivateParametersInstall *) (__extension__ ({ gsize __n = (
gsize) (1); gsize __s = sizeof (ActivateParametersInstall); 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; }))
;
1590 parameters_install->slot_info = parameters->slot_info;
1591 g_object_add_weak_pointer (G_OBJECT (parameters_install->slot_info)((((GObject*) (void *) ((parameters_install->slot_info))))
)
, (gpointer *)&parameters_install->slot_info);
1592 if (parameters->parent_window)
1593 {
1594 parameters_install->parent_window = parameters->parent_window;
1595 g_object_add_weak_pointer (G_OBJECT (parameters_install->parent_window)((((GObject*) (void *) ((parameters_install->parent_window
)))))
, (gpointer *)&parameters_install->parent_window);
1596 }
1597 parameters_install->activation_directory = g_strdup (parameters->activation_directory)g_strdup_inline (parameters->activation_directory);
1598 parameters_install->file = file;
1599 parameters_install->files = get_file_list_for_launch_locations (parameters->locations);
1600 parameters_install->mode = parameters->mode;
1601 parameters_install->flags = parameters->flags;
1602 parameters_install->user_confirmation = parameters->user_confirmation;
1603 parameters_install->uri = g_strdup(uri)g_strdup_inline (uri);
1604
1605#ifdef ENABLE_PACKAGEKIT1
1606 /* allow an admin to disable the PackageKit search functionality */
1607 show_install_mime = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_INSTALL_MIME_ACTIVATION"install-mime-activation");
1608#else
1609 /* we have no install functionality */
1610 show_install_mime = FALSE(0);
1611#endif
1612 /* There is no use trying to look for handlers of application/octet-stream */
1613 if (g_content_type_is_unknown (mime_type))
1614 {
1615 show_install_mime = FALSE(0);
Value stored to 'show_install_mime' is never read
1616 goto out;
1617 }
1618
1619 if (!show_install_mime)
1620 {
1621 goto out;
1622 }
1623
1624 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
1625 G_DBUS_PROXY_FLAGS_NONE,
1626 NULL((void*)0),
1627 "org.freedesktop.PackageKit",
1628 "/org/freedesktop/PackageKit",
1629 "org.freedesktop.PackageKit.Modify",
1630 NULL((void*)0),
1631 pk_proxy_appeared_cb,
1632 parameters_install);
1633
1634 return;
1635
1636out:
1637 /* show an unhelpful dialog */
1638 show_unhandled_type_error (parameters_install);
1639 /* The callback wasn't started, so we have to free the parameters */
1640 activate_parameters_install_free (parameters_install);
1641
1642 g_free (mime_type);
1643}
1644
1645typedef struct
1646{
1647 GtkWindow *parent_window;
1648 CajaFile *file;
1649} ActivateParametersDesktop;
1650
1651static void
1652activate_parameters_desktop_free (ActivateParametersDesktop *parameters_desktop)
1653{
1654 if (parameters_desktop->parent_window)
1655 {
1656 g_object_remove_weak_pointer (G_OBJECT (parameters_desktop->parent_window)((((GObject*) (void *) ((parameters_desktop->parent_window
)))))
, (gpointer *)&parameters_desktop->parent_window);
1657 }
1658 caja_file_unref (parameters_desktop->file);
1659 g_free (parameters_desktop);
1660}
1661
1662static void
1663untrusted_launcher_response_callback (GtkDialog *dialog,
1664 int response_id,
1665 ActivateParametersDesktop *parameters)
1666{
1667 GdkScreen *screen;
1668 char *uri;
1669 GFile *file;
1670
1671 switch (response_id)
1672 {
1673 case RESPONSE_RUN1000:
1674 screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window)((((GtkWidget*) (void *) ((parameters->parent_window))))));
1675 uri = caja_file_get_uri (parameters->file);
1676 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1677 "directory view activate_callback launch_desktop_file window=%p: %s",
1678 parameters->parent_window, uri);
1679 caja_launch_desktop_file (screen, uri, NULL((void*)0),
1680 parameters->parent_window);
1681 g_free (uri);
1682 break;
1683 case RESPONSE_MARK_TRUSTED1003:
1684 file = caja_file_get_location (parameters->file);
1685 caja_file_mark_desktop_file_trusted (file,
1686 parameters->parent_window,
1687 TRUE(!(0)),
1688 NULL((void*)0), NULL((void*)0));
1689 g_object_unref (file);
1690 break;
1691 default:
1692 /* Just destroy dialog */
1693 break;
1694 }
1695
1696 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1697 activate_parameters_desktop_free (parameters);
1698}
1699
1700static void
1701activate_desktop_file (ActivateParameters *parameters,
1702 CajaFile *file)
1703{
1704 ActivateParametersDesktop *parameters_desktop;
1705 GdkScreen *screen;
1706 char *uri;
1707
1708 screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window)((((GtkWidget*) (void *) ((parameters->parent_window))))));
1709
1710 if (!caja_file_is_trusted_link (file))
1711 {
1712 char *primary, *secondary, *display_name;
1713 GtkWidget *dialog;
1714
1715 /* copy the parts of parameters we are interested in as the orignal will be freed */
1716 parameters_desktop = g_new0 (ActivateParametersDesktop, 1)(ActivateParametersDesktop *) (__extension__ ({ gsize __n = (
gsize) (1); gsize __s = sizeof (ActivateParametersDesktop); 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; }))
;
1717 if (parameters->parent_window)
1718 {
1719 parameters_desktop->parent_window = parameters->parent_window;
1720 g_object_add_weak_pointer (G_OBJECT (parameters_desktop->parent_window)((((GObject*) (void *) ((parameters_desktop->parent_window
)))))
, (gpointer *)&parameters_desktop->parent_window);
1721 }
1722 parameters_desktop->file = caja_file_ref (file);
1723
1724 primary = _("Untrusted application launcher")dcgettext (((void*)0), "Untrusted application launcher", 5);
1725 display_name = caja_file_get_display_name (file);
1726 secondary =
1727 g_strdup_printf (_("The application launcher \"%s\" has not been marked as trusted. "dcgettext (((void*)0), "The application launcher \"%s\" has not been marked as trusted. "
"If you do not know the source of this file, launching it may be unsafe."
, 5)
1728 "If you do not know the source of this file, launching it may be unsafe."dcgettext (((void*)0), "The application launcher \"%s\" has not been marked as trusted. "
"If you do not know the source of this file, launching it may be unsafe."
, 5)
1729 )dcgettext (((void*)0), "The application launcher \"%s\" has not been marked as trusted. "
"If you do not know the source of this file, launching it may be unsafe."
, 5)
,
1730 display_name);
1731
1732 dialog = gtk_message_dialog_new (parameters->parent_window,
1733 0,
1734 GTK_MESSAGE_WARNING,
1735 GTK_BUTTONS_NONE,
1736 NULL((void*)0));
1737 g_object_set (dialog,
1738 "text", primary,
1739 "secondary-text", secondary,
1740 NULL((void*)0));
1741 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1742 _("_Launch Anyway")dcgettext (((void*)0), "_Launch Anyway", 5), RESPONSE_RUN1000);
1743 if (caja_file_can_set_permissions (file))
1744 {
1745 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1746 _("Mark as _Trusted")dcgettext (((void*)0), "Mark as _Trusted", 5), RESPONSE_MARK_TRUSTED1003);
1747 }
1748
1749 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
1750 _("_Cancel")dcgettext (((void*)0), "_Cancel", 5),
1751 "process-stop",
1752 GTK_RESPONSE_CANCEL);
1753
1754 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_CANCEL);
1755
1756 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
untrusted_launcher_response_callback))), (parameters_desktop)
, ((void*)0), (GConnectFlags) 0)
1757 G_CALLBACK (untrusted_launcher_response_callback),g_signal_connect_data ((dialog), ("response"), (((GCallback) (
untrusted_launcher_response_callback))), (parameters_desktop)
, ((void*)0), (GConnectFlags) 0)
1758 parameters_desktop)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
untrusted_launcher_response_callback))), (parameters_desktop)
, ((void*)0), (GConnectFlags) 0)
;
1759 gtk_widget_show (dialog);
1760
1761 g_free (display_name);
1762 g_free (secondary);
1763 return;
1764 }
1765
1766 uri = caja_file_get_uri (file);
1767 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1768 "directory view activate_callback launch_desktop_file window=%p: %s",
1769 parameters->parent_window, uri);
1770 caja_launch_desktop_file (screen, uri, NULL((void*)0),
1771 parameters->parent_window);
1772 g_free (uri);
1773}
1774
1775static void
1776activate_files (ActivateParameters *parameters)
1777{
1778 CajaWindowInfo *window_info;
1779 CajaWindowOpenFlags flags;
1780 CajaFile *file;
1781 GList *launch_desktop_files;
1782 GList *launch_files;
1783 GList *launch_in_terminal_files;
1784 GList *open_in_app_uris;
1785 GList *open_in_app_parameters;
1786 GList *unhandled_open_in_app_uris;
1787 GList *open_in_view_files;
1788 GList *l;
1789 int count;
1790 char *uri;
1791 char *executable_path, *quoted_path, *name;
1792 char *old_working_dir;
1793 ActivationAction action;
1794 GdkScreen *screen;
1795 LaunchLocation *location;
1796 ApplicationLaunchParameters *one_parameters = NULL((void*)0);
1797
1798 screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window)((((GtkWidget*) (void *) ((parameters->parent_window))))));
1799
1800 launch_desktop_files = NULL((void*)0);
1801 launch_files = NULL((void*)0);
1802 launch_in_terminal_files = NULL((void*)0);
1803 open_in_app_uris = NULL((void*)0);
1804 open_in_view_files = NULL((void*)0);
1805
1806 for (l = parameters->locations; l != NULL((void*)0); l = l->next)
1807 {
1808 location = l->data;
1809 file = location->file;
1810
1811 if (file_was_cancelled (file))
1812 {
1813 continue;
1814 }
1815
1816 action = get_activation_action (file);
1817 if (action == ACTIVATION_ACTION_ASK)
1818 {
1819 /* Special case for executable text files, since it might be
1820 * dangerous & unexpected to launch these.
1821 */
1822 pause_activation_timed_cancel (parameters);
1823 action = get_executable_text_file_action (parameters->parent_window, file);
1824 unpause_activation_timed_cancel (parameters);
1825 }
1826
1827 switch (action)
1828 {
1829 case ACTIVATION_ACTION_LAUNCH_DESKTOP_FILE :
1830 launch_desktop_files = g_list_prepend (launch_desktop_files, file);
1831 break;
1832 case ACTIVATION_ACTION_LAUNCH :
1833 launch_files = g_list_prepend (launch_files, file);
1834 break;
1835 case ACTIVATION_ACTION_LAUNCH_IN_TERMINAL :
1836 launch_in_terminal_files = g_list_prepend (launch_in_terminal_files, file);
1837 break;
1838 case ACTIVATION_ACTION_OPEN_IN_VIEW :
1839 open_in_view_files = g_list_prepend (open_in_view_files, file);
1840 break;
1841 case ACTIVATION_ACTION_OPEN_IN_APPLICATION :
1842 open_in_app_uris = g_list_prepend (open_in_app_uris, location->uri);
1843 break;
1844 case ACTIVATION_ACTION_DO_NOTHING :
1845 break;
1846 case ACTIVATION_ACTION_ASK :
1847 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-mime-actions.c"
, 1847, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1848 break;
1849 }
1850 }
1851
1852 launch_desktop_files = g_list_reverse (launch_desktop_files);
1853 for (l = launch_desktop_files; l != NULL((void*)0); l = l->next)
1854 {
1855 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1856
1857 activate_desktop_file (parameters, file);
1858 }
1859
1860 old_working_dir = NULL((void*)0);
1861 if (parameters->activation_directory &&
1862 (launch_files != NULL((void*)0) || launch_in_terminal_files != NULL((void*)0)))
1863 {
1864 old_working_dir = g_get_current_dir ();
1865 g_chdir (parameters->activation_directory);
1866
1867 }
1868
1869 launch_files = g_list_reverse (launch_files);
1870 for (l = launch_files; l != NULL((void*)0); l = l->next)
1871 {
1872 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1873
1874 uri = caja_file_get_activation_uri (file);
1875 executable_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
1876 quoted_path = g_shell_quote (executable_path);
1877 name = caja_file_get_name (file);
1878
1879 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1880 "directory view activate_callback launch_file window=%p: %s",
1881 parameters->parent_window, quoted_path);
1882
1883 caja_launch_application_from_command (screen, name, quoted_path, FALSE(0), NULL((void*)0));
1884 g_free (name);
1885 g_free (quoted_path);
1886 g_free (executable_path);
1887 g_free (uri);
1888
1889 }
1890
1891 launch_in_terminal_files = g_list_reverse (launch_in_terminal_files);
1892 for (l = launch_in_terminal_files; l != NULL((void*)0); l = l->next)
1893 {
1894 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1895
1896 uri = caja_file_get_activation_uri (file);
1897 executable_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
1898 quoted_path = g_shell_quote (executable_path);
1899 name = caja_file_get_name (file);
1900
1901 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1902 "directory view activate_callback launch_in_terminal window=%p: %s",
1903 parameters->parent_window, quoted_path);
1904
1905 caja_launch_application_from_command (screen, name, quoted_path, TRUE(!(0)), NULL((void*)0));
1906 g_free (name);
1907 g_free (quoted_path);
1908 g_free (executable_path);
1909 g_free (uri);
1910 }
1911
1912 if (old_working_dir != NULL((void*)0))
1913 {
1914 g_chdir (old_working_dir);
1915 g_free (old_working_dir);
1916 }
1917
1918 open_in_view_files = g_list_reverse (open_in_view_files);
1919 count = g_list_length (open_in_view_files);
1920
1921 flags = parameters->flags;
1922 if (count > 1)
1923 {
1924 if ((parameters->flags & CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW) == 0)
1925 {
1926 flags |= CAJA_WINDOW_OPEN_FLAG_NEW_TAB;
1927 }
1928 else
1929 {
1930 flags |= CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW;
1931 }
1932 }
1933
1934 if (parameters->slot_info != NULL((void*)0) &&
1935 (!parameters->user_confirmation ||
1936 confirm_multiple_windows (parameters->parent_window, count,
1937 (flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0)))
1938 {
1939
1940 if ((flags & CAJA_WINDOW_OPEN_FLAG_NEW_TAB) != 0 &&
1941 g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_NEW_TAB_POSITION"tabs-open-position") ==
1942 CAJA_NEW_TAB_POSITION_AFTER_CURRENT_TAB)
1943 {
1944 /* When inserting N tabs after the current one,
1945 * we first open tab N, then tab N-1, ..., then tab 0.
1946 * Each of them is appended to the current tab, i.e.
1947 * prepended to the list of tabs to open.
1948 */
1949 open_in_view_files = g_list_reverse (open_in_view_files);
1950 }
1951
1952
1953 for (l = open_in_view_files; l != NULL((void*)0); l = l->next)
1954 {
1955 GFile *f;
1956 /* The ui should ask for navigation or object windows
1957 * depending on what the current one is */
1958 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1959
1960 uri = caja_file_get_activation_uri (file);
1961 f = g_file_new_for_uri (uri);
1962 caja_window_slot_info_open_location (parameters->slot_info,caja_window_slot_info_open_location_full(parameters->slot_info
, f, parameters->mode, flags, ((void*)0), ((void*)0), ((void
*)0))
1963 f, parameters->mode, flags, NULL)caja_window_slot_info_open_location_full(parameters->slot_info
, f, parameters->mode, flags, ((void*)0), ((void*)0), ((void
*)0))
;
1964 g_object_unref (f);
1965 g_free (uri);
1966 }
1967 }
1968
1969 open_in_app_parameters = NULL((void*)0);
1970 unhandled_open_in_app_uris = NULL((void*)0);
1971
1972 if (open_in_app_uris != NULL((void*)0))
1973 {
1974 open_in_app_uris = g_list_reverse (open_in_app_uris);
1975
1976 open_in_app_parameters = make_activation_parameters
1977 (open_in_app_uris, &unhandled_open_in_app_uris);
1978 }
1979
1980 for (l = open_in_app_parameters; l != NULL((void*)0); l = l->next)
1981 {
1982 one_parameters = l->data;
1983
1984 caja_launch_application_by_uri (one_parameters->application,
1985 one_parameters->uris,
1986 parameters->parent_window);
1987 application_launch_parameters_free (one_parameters);
1988 }
1989
1990 for (l = unhandled_open_in_app_uris; l != NULL((void*)0); l = l->next)
1991 {
1992 uri = l->data;
1993
1994 /* this does not block */
1995 application_unhandled_uri (parameters, uri);
1996 }
1997
1998 window_info = NULL((void*)0);
1999 if (parameters->slot_info != NULL((void*)0))
2000 {
2001 window_info = caja_window_slot_info_get_window (parameters->slot_info);
2002 }
2003
2004 if (open_in_app_parameters != NULL((void*)0) ||
2005 unhandled_open_in_app_uris != NULL((void*)0))
2006 {
2007 if ((parameters->flags & CAJA_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0 &&
2008 window_info != NULL((void*)0) &&
2009 caja_window_info_get_window_type (window_info) == CAJA_WINDOW_SPATIAL)
2010 {
2011 caja_window_info_close (window_info);
2012 }
2013 }
2014
2015 g_list_free (launch_desktop_files);
2016 g_list_free (launch_files);
2017 g_list_free (launch_in_terminal_files);
2018 g_list_free (open_in_view_files);
2019 g_list_free (open_in_app_uris);
2020 g_list_free (open_in_app_parameters);
2021 g_list_free (unhandled_open_in_app_uris);
2022
2023 activation_parameters_free (parameters);
2024}
2025
2026static void
2027activation_mount_not_mounted_callback (GObject *source_object,
2028 GAsyncResult *res,
2029 gpointer user_data)
2030{
2031 ActivateParameters *parameters = user_data;
2032 GError *error;
2033 CajaFile *file;
2034
2035 file = parameters->not_mounted->data;
2036
2037 error = NULL((void*)0);
2038 if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error))
2039 {
2040 if (error->domain != G_IO_ERRORg_io_error_quark() ||
2041 (error->code != G_IO_ERROR_CANCELLED &&
2042 error->code != G_IO_ERROR_FAILED_HANDLED &&
2043 error->code != G_IO_ERROR_ALREADY_MOUNTED))
2044 {
2045 eel_show_error_dialog (_("Unable to mount location")dcgettext (((void*)0), "Unable to mount location", 5),
2046 error->message, parameters->parent_window);
2047 }
2048
2049 if (error->domain != G_IO_ERRORg_io_error_quark() ||
2050 error->code != G_IO_ERROR_ALREADY_MOUNTED)
2051 {
2052 LaunchLocation *loc;
2053
2054 loc = find_launch_location_for_file (parameters->locations,
2055 file);
2056 if (loc)
2057 {
2058 parameters->locations =
2059 g_list_remove (parameters->locations, loc);
2060 launch_location_free (loc);
2061 }
2062 }
2063
2064 g_error_free (error);
2065 }
2066
2067 parameters->not_mounted = g_list_delete_link (parameters->not_mounted,
2068 parameters->not_mounted);
2069 caja_file_unref (file);
2070
2071 activation_mount_not_mounted (parameters);
2072}
2073
2074static void
2075activation_mount_not_mounted (ActivateParameters *parameters)
2076{
2077 LaunchLocation *loc = NULL((void*)0);
2078 GList *l, *next, *files;
2079
2080 if (parameters->not_mounted != NULL((void*)0))
2081 {
2082 CajaFile *file;
2083 GFile *location;
2084 GMountOperation *mount_op;
2085
2086 file = parameters->not_mounted->data;
2087 mount_op = gtk_mount_operation_new (parameters->parent_window);
2088 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2089 g_signal_connect (mount_op, "notify::is-showing",g_signal_connect_data ((mount_op), ("notify::is-showing"), ((
(GCallback) (activate_mount_op_active))), (parameters), ((void
*)0), (GConnectFlags) 0)
2090 G_CALLBACK (activate_mount_op_active), parameters)g_signal_connect_data ((mount_op), ("notify::is-showing"), ((
(GCallback) (activate_mount_op_active))), (parameters), ((void
*)0), (GConnectFlags) 0)
;
2091 location = caja_file_get_location (file);
2092 g_file_mount_enclosing_volume (location, 0, mount_op, parameters->cancellable,
2093 activation_mount_not_mounted_callback, parameters);
2094 g_object_unref (location);
2095 /* unref mount_op here - g_file_mount_enclosing_volume() does ref for itself */
2096 g_object_unref (mount_op);
2097 return;
2098 }
2099
2100 parameters->tried_mounting = TRUE(!(0));
2101
2102 if (parameters->locations == NULL((void*)0))
2103 {
2104 activation_parameters_free (parameters);
2105 return;
2106 }
2107
2108 /* once the mount is finished, refresh all attributes */
2109 /* - fixes new windows not appearing after successful mount */
2110 for (l = parameters->locations; l != NULL((void*)0); l = next)
2111 {
2112 loc = l->data;
2113 next = l->next;
2114 caja_file_invalidate_all_attributes (loc->file);
2115 }
2116
2117 files = get_file_list_for_launch_locations (parameters->locations);
2118 caja_file_list_call_when_ready
2119 (files,
2120 caja_mime_actions_get_required_file_attributes () | CAJA_FILE_ATTRIBUTE_LINK_INFO,
2121 &parameters->files_handle,
2122 activate_callback, parameters);
2123 caja_file_list_free (files);
2124}
2125
2126
2127static void
2128activate_callback (GList *files, gpointer callback_data)
2129{
2130 ActivateParameters *parameters = callback_data;
2131 GList *l, *next;
2132 LaunchLocation *location;
2133 CajaFile *file = NULL((void*)0);
2134
2135 parameters->files_handle = NULL((void*)0);
2136
2137 for (l = parameters->locations; l != NULL((void*)0); l = next)
2138 {
2139 location = l->data;
2140 file = location->file;
2141 next = l->next;
2142
2143 if (file_was_cancelled (file))
2144 {
2145 launch_location_free (location);
2146 parameters->locations = g_list_delete_link (parameters->locations, l);
2147 continue;
2148 }
2149
2150 if (file_was_not_mounted (file))
2151 {
2152 if (parameters->tried_mounting)
2153 {
2154 launch_location_free (location);
2155 parameters->locations = g_list_delete_link (parameters->locations, l);
2156 }
2157 else
2158 {
2159 parameters->not_mounted = g_list_prepend (parameters->not_mounted,
2160 caja_file_ref (file));
2161 }
2162 continue;
2163 }
2164 }
2165
2166
2167 if (parameters->not_mounted != NULL((void*)0))
2168 {
2169 activation_mount_not_mounted (parameters);
2170 }
2171 else
2172 {
2173 activate_files (parameters);
2174 }
2175}
2176
2177static void
2178activate_activation_uris_ready_callback (GList *files_ignore,
2179 gpointer callback_data)
2180{
2181 ActivateParameters *parameters = callback_data;
2182 GList *l, *next, *files;
2183 LaunchLocation *location;
2184 CajaFile *file = NULL((void*)0);
2185
2186 parameters->files_handle = NULL((void*)0);
2187
2188 for (l = parameters->locations; l != NULL((void*)0); l = next)
2189 {
2190 location = l->data;
2191 file = location->file;
2192 next = l->next;
2193
2194 if (file_was_cancelled (file))
2195 {
2196 launch_location_free (location);
2197 parameters->locations = g_list_delete_link (parameters->locations, l);
2198 continue;
2199 }
2200
2201 if (caja_file_is_broken_symbolic_link (file))
2202 {
2203 launch_location_free (location);
2204 parameters->locations = g_list_delete_link (parameters->locations, l);
2205 pause_activation_timed_cancel (parameters);
2206 report_broken_symbolic_link (parameters->parent_window, file);
2207 unpause_activation_timed_cancel (parameters);
2208 continue;
2209 }
2210
2211 if (caja_file_get_file_type (file) == G_FILE_TYPE_MOUNTABLE &&
2212 !caja_file_has_activation_uri (file))
2213 {
2214 /* Don't launch these... There is nothing we
2215 can do */
2216 launch_location_free (location);
2217 parameters->locations = g_list_delete_link (parameters->locations, l);
2218 continue;
2219 }
2220
2221 }
2222
2223 if (parameters->locations == NULL((void*)0))
2224 {
2225 activation_parameters_free (parameters);
2226 return;
2227 }
2228
2229 /* Convert the files to the actual activation uri files */
2230 for (l = parameters->locations; l != NULL((void*)0); l = l->next)
2231 {
2232 char *uri;
2233 location = l->data;
2234
2235 /* We want the file for the activation URI since we care
2236 * about the attributes for that, not for the original file.
2237 */
2238 uri = caja_file_get_activation_uri (location->file);
2239 if (uri != NULL((void*)0))
2240 {
2241 launch_location_update_from_uri (location, uri);
2242 }
2243 g_free (uri);
2244 }
2245
2246
2247 /* get the parameters for the actual files */
2248 files = get_file_list_for_launch_locations (parameters->locations);
2249 caja_file_list_call_when_ready
2250 (files,
2251 caja_mime_actions_get_required_file_attributes () | CAJA_FILE_ATTRIBUTE_LINK_INFO,
2252 &parameters->files_handle,
2253 activate_callback, parameters);
2254 caja_file_list_free (files);
2255}
2256
2257static void
2258activation_get_activation_uris (ActivateParameters *parameters)
2259{
2260 GList *l, *files;
2261 LaunchLocation *location;
2262 CajaFile *file = NULL((void*)0);
2263
2264 /* link target info might be stale, re-read it */
2265 for (l = parameters->locations; l != NULL((void*)0); l = l->next)
2266 {
2267 location = l->data;
2268 file = location->file;
2269
2270 if (file_was_cancelled (file))
2271 {
2272 launch_location_free (location);
2273 parameters->locations = g_list_delete_link (parameters->locations, l);
2274 continue;
2275 }
2276
2277 if (caja_file_is_symbolic_link (file))
2278 {
2279 caja_file_invalidate_attributes
2280 (file,
2281 CAJA_FILE_ATTRIBUTE_INFO |
2282 CAJA_FILE_ATTRIBUTE_LINK_INFO);
2283 }
2284 }
2285
2286 if (parameters->locations == NULL((void*)0))
2287 {
2288 activation_parameters_free (parameters);
2289 return;
2290 }
2291
2292 files = get_file_list_for_launch_locations (parameters->locations);
2293 caja_file_list_call_when_ready
2294 (files,
2295 CAJA_FILE_ATTRIBUTE_INFO |
2296 CAJA_FILE_ATTRIBUTE_LINK_INFO,
2297 &parameters->files_handle,
2298 activate_activation_uris_ready_callback, parameters);
2299 caja_file_list_free (files);
2300}
2301
2302static void
2303activation_mountable_mounted (CajaFile *file,
2304 GFile *result_location,
2305 GError *error,
2306 gpointer callback_data)
2307{
2308 ActivateParameters *parameters = callback_data;
2309 LaunchLocation *location;
2310
2311 /* Remove from list of files that have to be mounted */
2312 parameters->mountables = g_list_remove (parameters->mountables, file);
2313 caja_file_unref (file);
2314
2315
2316 if (error == NULL((void*)0))
2317 {
2318 CajaFile *target_file;
2319
2320 /* Replace file with the result of the mount */
2321 target_file = caja_file_get (result_location);
2322
2323 location = find_launch_location_for_file (parameters->locations,
2324 file);
2325 if (location)
2326 {
2327 launch_location_update_from_file (location, target_file);
2328 }
2329 caja_file_unref (target_file);
2330 }
2331 else
2332 {
2333 /* Remove failed file */
2334
2335 if (error->domain != G_IO_ERRORg_io_error_quark() ||
2336 (error->code != G_IO_ERROR_FAILED_HANDLED &&
2337 error->code != G_IO_ERROR_ALREADY_MOUNTED))
2338 {
2339 location = find_launch_location_for_file (parameters->locations,
2340 file);
2341 if (location)
2342 {
2343 parameters->locations =
2344 g_list_remove (parameters->locations,
2345 location);
2346 launch_location_free (location);
2347 }
2348 }
2349
2350 if (error->domain != G_IO_ERRORg_io_error_quark() ||
2351 (error->code != G_IO_ERROR_CANCELLED &&
2352 error->code != G_IO_ERROR_FAILED_HANDLED &&
2353 error->code != G_IO_ERROR_ALREADY_MOUNTED))
2354 {
2355 eel_show_error_dialog (_("Unable to mount location")dcgettext (((void*)0), "Unable to mount location", 5),
2356 error->message, parameters->parent_window);
2357 }
2358
2359 if (error->code == G_IO_ERROR_CANCELLED)
2360 {
2361 activation_parameters_free (parameters);
2362 return;
2363 }
2364 }
2365
2366 /* Mount more mountables */
2367 activation_mount_mountables (parameters);
2368}
2369
2370
2371static void
2372activation_mount_mountables (ActivateParameters *parameters)
2373{
2374 if (parameters->mountables != NULL((void*)0))
2375 {
2376 CajaFile *file;
2377 GMountOperation *mount_op;
2378
2379 file = parameters->mountables->data;
2380 mount_op = gtk_mount_operation_new (parameters->parent_window);
2381 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2382 g_signal_connect (mount_op, "notify::is-showing",g_signal_connect_data ((mount_op), ("notify::is-showing"), ((
(GCallback) (activate_mount_op_active))), (parameters), ((void
*)0), (GConnectFlags) 0)
2383 G_CALLBACK (activate_mount_op_active), parameters)g_signal_connect_data ((mount_op), ("notify::is-showing"), ((
(GCallback) (activate_mount_op_active))), (parameters), ((void
*)0), (GConnectFlags) 0)
;
2384 caja_file_mount (file,
2385 mount_op,
2386 parameters->cancellable,
2387 activation_mountable_mounted,
2388 parameters);
2389 g_object_unref (mount_op);
2390 return;
2391 }
2392
2393 if (parameters->mountables == NULL((void*)0) && parameters->start_mountables == NULL((void*)0))
2394 activation_get_activation_uris (parameters);
2395}
2396
2397
2398static void
2399activation_mountable_started (CajaFile *file,
2400 GFile *gfile_of_file,
2401 GError *error,
2402 gpointer callback_data)
2403{
2404 ActivateParameters *parameters = callback_data;
2405 LaunchLocation *location;
2406
2407 /* Remove from list of files that have to be mounted */
2408 parameters->start_mountables = g_list_remove (parameters->start_mountables, file);
2409 caja_file_unref (file);
2410
2411 if (error == NULL((void*)0))
2412 {
2413 /* Remove file */
2414 location = find_launch_location_for_file (parameters->locations, file);
2415 if (location != NULL((void*)0))
2416 {
2417 parameters->locations = g_list_remove (parameters->locations, location);
2418 launch_location_free (location);
2419 }
2420
2421 }
2422 else
2423 {
2424 /* Remove failed file */
2425 if (error->domain != G_IO_ERRORg_io_error_quark() ||
2426 (error->code != G_IO_ERROR_FAILED_HANDLED))
2427 {
2428 location = find_launch_location_for_file (parameters->locations,
2429 file);
2430 if (location)
2431 {
2432 parameters->locations =
2433 g_list_remove (parameters->locations,
2434 location);
2435 launch_location_free (location);
2436 }
2437 }
2438
2439 if (error->domain != G_IO_ERRORg_io_error_quark() ||
2440 (error->code != G_IO_ERROR_CANCELLED &&
2441 error->code != G_IO_ERROR_FAILED_HANDLED))
2442 {
2443 eel_show_error_dialog (_("Unable to start location")dcgettext (((void*)0), "Unable to start location", 5),
2444 error->message, NULL((void*)0));
2445 }
2446
2447 if (error->code == G_IO_ERROR_CANCELLED)
2448 {
2449 activation_parameters_free (parameters);
2450 return;
2451 }
2452 }
2453
2454 /* Start more mountables */
2455 activation_start_mountables (parameters);
2456}
2457
2458static void
2459activation_start_mountables (ActivateParameters *parameters)
2460{
2461 if (parameters->start_mountables != NULL((void*)0))
2462 {
2463 CajaFile *file;
2464 GMountOperation *start_op;
2465
2466 file = parameters->start_mountables->data;
2467 start_op = gtk_mount_operation_new (parameters->parent_window);
2468 g_signal_connect (start_op, "notify::is-showing",g_signal_connect_data ((start_op), ("notify::is-showing"), ((
(GCallback) (activate_mount_op_active))), (parameters), ((void
*)0), (GConnectFlags) 0)
2469 G_CALLBACK (activate_mount_op_active), parameters)g_signal_connect_data ((start_op), ("notify::is-showing"), ((
(GCallback) (activate_mount_op_active))), (parameters), ((void
*)0), (GConnectFlags) 0)
;
2470 caja_file_start (file,
2471 start_op,
2472 parameters->cancellable,
2473 activation_mountable_started,
2474 parameters);
2475 g_object_unref (start_op);
2476 return;
2477 }
2478
2479 if (parameters->mountables == NULL((void*)0) && parameters->start_mountables == NULL((void*)0))
2480 activation_get_activation_uris (parameters);
2481}
2482
2483/**
2484 * caja_mime_activate_files:
2485 *
2486 * Activate a list of files. Each one might launch with an application or
2487 * with a component. This is normally called only by subclasses.
2488 * @view: FMDirectoryView in question.
2489 * @files: A GList of CajaFiles to activate.
2490 *
2491 **/
2492void
2493caja_mime_activate_files (GtkWindow *parent_window,
2494 CajaWindowSlotInfo *slot_info,
2495 GList *files,
2496 const char *launch_directory,
2497 CajaWindowOpenMode mode,
2498 CajaWindowOpenFlags flags,
2499 gboolean user_confirmation)
2500{
2501 ActivateParameters *parameters;
2502 int file_count;
2503 GList *l, *next;
2504 LaunchLocation *location;
2505 CajaFile *file = NULL((void*)0);
2506
2507 if (files == NULL((void*)0))
2508 {
2509 return;
2510 }
2511
2512 caja_debug_log_with_file_list (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER", files,
2513 "caja_mime_activate_files window=%p",
2514 parent_window);
2515
2516 parameters = g_new0 (ActivateParameters, 1)(ActivateParameters *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ActivateParameters); 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; }))
;
2517 parameters->slot_info = slot_info;
2518 g_object_add_weak_pointer (G_OBJECT (parameters->slot_info)((((GObject*) (void *) ((parameters->slot_info))))), (gpointer *)&parameters->slot_info);
2519 if (parent_window)
2520 {
2521 parameters->parent_window = parent_window;
2522 g_object_add_weak_pointer (G_OBJECT (parameters->parent_window)((((GObject*) (void *) ((parameters->parent_window))))), (gpointer *)&parameters->parent_window);
2523 }
2524 parameters->cancellable = g_cancellable_new ();
2525 parameters->activation_directory = g_strdup (launch_directory)g_strdup_inline (launch_directory);
2526 parameters->locations = launch_locations_from_file_list (files);
2527 parameters->mode = mode;
2528 parameters->flags = flags;
2529 parameters->user_confirmation = user_confirmation;
2530
2531 file_count = g_list_length (files);
2532 if (file_count == 1)
2533 {
2534 char *file_name;
2535
2536 file_name = caja_file_get_display_name (files->data);
2537 parameters->timed_wait_prompt = g_strdup_printf (_("Opening \"%s\".")dcgettext (((void*)0), "Opening \"%s\".", 5), file_name);
2538 g_free (file_name);
2539 }
2540 else
2541 {
2542 parameters->timed_wait_prompt = g_strdup_printf (ngettext ("Opening %d item.",dcngettext (((void*)0), "Opening %d item.", "Opening %d items."
, file_count, 5)
2543 "Opening %d items.",dcngettext (((void*)0), "Opening %d item.", "Opening %d items."
, file_count, 5)
2544 file_count)dcngettext (((void*)0), "Opening %d item.", "Opening %d items."
, file_count, 5)
,
2545 file_count);
2546 }
2547
2548
2549 for (l = parameters->locations; l != NULL((void*)0); l = next)
2550 {
2551 location = l->data;
2552 file = location->file;
2553 next = l->next;
2554
2555 if (caja_file_can_mount (file))
2556 {
2557 parameters->mountables = g_list_prepend (parameters->mountables,
2558 caja_file_ref (file));
2559 }
2560
2561 if (caja_file_can_start (file))
2562 {
2563 parameters->start_mountables = g_list_prepend (parameters->start_mountables,
2564 caja_file_ref (file));
2565 }
2566 }
2567
2568 activation_start_timed_cancel (parameters);
2569 if (parameters->mountables != NULL((void*)0))
2570 activation_mount_mountables (parameters);
2571 if (parameters->start_mountables != NULL((void*)0))
2572 activation_start_mountables (parameters);
2573 if (parameters->mountables == NULL((void*)0) && parameters->start_mountables == NULL((void*)0))
2574 activation_get_activation_uris (parameters);
2575}
2576
2577/**
2578 * caja_mime_activate_file:
2579 *
2580 * Activate a file in this view. This might involve switching the displayed
2581 * location for the current window, or launching an application.
2582 * @view: FMDirectoryView in question.
2583 * @file: A CajaFile representing the file in this view to activate.
2584 * @use_new_window: Should this item be opened in a new window?
2585 *
2586 **/
2587
2588void
2589caja_mime_activate_file (GtkWindow *parent_window,
2590 CajaWindowSlotInfo *slot_info,
2591 CajaFile *file,
2592 const char *launch_directory,
2593 CajaWindowOpenMode mode,
2594 CajaWindowOpenFlags flags)
2595{
2596 GList *files;
2597
2598 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_25
= 1; else _g_boolean_var_25 = 0; _g_boolean_var_25; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while (0)
;
2599
2600 files = g_list_prepend (NULL((void*)0), file);
2601 caja_mime_activate_files (parent_window, slot_info, files, launch_directory, mode, flags, FALSE(0));
2602 g_list_free (files);
2603}
diff --git a/2024-07-29-023715-6438-1/report-8ec019.html b/2024-07-29-023715-6438-1/report-8ec019.html new file mode 100644 index 000000000..3ea677e89 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-8ec019.html @@ -0,0 +1,1994 @@ + + + +caja-tree-view-drag-dest.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-tree-view-drag-dest.c
Warning:line 682, column 9
Value stored to 'action' 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 caja-tree-view-drag-dest.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-tree-view-drag-dest.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/*
4 * Caja
5 *
6 * Copyright (C) 2002 Sun Microsystems, Inc.
7 *
8 * Caja is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * Caja is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 * Author: Dave Camp <dave@ximian.com>
24 * XDS support: Benedikt Meurer <benny@xfce.org> (adapted by Amos Brocco <amos.brocco@unifr.ch>)
25 */
26
27/* caja-tree-view-drag-dest.c: Handles drag and drop for treeviews which
28 * contain a hierarchy of files
29 */
30
31#include <config.h>
32#include <stdio.h>
33#include <string.h>
34
35#include <gtk/gtk.h>
36
37#include <eel/eel-gtk-macros.h>
38
39#include "caja-tree-view-drag-dest.h"
40#include "caja-file-dnd.h"
41#include "caja-file-changes-queue.h"
42#include "caja-icon-dnd.h"
43#include "caja-link.h"
44#include "caja-marshal.h"
45#include "caja-debug-log.h"
46
47#define AUTO_SCROLL_MARGIN20 20
48
49#define HOVER_EXPAND_TIMEOUT1 1
50
51struct _CajaTreeViewDragDestDetails
52{
53 GtkTreeView *tree_view;
54
55 gboolean drop_occurred;
56
57 gboolean have_drag_data;
58 guint drag_type;
59 GtkSelectionData *drag_data;
60 GList *drag_list;
61
62 guint highlight_id;
63 guint scroll_id;
64 guint expand_id;
65
66 char *direct_save_uri;
67};
68
69enum
70{
71 GET_ROOT_URI,
72 GET_FILE_FOR_PATH,
73 MOVE_COPY_ITEMS,
74 HANDLE_NETSCAPE_URL,
75 HANDLE_URI_LIST,
76 HANDLE_TEXT,
77 HANDLE_RAW,
78 LAST_SIGNAL
79};
80
81static guint signals[LAST_SIGNAL] = { 0 };
82
83G_DEFINE_TYPE (CajaTreeViewDragDest, caja_tree_view_drag_dest,static void caja_tree_view_drag_dest_init (CajaTreeViewDragDest
*self); static void caja_tree_view_drag_dest_class_init (CajaTreeViewDragDestClass
*klass); static GType caja_tree_view_drag_dest_get_type_once
(void); static gpointer caja_tree_view_drag_dest_parent_class
= ((void*)0); static gint CajaTreeViewDragDest_private_offset
; static void caja_tree_view_drag_dest_class_intern_init (gpointer
klass) { caja_tree_view_drag_dest_parent_class = g_type_class_peek_parent
(klass); if (CajaTreeViewDragDest_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaTreeViewDragDest_private_offset); caja_tree_view_drag_dest_class_init
((CajaTreeViewDragDestClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer caja_tree_view_drag_dest_get_instance_private
(CajaTreeViewDragDest *self) { return (((gpointer) ((guint8*
) (self) + (glong) (CajaTreeViewDragDest_private_offset)))); }
GType caja_tree_view_drag_dest_get_type (void) { static GType
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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_tree_view_drag_dest_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_pointer ((&static_g_define_type_id), (
gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_tree_view_drag_dest_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CajaTreeViewDragDest"
), sizeof (CajaTreeViewDragDestClass), (GClassInitFunc)(void (
*)(void)) caja_tree_view_drag_dest_class_intern_init, sizeof (
CajaTreeViewDragDest), (GInstanceInitFunc)(void (*)(void)) caja_tree_view_drag_dest_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
84 G_TYPE_OBJECT)static void caja_tree_view_drag_dest_init (CajaTreeViewDragDest
*self); static void caja_tree_view_drag_dest_class_init (CajaTreeViewDragDestClass
*klass); static GType caja_tree_view_drag_dest_get_type_once
(void); static gpointer caja_tree_view_drag_dest_parent_class
= ((void*)0); static gint CajaTreeViewDragDest_private_offset
; static void caja_tree_view_drag_dest_class_intern_init (gpointer
klass) { caja_tree_view_drag_dest_parent_class = g_type_class_peek_parent
(klass); if (CajaTreeViewDragDest_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaTreeViewDragDest_private_offset); caja_tree_view_drag_dest_class_init
((CajaTreeViewDragDestClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer caja_tree_view_drag_dest_get_instance_private
(CajaTreeViewDragDest *self) { return (((gpointer) ((guint8*
) (self) + (glong) (CajaTreeViewDragDest_private_offset)))); }
GType caja_tree_view_drag_dest_get_type (void) { static GType
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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_tree_view_drag_dest_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_pointer ((&static_g_define_type_id), (
gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_tree_view_drag_dest_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CajaTreeViewDragDest"
), sizeof (CajaTreeViewDragDestClass), (GClassInitFunc)(void (
*)(void)) caja_tree_view_drag_dest_class_intern_init, sizeof (
CajaTreeViewDragDest), (GInstanceInitFunc)(void (*)(void)) caja_tree_view_drag_dest_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
;
85
86#define parent_classcaja_tree_view_drag_dest_parent_class caja_tree_view_drag_dest_parent_class
87
88static const GtkTargetEntry drag_types [] =
89{
90 { CAJA_ICON_DND_MATE_ICON_LIST_TYPE"x-special/mate-icon-list", 0, CAJA_ICON_DND_MATE_ICON_LIST },
91 /* prefer "_NETSCAPE_URL" over "text/uri-list" to satisfy web browsers. */
92 { CAJA_ICON_DND_NETSCAPE_URL_TYPE"_NETSCAPE_URL", 0, CAJA_ICON_DND_NETSCAPE_URL },
93 { CAJA_ICON_DND_URI_LIST_TYPE"text/uri-list", 0, CAJA_ICON_DND_URI_LIST },
94 { CAJA_ICON_DND_KEYWORD_TYPE"property/keyword", 0, CAJA_ICON_DND_KEYWORD },
95 { CAJA_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", 0, CAJA_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */
96 { CAJA_ICON_DND_RAW_TYPE"application/octet-stream", 0, CAJA_ICON_DND_RAW }
97};
98
99
100static void
101gtk_tree_view_vertical_autoscroll (GtkTreeView *tree_view)
102{
103 GdkRectangle visible_rect;
104 GtkAdjustment *vadjustment;
105 GdkDisplay *display;
106 GdkSeat *seat;
107 GdkDevice *pointer;
108 GdkWindow *window;
109 int y;
110 int offset;
111 float value;
112
113 window = gtk_tree_view_get_bin_window (tree_view);
114
115 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE(tree_view)((((GtkScrollable*) (void *) ((tree_view))))));
116
117 display = gtk_widget_get_display (GTK_WIDGET (tree_view)((((GtkWidget*) (void *) ((tree_view))))));
118 seat = gdk_display_get_default_seat (display);
119 pointer = gdk_seat_get_pointer (seat);
120 gdk_window_get_device_position (window, pointer,
121 NULL((void*)0), &y, NULL((void*)0));
122
123 y += gtk_adjustment_get_value (vadjustment);
124
125 gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
126
127 offset = y - (visible_rect.y + 2 * AUTO_SCROLL_MARGIN20);
128 if (offset > 0)
129 {
130 offset = y - (visible_rect.y + visible_rect.height - 2 * AUTO_SCROLL_MARGIN20);
131 if (offset < 0)
132 {
133 return;
134 }
135 }
136
137 value = CLAMP (gtk_adjustment_get_value (vadjustment) + offset, 0.0,(((gtk_adjustment_get_value (vadjustment) + offset) > (gtk_adjustment_get_upper
(vadjustment) - gtk_adjustment_get_page_size (vadjustment)))
? (gtk_adjustment_get_upper (vadjustment) - gtk_adjustment_get_page_size
(vadjustment)) : (((gtk_adjustment_get_value (vadjustment) +
offset) < (0.0)) ? (0.0) : (gtk_adjustment_get_value (vadjustment
) + offset)))
138 gtk_adjustment_get_upper (vadjustment) - gtk_adjustment_get_page_size (vadjustment))(((gtk_adjustment_get_value (vadjustment) + offset) > (gtk_adjustment_get_upper
(vadjustment) - gtk_adjustment_get_page_size (vadjustment)))
? (gtk_adjustment_get_upper (vadjustment) - gtk_adjustment_get_page_size
(vadjustment)) : (((gtk_adjustment_get_value (vadjustment) +
offset) < (0.0)) ? (0.0) : (gtk_adjustment_get_value (vadjustment
) + offset)))
;
139 gtk_adjustment_set_value (vadjustment, value);
140}
141
142static int
143scroll_timeout (gpointer data)
144{
145 GtkTreeView *tree_view = GTK_TREE_VIEW (data)((((GtkTreeView*) (void *) ((data)))));
146
147 gtk_tree_view_vertical_autoscroll (tree_view);
148
149 return TRUE(!(0));
150}
151
152static void
153remove_scroll_timeout (CajaTreeViewDragDest *dest)
154{
155 if (dest->details->scroll_id)
156 {
157 g_source_remove (dest->details->scroll_id);
158 dest->details->scroll_id = 0;
159 }
160}
161
162static int
163expand_timeout (gpointer data)
164{
165 GtkTreeView *tree_view;
166 GtkTreePath *drop_path;
167
168 tree_view = GTK_TREE_VIEW (data)((((GtkTreeView*) (void *) ((data)))));
169
170 gtk_tree_view_get_drag_dest_row (tree_view, &drop_path, NULL((void*)0));
171
172 if (drop_path)
173 {
174 gtk_tree_view_expand_row (tree_view, drop_path, FALSE(0));
175 gtk_tree_path_free (drop_path);
176 }
177
178 return FALSE(0);
179}
180
181static void
182remove_expand_timeout (CajaTreeViewDragDest *dest)
183{
184 if (dest->details->expand_id)
185 {
186 g_source_remove (dest->details->expand_id);
187 dest->details->expand_id = 0;
188 }
189}
190
191static gboolean
192highlight_draw (GtkWidget *widget,
193 cairo_t *cr,
194 gpointer data)
195{
196 GdkWindow *bin_window;
197 int width;
198 int height;
199 GtkStyleContext *style;
200
201 /* FIXMEchpe: is bin window right here??? */
202 bin_window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))));
203
204 width = gdk_window_get_width(bin_window);
205 height = gdk_window_get_height(bin_window);
206
207 style = gtk_widget_get_style_context (widget);
208
209 gtk_style_context_save (style);
210 gtk_style_context_add_class (style, "treeview-drop-indicator");
211
212 gtk_render_focus (style,
213 cr,
214 0, 0, width, height);
215
216 gtk_style_context_restore (style);
217
218 return FALSE(0);
219}
220
221static void
222set_widget_highlight (CajaTreeViewDragDest *dest, gboolean highlight)
223{
224 if (!highlight && dest->details->highlight_id)
225 {
226 g_signal_handler_disconnect (dest->details->tree_view,
227 dest->details->highlight_id);
228 dest->details->highlight_id = 0;
229 gtk_widget_queue_draw (GTK_WIDGET (dest->details->tree_view)((((GtkWidget*) (void *) ((dest->details->tree_view))))
)
);
230 }
231
232 if (highlight && !dest->details->highlight_id)
233 {
234 dest->details->highlight_id =
235 g_signal_connect_object (dest->details->tree_view,
236 "draw",
237 G_CALLBACK (highlight_draw)((GCallback) (highlight_draw)),
238 dest, 0);
239 gtk_widget_queue_draw (GTK_WIDGET (dest->details->tree_view)((((GtkWidget*) (void *) ((dest->details->tree_view))))
)
);
240 }
241}
242
243static void
244set_drag_dest_row (CajaTreeViewDragDest *dest,
245 GtkTreePath *path)
246{
247 if (path)
248 {
249 set_widget_highlight (dest, FALSE(0));
250 gtk_tree_view_set_drag_dest_row
251 (dest->details->tree_view,
252 path,
253 GTK_TREE_VIEW_DROP_INTO_OR_BEFORE);
254 }
255 else
256 {
257 set_widget_highlight (dest, TRUE(!(0)));
258 gtk_tree_view_set_drag_dest_row (dest->details->tree_view,
259 NULL((void*)0),
260 0);
261 }
262}
263
264static void
265clear_drag_dest_row (CajaTreeViewDragDest *dest)
266{
267 gtk_tree_view_set_drag_dest_row (dest->details->tree_view, NULL((void*)0), 0);
268 set_widget_highlight (dest, FALSE(0));
269}
270
271static gboolean
272get_drag_data (CajaTreeViewDragDest *dest,
273 GdkDragContext *context,
274 guint32 time)
275{
276 GdkAtom target;
277
278 target = gtk_drag_dest_find_target (GTK_WIDGET (dest->details->tree_view)((((GtkWidget*) (void *) ((dest->details->tree_view))))
)
,
279 context,
280 NULL((void*)0));
281
282 if (target == GDK_NONE((GdkAtom)((gpointer) (gulong) (0))))
283 {
284 return FALSE(0);
285 }
286
287 if (target == gdk_atom_intern (CAJA_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", FALSE(0)) &&
288 !dest->details->drop_occurred)
289 {
290 dest->details->drag_type = CAJA_ICON_DND_XDNDDIRECTSAVE;
291 dest->details->have_drag_data = TRUE(!(0));
292 return TRUE(!(0));
293 }
294
295 gtk_drag_get_data (GTK_WIDGET (dest->details->tree_view)((((GtkWidget*) (void *) ((dest->details->tree_view))))
)
,
296 context, target, time);
297
298 return TRUE(!(0));
299}
300
301static void
302free_drag_data (CajaTreeViewDragDest *dest)
303{
304 dest->details->have_drag_data = FALSE(0);
305
306 if (dest->details->drag_data)
307 {
308 gtk_selection_data_free (dest->details->drag_data);
309 dest->details->drag_data = NULL((void*)0);
310 }
311
312 if (dest->details->drag_list)
313 {
314 caja_drag_destroy_selection_list (dest->details->drag_list);
315 dest->details->drag_list = NULL((void*)0);
316 }
317
318 g_free (dest->details->direct_save_uri);
319 dest->details->direct_save_uri = NULL((void*)0);
320}
321
322static char *
323get_root_uri (CajaTreeViewDragDest *dest)
324{
325 char *uri;
326
327 g_signal_emit (dest, signals[GET_ROOT_URI], 0, &uri);
328
329 return uri;
330}
331
332static CajaFile *
333file_for_path (CajaTreeViewDragDest *dest, GtkTreePath *path)
334{
335 CajaFile *file;
336
337 if (path)
338 {
339 g_signal_emit (dest, signals[GET_FILE_FOR_PATH], 0, path, &file);
340 }
341 else
342 {
343 char *uri;
344
345 uri = get_root_uri (dest);
346
347 file = NULL((void*)0);
348 if (uri != NULL((void*)0))
349 {
350 file = caja_file_get_by_uri (uri);
351 }
352
353 g_free (uri);
354 }
355
356 return file;
357}
358
359static GtkTreePath *
360get_drop_path (CajaTreeViewDragDest *dest,
361 GtkTreePath *path)
362{
363 CajaFile *file;
364 GtkTreePath *ret;
365
366 if (!path || !dest->details->have_drag_data)
367 {
368 return NULL((void*)0);
369 }
370
371 ret = gtk_tree_path_copy (path);
372 file = file_for_path (dest, ret);
373
374 /* Go up the tree until we find a file that can accept a drop */
375 while (file == NULL((void*)0) /* dummy row */ ||
376 !caja_drag_can_accept_info (file,
377 dest->details->drag_type,
378 dest->details->drag_list))
379 {
380 if (gtk_tree_path_get_depth (ret) == 1)
381 {
382 gtk_tree_path_free (ret);
383 ret = NULL((void*)0);
384 break;
385 }
386 else
387 {
388 gtk_tree_path_up (ret);
389
390 caja_file_unref (file);
391 file = file_for_path (dest, ret);
392 }
393 }
394 caja_file_unref (file);
395
396 return ret;
397}
398
399static char *
400get_drop_target_uri_for_path (CajaTreeViewDragDest *dest,
401 GtkTreePath *path)
402{
403 CajaFile *file;
404 char *target;
405
406 file = file_for_path (dest, path);
407 if (file == NULL((void*)0))
408 {
409 return NULL((void*)0);
410 }
411
412 target = caja_file_get_drop_target_uri (file);
413 caja_file_unref (file);
414
415 return target;
416}
417
418static guint
419get_drop_action (CajaTreeViewDragDest *dest,
420 GdkDragContext *context,
421 GtkTreePath *path)
422{
423 char *drop_target;
424 int action;
425
426 if (!dest->details->have_drag_data ||
427 (dest->details->drag_type == CAJA_ICON_DND_MATE_ICON_LIST &&
428 dest->details->drag_list == NULL((void*)0)))
429 {
430 return 0;
431 }
432
433 switch (dest->details->drag_type)
434 {
435 case CAJA_ICON_DND_MATE_ICON_LIST :
436 drop_target = get_drop_target_uri_for_path (dest, path);
437
438 if (!drop_target)
439 {
440 return 0;
441 }
442
443 caja_drag_default_drop_action_for_icons
444 (context,
445 drop_target,
446 dest->details->drag_list,
447 &action);
448
449 g_free (drop_target);
450
451 return action;
452
453 case CAJA_ICON_DND_NETSCAPE_URL:
454 drop_target = get_drop_target_uri_for_path (dest, path);
455
456 if (drop_target == NULL((void*)0))
457 {
458 return 0;
459 }
460
461 action = caja_drag_default_drop_action_for_netscape_url (context);
462
463 g_free (drop_target);
464
465 return action;
466
467 case CAJA_ICON_DND_URI_LIST :
468 drop_target = get_drop_target_uri_for_path (dest, path);
469
470 if (drop_target == NULL((void*)0))
471 {
472 return 0;
473 }
474
475 g_free (drop_target);
476
477 return gdk_drag_context_get_suggested_action (context);
478
479 case CAJA_ICON_DND_TEXT:
480 case CAJA_ICON_DND_RAW:
481 case CAJA_ICON_DND_XDNDDIRECTSAVE:
482 return GDK_ACTION_COPY;
483
484 case CAJA_ICON_DND_KEYWORD:
485
486 if (!path)
487 {
488 return 0;
489 }
490
491 return GDK_ACTION_COPY;
492 }
493
494 return 0;
495}
496
497static gboolean
498drag_motion_callback (GtkWidget *widget,
499 GdkDragContext *context,
500 int x,
501 int y,
502 guint32 time,
503 gpointer data)
504{
505 CajaTreeViewDragDest *dest;
506 GtkTreePath *path;
507 GtkTreePath *drop_path, *old_drop_path;
508 GtkTreeIter drop_iter;
509 GtkTreeViewDropPosition pos;
510 GdkWindow *bin_window;
511 guint action;
512 gboolean res = TRUE(!(0));
513
514 dest = CAJA_TREE_VIEW_DRAG_DEST (data)((((CajaTreeViewDragDest*) (void *) ((data)))));
515
516 gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))),
517 x, y, &path, &pos);
518
519
520 if (!dest->details->have_drag_data)
521 {
522 res = get_drag_data (dest, context, time);
523 }
524
525 if (!res)
526 {
527 return FALSE(0);
528 }
529
530 drop_path = get_drop_path (dest, path);
531
532 action = 0;
533 bin_window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))));
534 if (bin_window != NULL((void*)0))
535 {
536 int bin_x, bin_y;
537 gdk_window_get_position (bin_window, &bin_x, &bin_y);
538 if (bin_y <= y)
539 {
540 /* ignore drags on the header */
541 action = get_drop_action (dest, context, drop_path);
542 }
543 }
544
545 gtk_tree_view_get_drag_dest_row (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))), &old_drop_path,
546 NULL((void*)0));
547
548 if (action)
549 {
550 GtkTreeModel *model;
551
552 set_drag_dest_row (dest, drop_path);
553 model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))));
554 if (drop_path == NULL((void*)0) || (old_drop_path != NULL((void*)0) &&
555 gtk_tree_path_compare (old_drop_path, drop_path) != 0))
556 {
557 remove_expand_timeout (dest);
558 }
559 if (dest->details->expand_id == 0 && drop_path != NULL((void*)0))
560 {
561 gtk_tree_model_get_iter (model, &drop_iter, drop_path);
562 if (gtk_tree_model_iter_has_child (model, &drop_iter))
563 {
564 dest->details->expand_id = g_timeout_add_seconds (HOVER_EXPAND_TIMEOUT1,
565 expand_timeout,
566 dest->details->tree_view);
567 }
568 }
569 }
570 else
571 {
572 clear_drag_dest_row (dest);
573 remove_expand_timeout (dest);
574 }
575
576 if (path)
577 {
578 gtk_tree_path_free (path);
579 }
580
581 if (drop_path)
582 {
583 gtk_tree_path_free (drop_path);
584 }
585
586 if (old_drop_path)
587 {
588 gtk_tree_path_free (old_drop_path);
589 }
590
591 if (dest->details->scroll_id == 0)
592 {
593 dest->details->scroll_id =
594 g_timeout_add (150,
595 scroll_timeout,
596 dest->details->tree_view);
597 }
598
599 gdk_drag_status (context, action, time);
600
601 return TRUE(!(0));
602}
603
604static void
605drag_leave_callback (GtkWidget *widget,
606 GdkDragContext *context,
607 guint32 time,
608 gpointer data)
609{
610 CajaTreeViewDragDest *dest;
611
612 dest = CAJA_TREE_VIEW_DRAG_DEST (data)((((CajaTreeViewDragDest*) (void *) ((data)))));
613
614 clear_drag_dest_row (dest);
615
616 free_drag_data (dest);
617
618 remove_scroll_timeout (dest);
619 remove_expand_timeout (dest);
620}
621
622static char *
623get_drop_target_uri_at_pos (CajaTreeViewDragDest *dest, int x, int y)
624{
625 char *drop_target;
626 GtkTreePath *path;
627 GtkTreePath *drop_path;
628 GtkTreeViewDropPosition pos;
629
630 gtk_tree_view_get_dest_row_at_pos (dest->details->tree_view, x, y,
631 &path, &pos);
632
633 drop_path = get_drop_path (dest, path);
634
635 drop_target = get_drop_target_uri_for_path (dest, drop_path);
636
637 if (path != NULL((void*)0))
638 {
639 gtk_tree_path_free (path);
640 }
641
642 if (drop_path != NULL((void*)0))
643 {
644 gtk_tree_path_free (drop_path);
645 }
646
647 return drop_target;
648}
649
650static void
651receive_uris (CajaTreeViewDragDest *dest,
652 GdkDragContext *context,
653 GList *source_uris,
654 int x, int y)
655{
656 char *drop_target;
657 GdkDragAction action, real_action;
658
659 drop_target = get_drop_target_uri_at_pos (dest, x, y);
660 g_assert (drop_target != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (drop_target != ((void*)0)) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-tree-view-drag-dest.c", 660, ((const char
*) (__func__)), "drop_target != NULL"); } while (0)
;
661
662 real_action = gdk_drag_context_get_selected_action (context);
663
664 if (real_action == GDK_ACTION_ASK)
665 {
666 if (caja_drag_selection_includes_special_link (dest->details->drag_list))
667 {
668 /* We only want to move the trash */
669 action = GDK_ACTION_MOVE;
670 }
671 else
672 {
673 action = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK;
674 }
675 real_action = caja_drag_drop_action_ask
676 (GTK_WIDGET (dest->details->tree_view)((((GtkWidget*) (void *) ((dest->details->tree_view))))
)
, action);
677 }
678
679 /* We only want to copy external uris */
680 if (dest->details->drag_type == CAJA_ICON_DND_URI_LIST)
681 {
682 action = GDK_ACTION_COPY;
Value stored to 'action' is never read
683 }
684
685 if (real_action > 0)
686 {
687 if (!caja_drag_uris_local (drop_target, source_uris)
688 || real_action != GDK_ACTION_MOVE)
689 {
690 g_signal_emit (dest, signals[MOVE_COPY_ITEMS], 0,
691 source_uris,
692 drop_target,
693 real_action,
694 x, y);
695 }
696 }
697
698 g_free (drop_target);
699}
700
701static void
702receive_dropped_icons (CajaTreeViewDragDest *dest,
703 GdkDragContext *context,
704 int x, int y)
705{
706 GList *source_uris;
707 GList *l;
708
709 /* FIXME: ignore local only moves */
710
711 if (!dest->details->drag_list)
712 {
713 return;
714 }
715
716 source_uris = NULL((void*)0);
717 for (l = dest->details->drag_list; l != NULL((void*)0); l = l->next)
718 {
719 source_uris = g_list_prepend (source_uris,
720 ((CajaDragSelectionItem *)l->data)->uri);
721 }
722
723 source_uris = g_list_reverse (source_uris);
724
725 receive_uris (dest, context, source_uris, x, y);
726
727 g_list_free (source_uris);
728}
729
730static void
731receive_dropped_uri_list (CajaTreeViewDragDest *dest,
732 GdkDragContext *context,
733 int x, int y)
734{
735 char *drop_target;
736
737 if (!dest->details->drag_data)
738 {
739 return;
740 }
741
742 drop_target = get_drop_target_uri_at_pos (dest, x, y);
743 g_assert (drop_target != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (drop_target != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-tree-view-drag-dest.c", 743, ((const char
*) (__func__)), "drop_target != NULL"); } while (0)
;
744
745 g_signal_emit (dest, signals[HANDLE_URI_LIST], 0,
746 (char*) gtk_selection_data_get_data (dest->details->drag_data),
747 drop_target,
748 gdk_drag_context_get_selected_action (context),
749 x, y);
750
751 g_free (drop_target);
752}
753
754static void
755receive_dropped_text (CajaTreeViewDragDest *dest,
756 GdkDragContext *context,
757 int x, int y)
758{
759 char *drop_target;
760 char *text;
761
762 if (!dest->details->drag_data)
763 {
764 return;
765 }
766
767 drop_target = get_drop_target_uri_at_pos (dest, x, y);
768 g_assert (drop_target != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (drop_target != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-tree-view-drag-dest.c", 768, ((const char
*) (__func__)), "drop_target != NULL"); } while (0)
;
769
770 text = gtk_selection_data_get_text (dest->details->drag_data);
771 g_signal_emit (dest, signals[HANDLE_TEXT], 0,
772 (char *) text, drop_target,
773 gdk_drag_context_get_selected_action (context),
774 x, y);
775
776 g_free (text);
777 g_free (drop_target);
778}
779
780static void
781receive_dropped_raw (CajaTreeViewDragDest *dest,
782 const char *raw_data, int length,
783 GdkDragContext *context,
784 int x, int y)
785{
786 char *drop_target;
787
788 if (!dest->details->drag_data)
789 {
790 return;
791 }
792
793 drop_target = get_drop_target_uri_at_pos (dest, x, y);
794 g_assert (drop_target != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (drop_target != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-tree-view-drag-dest.c", 794, ((const char
*) (__func__)), "drop_target != NULL"); } while (0)
;
795
796 g_signal_emit (dest, signals[HANDLE_RAW], 0,
797 raw_data, length, drop_target,
798 dest->details->direct_save_uri,
799 gdk_drag_context_get_selected_action (context),
800 x, y);
801
802 g_free (drop_target);
803}
804
805static void
806receive_dropped_netscape_url (CajaTreeViewDragDest *dest,
807 GdkDragContext *context,
808 int x, int y)
809{
810 char *drop_target;
811
812 if (!dest->details->drag_data)
813 {
814 return;
815 }
816
817 drop_target = get_drop_target_uri_at_pos (dest, x, y);
818 g_assert (drop_target != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (drop_target != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-tree-view-drag-dest.c", 818, ((const char
*) (__func__)), "drop_target != NULL"); } while (0)
;
819
820 g_signal_emit (dest, signals[HANDLE_NETSCAPE_URL], 0,
821 (char*) gtk_selection_data_get_data (dest->details->drag_data),
822 drop_target,
823 gdk_drag_context_get_selected_action (context),
824 x, y);
825
826 g_free (drop_target);
827}
828
829static void
830receive_dropped_keyword (CajaTreeViewDragDest *dest,
831 GdkDragContext *context,
832 int x, int y)
833{
834 char *drop_target_uri;
835 CajaFile *drop_target_file;
836
837 if (!dest->details->drag_data)
838 {
839 return;
840 }
841
842 drop_target_uri = get_drop_target_uri_at_pos (dest, x, y);
843 g_assert (drop_target_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (drop_target_uri != ((void*)0)) _g_boolean_var_23 = 1; else
_g_boolean_var_23 = 0; _g_boolean_var_23; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-tree-view-drag-dest.c", 843, ((const char
*) (__func__)), "drop_target_uri != NULL"); } while (0)
;
844
845 drop_target_file = caja_file_get_by_uri (drop_target_uri);
846
847 if (drop_target_file != NULL((void*)0))
848 {
849 caja_drag_file_receive_dropped_keyword (drop_target_file,
850 (char *) gtk_selection_data_get_data (dest->details->drag_data));
851 caja_file_unref (drop_target_file);
852 }
853
854 g_free (drop_target_uri);
855}
856
857static gboolean
858receive_xds (CajaTreeViewDragDest *dest,
859 GtkWidget *widget,
860 guint32 time,
861 GdkDragContext *context,
862 int x, int y)
863{
864 GFile *location;
865 const guchar *selection_data;
866 gint selection_format;
867 gint selection_length;
868
869 selection_data = gtk_selection_data_get_data (dest->details->drag_data);
870 selection_format = gtk_selection_data_get_format (dest->details->drag_data);
871 selection_length = gtk_selection_data_get_length (dest->details->drag_data);
872
873 if (selection_format == 8
874 && selection_length == 1
875 && selection_data[0] == 'F')
876 {
877 gtk_drag_get_data (widget, context,
878 gdk_atom_intern (CAJA_ICON_DND_RAW_TYPE"application/octet-stream",
879 FALSE(0)),
880 time);
881 return FALSE(0);
882 }
883 else if (selection_format == 8
884 && selection_length == 1
885 && selection_data[0] == 'S')
886 {
887 g_assert (dest->details->direct_save_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (dest->details->direct_save_uri != ((void*)0)) _g_boolean_var_24
= 1; else _g_boolean_var_24 = 0; _g_boolean_var_24; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-tree-view-drag-dest.c"
, 887, ((const char*) (__func__)), "dest->details->direct_save_uri != NULL"
); } while (0)
;
888 location = g_file_new_for_uri (dest->details->direct_save_uri);
889
890 caja_file_changes_queue_file_added (location);
891 caja_file_changes_consume_changes (TRUE(!(0)));
892
893 g_object_unref (location);
894 }
895 return TRUE(!(0));
896}
897
898
899static gboolean
900drag_data_received_callback (GtkWidget *widget,
901 GdkDragContext *context,
902 int x,
903 int y,
904 GtkSelectionData *selection_data,
905 guint info,
906 guint32 time,
907 gpointer data)
908{
909 CajaTreeViewDragDest *dest;
910 gboolean success, finished;
911
912 dest = CAJA_TREE_VIEW_DRAG_DEST (data)((((CajaTreeViewDragDest*) (void *) ((data)))));
913
914 if (!dest->details->have_drag_data)
915 {
916 dest->details->have_drag_data = TRUE(!(0));
917 dest->details->drag_type = info;
918 dest->details->drag_data =
919 gtk_selection_data_copy (selection_data);
920 if (info == CAJA_ICON_DND_MATE_ICON_LIST)
921 {
922 dest->details->drag_list =
923 caja_drag_build_selection_list (selection_data);
924 }
925 }
926
927 if (dest->details->drop_occurred)
928 {
929 success = FALSE(0);
930 finished = TRUE(!(0));
931 switch (info)
932 {
933 case CAJA_ICON_DND_MATE_ICON_LIST :
934 receive_dropped_icons (dest, context, x, y);
935 success = TRUE(!(0));
936 break;
937 case CAJA_ICON_DND_NETSCAPE_URL :
938 receive_dropped_netscape_url (dest, context, x, y);
939 success = TRUE(!(0));
940 break;
941 case CAJA_ICON_DND_URI_LIST :
942 receive_dropped_uri_list (dest, context, x, y);
943 success = TRUE(!(0));
944 break;
945 case CAJA_ICON_DND_TEXT:
946 receive_dropped_text (dest, context, x, y);
947 success = TRUE(!(0));
948 break;
949 case CAJA_ICON_DND_RAW:
950 {
951 const char *tmp;
952 int length;
953
954 length = gtk_selection_data_get_length (selection_data);
955 tmp = gtk_selection_data_get_data (selection_data);
956 receive_dropped_raw (dest, tmp, length, context, x, y);
957 success = TRUE(!(0));
958 break;
959 }
960 case CAJA_ICON_DND_KEYWORD:
961 receive_dropped_keyword (dest, context, x, y);
962 success = TRUE(!(0));
963 break;
964 case CAJA_ICON_DND_XDNDDIRECTSAVE:
965 finished = receive_xds (dest, widget, time, context, x, y);
966 success = TRUE(!(0));
967 break;
968 }
969
970 if (finished)
971 {
972 dest->details->drop_occurred = FALSE(0);
973 free_drag_data (dest);
974 gtk_drag_finish (context, success, FALSE(0), time);
975 }
976 }
977
978 /* appease GtkTreeView by preventing its drag_data_receive
979 * from being called */
980 g_signal_stop_emission_by_name (dest->details->tree_view,
981 "drag_data_received");
982
983 return TRUE(!(0));
984}
985
986static char *
987get_direct_save_filename (GdkDragContext *context)
988{
989 guchar *prop_text;
990 gint prop_len;
991
992 if (!gdk_property_get (gdk_drag_context_get_source_window (context), gdk_atom_intern (CAJA_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", FALSE(0)),
993 gdk_atom_intern ("text/plain", FALSE(0)), 0, 1024, FALSE(0), NULL((void*)0), NULL((void*)0),
994 &prop_len, &prop_text))
995 {
996 return NULL((void*)0);
997 }
998
999 /* Zero-terminate the string */
1000 prop_text = g_realloc (prop_text, prop_len + 1);
1001 prop_text[prop_len] = '\0';
1002
1003 /* Verify that the file name provided by the source is valid */
1004 if (*prop_text == '\0' ||
1005 strchr ((const gchar *) prop_text, G_DIR_SEPARATOR'/') != NULL((void*)0))
1006 {
1007 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1008 "Invalid filename provided by XDS drag site");
1009 g_free (prop_text);
1010 return NULL((void*)0);
1011 }
1012
1013 return prop_text;
1014}
1015
1016static gboolean
1017set_direct_save_uri (CajaTreeViewDragDest *dest,
1018 GdkDragContext *context,
1019 int x, int y)
1020{
1021 char *drop_uri;
1022 char *uri;
1023
1024 g_assert (dest->details->direct_save_uri == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (dest->details->direct_save_uri == ((void*)0)) _g_boolean_var_25
= 1; else _g_boolean_var_25 = 0; _g_boolean_var_25; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-tree-view-drag-dest.c"
, 1024, ((const char*) (__func__)), "dest->details->direct_save_uri == NULL"
); } while (0)
;
1025
1026 uri = NULL((void*)0);
1027
1028 drop_uri = get_drop_target_uri_at_pos (dest, x, y);
1029 if (drop_uri != NULL((void*)0))
1030 {
1031 char *filename;
1032
1033 filename = get_direct_save_filename (context);
1034 if (filename != NULL((void*)0))
1035 {
1036 GFile *base, *child;
1037
1038 /* Resolve relative path */
1039 base = g_file_new_for_uri (drop_uri);
1040 child = g_file_get_child (base, filename);
1041 uri = g_file_get_uri (child);
1042
1043 g_object_unref (base);
1044 g_object_unref (child);
1045 g_free (filename);
1046
1047 /* Change the property */
1048 gdk_property_change (gdk_drag_context_get_source_window (context),
1049 gdk_atom_intern (CAJA_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", FALSE(0)),
1050 gdk_atom_intern ("text/plain", FALSE(0)), 8,
1051 GDK_PROP_MODE_REPLACE, (const guchar *) uri,
1052 strlen (uri));
1053
1054 dest->details->direct_save_uri = uri;
1055 }
1056 else
1057 {
1058 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1059 "Invalid filename provided by XDS drag site");
1060 }
1061 }
1062 else
1063 {
1064 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1065 "Could not retrieve XDS drop destination");
1066 }
1067
1068 return uri != NULL((void*)0);
1069}
1070
1071static gboolean
1072drag_drop_callback (GtkWidget *widget,
1073 GdkDragContext *context,
1074 int x,
1075 int y,
1076 guint32 time,
1077 gpointer data)
1078{
1079 CajaTreeViewDragDest *dest;
1080 guint info;
1081 GdkAtom target;
1082
1083 dest = CAJA_TREE_VIEW_DRAG_DEST (data)((((CajaTreeViewDragDest*) (void *) ((data)))));
1084
1085 target = gtk_drag_dest_find_target (GTK_WIDGET (dest->details->tree_view)((((GtkWidget*) (void *) ((dest->details->tree_view))))
)
,
1086 context,
1087 NULL((void*)0));
1088 if (target == GDK_NONE((GdkAtom)((gpointer) (gulong) (0))))
1089 {
1090 return FALSE(0);
1091 }
1092
1093 info = dest->details->drag_type;
1094
1095 if (info == CAJA_ICON_DND_XDNDDIRECTSAVE)
1096 {
1097 /* We need to set this or get_drop_path will fail, and it
1098 was unset by drag_leave_callback */
1099 dest->details->have_drag_data = TRUE(!(0));
1100 if (!set_direct_save_uri (dest, context, x, y))
1101 {
1102 return FALSE(0);
1103 }
1104 dest->details->have_drag_data = FALSE(0);
1105 }
1106
1107 dest->details->drop_occurred = TRUE(!(0));
1108
1109 get_drag_data (dest, context, time);
1110 remove_scroll_timeout (dest);
1111 remove_expand_timeout (dest);
1112 clear_drag_dest_row (dest);
1113
1114 return TRUE(!(0));
1115}
1116
1117static void
1118tree_view_weak_notify (gpointer user_data,
1119 GObject *object)
1120{
1121 CajaTreeViewDragDest *dest;
1122
1123 dest = CAJA_TREE_VIEW_DRAG_DEST (user_data)((((CajaTreeViewDragDest*) (void *) ((user_data)))));
1124
1125 remove_scroll_timeout (dest);
1126 remove_expand_timeout (dest);
1127
1128 dest->details->tree_view = NULL((void*)0);
1129}
1130
1131static void
1132caja_tree_view_drag_dest_dispose (GObject *object)
1133{
1134 CajaTreeViewDragDest *dest;
1135
1136 dest = CAJA_TREE_VIEW_DRAG_DEST (object)((((CajaTreeViewDragDest*) (void *) ((object)))));
1137
1138 if (dest->details->tree_view)
1139 {
1140 g_object_weak_unref (G_OBJECT (dest->details->tree_view)((((GObject*) (void *) ((dest->details->tree_view))))),
1141 tree_view_weak_notify,
1142 dest);
1143 }
1144
1145 remove_scroll_timeout (dest);
1146 remove_expand_timeout (dest);
1147
1148 EEL_CALL_PARENT (G_OBJECT_CLASS, dispose, (object))do { if (((((GObjectClass*) (void *) ((caja_tree_view_drag_dest_parent_class
)))))->dispose != ((void*)0)) { (* ((((GObjectClass*) (void
*) ((caja_tree_view_drag_dest_parent_class)))))->dispose)
(object); } } while (0)
;
1149}
1150
1151static void
1152caja_tree_view_drag_dest_finalize (GObject *object)
1153{
1154 CajaTreeViewDragDest *dest;
1155
1156 dest = CAJA_TREE_VIEW_DRAG_DEST (object)((((CajaTreeViewDragDest*) (void *) ((object)))));
1157
1158 free_drag_data (dest);
1159
1160 g_free (dest->details);
1161
1162 EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object))do { if (((((GObjectClass*) (void *) ((caja_tree_view_drag_dest_parent_class
)))))->finalize != ((void*)0)) { (* ((((GObjectClass*) (void
*) ((caja_tree_view_drag_dest_parent_class)))))->finalize
) (object); } } while (0)
;
1163}
1164
1165static void
1166caja_tree_view_drag_dest_init (CajaTreeViewDragDest *dest)
1167{
1168 dest->details = g_new0 (CajaTreeViewDragDestDetails, 1)(CajaTreeViewDragDestDetails *) (__extension__ ({ gsize __n =
(gsize) (1); gsize __s = sizeof (CajaTreeViewDragDestDetails
); 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; }))
;
1169}
1170
1171static void
1172caja_tree_view_drag_dest_class_init (CajaTreeViewDragDestClass *class)
1173{
1174 GObjectClass *gobject_class;
1175
1176 gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))));
1177
1178 gobject_class->dispose = caja_tree_view_drag_dest_dispose;
1179 gobject_class->finalize = caja_tree_view_drag_dest_finalize;
1180
1181 signals[GET_ROOT_URI] =
1182 g_signal_new ("get_root_uri",
1183 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
1184 G_SIGNAL_RUN_LAST,
1185 G_STRUCT_OFFSET (CajaTreeViewDragDestClass,((glong) __builtin_offsetof(CajaTreeViewDragDestClass, get_root_uri
))
1186 get_root_uri)((glong) __builtin_offsetof(CajaTreeViewDragDestClass, get_root_uri
))
,
1187 NULL((void*)0), NULL((void*)0),
1188 caja_marshal_STRING__VOID,
1189 G_TYPE_STRING((GType) ((16) << (2))), 0);
1190 signals[GET_FILE_FOR_PATH] =
1191 g_signal_new ("get_file_for_path",
1192 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
1193 G_SIGNAL_RUN_LAST,
1194 G_STRUCT_OFFSET (CajaTreeViewDragDestClass,((glong) __builtin_offsetof(CajaTreeViewDragDestClass, get_file_for_path
))
1195 get_file_for_path)((glong) __builtin_offsetof(CajaTreeViewDragDestClass, get_file_for_path
))
,
1196 NULL((void*)0), NULL((void*)0),
1197 caja_marshal_OBJECT__BOXED,
1198 CAJA_TYPE_FILEcaja_file_get_type(), 1,
1199 GTK_TYPE_TREE_PATH(gtk_tree_path_get_type ()));
1200 signals[MOVE_COPY_ITEMS] =
1201 g_signal_new ("move_copy_items",
1202 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
1203 G_SIGNAL_RUN_LAST,
1204 G_STRUCT_OFFSET (CajaTreeViewDragDestClass,((glong) __builtin_offsetof(CajaTreeViewDragDestClass, move_copy_items
))
1205 move_copy_items)((glong) __builtin_offsetof(CajaTreeViewDragDestClass, move_copy_items
))
,
1206 NULL((void*)0), NULL((void*)0),
1207
1208 caja_marshal_VOID__POINTER_STRING_ENUM_INT_INT,
1209 G_TYPE_NONE((GType) ((1) << (2))), 5,
1210 G_TYPE_POINTER((GType) ((17) << (2))),
1211 G_TYPE_STRING((GType) ((16) << (2))),
1212 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
1213 G_TYPE_INT((GType) ((6) << (2))),
1214 G_TYPE_INT((GType) ((6) << (2))));
1215 signals[HANDLE_NETSCAPE_URL] =
1216 g_signal_new ("handle_netscape_url",
1217 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
1218 G_SIGNAL_RUN_LAST,
1219 G_STRUCT_OFFSET (CajaTreeViewDragDestClass,((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_netscape_url
))
1220 handle_netscape_url)((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_netscape_url
))
,
1221 NULL((void*)0), NULL((void*)0),
1222 caja_marshal_VOID__STRING_STRING_ENUM_INT_INT,
1223 G_TYPE_NONE((GType) ((1) << (2))), 5,
1224 G_TYPE_STRING((GType) ((16) << (2))),
1225 G_TYPE_STRING((GType) ((16) << (2))),
1226 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
1227 G_TYPE_INT((GType) ((6) << (2))),
1228 G_TYPE_INT((GType) ((6) << (2))));
1229 signals[HANDLE_URI_LIST] =
1230 g_signal_new ("handle_uri_list",
1231 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
1232 G_SIGNAL_RUN_LAST,
1233 G_STRUCT_OFFSET (CajaTreeViewDragDestClass,((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_uri_list
))
1234 handle_uri_list)((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_uri_list
))
,
1235 NULL((void*)0), NULL((void*)0),
1236 caja_marshal_VOID__STRING_STRING_ENUM_INT_INT,
1237 G_TYPE_NONE((GType) ((1) << (2))), 5,
1238 G_TYPE_STRING((GType) ((16) << (2))),
1239 G_TYPE_STRING((GType) ((16) << (2))),
1240 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
1241 G_TYPE_INT((GType) ((6) << (2))),
1242 G_TYPE_INT((GType) ((6) << (2))));
1243 signals[HANDLE_TEXT] =
1244 g_signal_new ("handle_text",
1245 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
1246 G_SIGNAL_RUN_LAST,
1247 G_STRUCT_OFFSET (CajaTreeViewDragDestClass,((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_text
))
1248 handle_text)((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_text
))
,
1249 NULL((void*)0), NULL((void*)0),
1250 caja_marshal_VOID__STRING_STRING_ENUM_INT_INT,
1251 G_TYPE_NONE((GType) ((1) << (2))), 5,
1252 G_TYPE_STRING((GType) ((16) << (2))),
1253 G_TYPE_STRING((GType) ((16) << (2))),
1254 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
1255 G_TYPE_INT((GType) ((6) << (2))),
1256 G_TYPE_INT((GType) ((6) << (2))));
1257 signals[HANDLE_RAW] =
1258 g_signal_new ("handle_raw",
1259 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
1260 G_SIGNAL_RUN_LAST,
1261 G_STRUCT_OFFSET (CajaTreeViewDragDestClass,((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_raw
))
1262 handle_raw)((glong) __builtin_offsetof(CajaTreeViewDragDestClass, handle_raw
))
,
1263 NULL((void*)0), NULL((void*)0),
1264 caja_marshal_VOID__POINTER_INT_STRING_STRING_ENUM_INT_INT,
1265 G_TYPE_NONE((GType) ((1) << (2))), 7,
1266 G_TYPE_POINTER((GType) ((17) << (2))),
1267 G_TYPE_INT((GType) ((6) << (2))),
1268 G_TYPE_STRING((GType) ((16) << (2))),
1269 G_TYPE_STRING((GType) ((16) << (2))),
1270 GDK_TYPE_DRAG_ACTION(gdk_drag_action_get_type ()),
1271 G_TYPE_INT((GType) ((6) << (2))),
1272 G_TYPE_INT((GType) ((6) << (2))));
1273}
1274
1275
1276
1277CajaTreeViewDragDest *
1278caja_tree_view_drag_dest_new (GtkTreeView *tree_view)
1279{
1280 CajaTreeViewDragDest *dest;
1281 GtkTargetList *targets;
1282
1283 dest = g_object_new (CAJA_TYPE_TREE_VIEW_DRAG_DEST(caja_tree_view_drag_dest_get_type ()), NULL((void*)0));
1284
1285 dest->details->tree_view = tree_view;
1286 g_object_weak_ref (G_OBJECT (dest->details->tree_view)((((GObject*) (void *) ((dest->details->tree_view))))),
1287 tree_view_weak_notify, dest);
1288
1289 gtk_drag_dest_set (GTK_WIDGET (tree_view)((((GtkWidget*) (void *) ((tree_view))))),
1290 0, drag_types, G_N_ELEMENTS (drag_types)(sizeof (drag_types) / sizeof ((drag_types)[0])),
1291 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK);
1292
1293 targets = gtk_drag_dest_get_target_list (GTK_WIDGET (tree_view)((((GtkWidget*) (void *) ((tree_view))))));
1294 gtk_target_list_add_text_targets (targets, CAJA_ICON_DND_TEXT);
1295
1296 g_signal_connect_object (tree_view,
1297 "drag_motion",
1298 G_CALLBACK (drag_motion_callback)((GCallback) (drag_motion_callback)),
1299 dest, 0);
1300 g_signal_connect_object (tree_view,
1301 "drag_leave",
1302 G_CALLBACK (drag_leave_callback)((GCallback) (drag_leave_callback)),
1303 dest, 0);
1304 g_signal_connect_object (tree_view,
1305 "drag_drop",
1306 G_CALLBACK (drag_drop_callback)((GCallback) (drag_drop_callback)),
1307 dest, 0);
1308 g_signal_connect_object (tree_view,
1309 "drag_data_received",
1310 G_CALLBACK (drag_data_received_callback)((GCallback) (drag_data_received_callback)),
1311 dest, 0);
1312
1313 return dest;
1314}
diff --git a/2024-07-29-023715-6438-1/report-9708c1.html b/2024-07-29-023715-6438-1/report-9708c1.html new file mode 100644 index 000000000..33972d053 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-9708c1.html @@ -0,0 +1,4916 @@ + + + +eel-canvas.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-canvas.c
Warning:line 580, column 26
Access to field 'next' results in a dereference of a null pointer (loaded from field 'prev')
+ +

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 eel-canvas.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-canvas.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
2/*
3 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
4 * All rights reserved.
5 *
6 * This file is part of the Mate Library.
7 *
8 * The Mate Library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * The Mate 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 the Mate Library; see the file COPYING.LIB. If not,
20 * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23/*
24 @NOTATION@
25 */
26/*
27 * EelCanvas widget - Tk-like canvas widget for Mate
28 *
29 * EelCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
30 * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
31 *
32 *
33 * Authors: Federico Mena <federico@nuclecu.unam.mx>
34 * Raph Levien <raph@gimp.org>
35 */
36
37/*
38 * TO-DO list for the canvas:
39 *
40 * - Allow to specify whether EelCanvasImage sizes are in units or pixels (scale or don't scale).
41 *
42 * - Implement a flag for eel_canvas_item_reparent() that tells the function to keep the item
43 * visually in the same place, that is, to keep it in the same place with respect to the canvas
44 * origin.
45 *
46 * - GC put functions for items.
47 *
48 * - Widget item (finish it).
49 *
50 * - GList *eel_canvas_gimme_all_items_contained_in_this_area (EelCanvas *canvas, Rectangle area);
51 *
52 * - Retrofit all the primitive items with microtile support.
53 *
54 * - Curve support for line item.
55 *
56 * - Arc item (Havoc has it; to be integrated in EelCanvasEllipse).
57 *
58 * - Sane font handling API.
59 *
60 * - Get_arg methods for items:
61 * - How to fetch the outline width and know whether it is in pixels or units?
62 */
63
64#include <config.h>
65
66#include <math.h>
67#include <string.h>
68#include <stdio.h>
69#include <gdk/gdkprivate.h>
70#include <gtk/gtk.h>
71#include <gtk/gtk-a11y.h>
72#include <glib/gi18n-lib.h>
73#include <cairo/cairo-gobject.h>
74#include "eel-canvas.h"
75
76#include "eel-marshal.h"
77
78static void eel_canvas_request_update (EelCanvas *canvas);
79static void group_add (EelCanvasGroup *group,
80 EelCanvasItem *item);
81static void group_remove (EelCanvasGroup *group,
82 EelCanvasItem *item);
83static void redraw_and_repick_if_mapped (EelCanvasItem *item);
84
85/*** EelCanvasItem ***/
86
87/* Some convenience stuff */
88#define GCI_UPDATE_MASK(EEL_CANVAS_UPDATE_REQUESTED | EEL_CANVAS_UPDATE_DEEP) (EEL_CANVAS_UPDATE_REQUESTED | EEL_CANVAS_UPDATE_DEEP)
89
90enum
91{
92 ITEM_PROP_0,
93 ITEM_PROP_PARENT,
94 ITEM_PROP_VISIBLE
95};
96
97enum
98{
99 ITEM_DESTROY,
100 ITEM_EVENT,
101 ITEM_LAST_SIGNAL
102};
103
104static void eel_canvas_item_class_init (EelCanvasItemClass *klass);
105static void eel_canvas_item_init (EelCanvasItem *item);
106static int emit_event (EelCanvas *canvas, GdkEvent *event);
107
108static guint item_signals[ITEM_LAST_SIGNAL] = { 0 };
109
110static GObjectClass *item_parent_class;
111
112static gpointer accessible_item_parent_class;
113static gpointer accessible_parent_class;
114
115
116/**
117 * eel_canvas_item_get_type:
118 *
119 * Registers the &EelCanvasItem class if necessary, and returns the type ID
120 * associated to it.
121 *
122 * Return value: The type ID of the &EelCanvasItem class.
123 **/
124GType
125eel_canvas_item_get_type (void)
126{
127 static GType canvas_item_type = 0;
128
129 if (!canvas_item_type)
130 {
131 static const GTypeInfo canvas_item_info =
132 {
133 sizeof (EelCanvasItemClass),
134 (GBaseInitFunc) NULL((void*)0),
135 (GBaseFinalizeFunc) NULL((void*)0),
136 (GClassInitFunc) eel_canvas_item_class_init,
137 NULL((void*)0), /* class_finalize */
138 NULL((void*)0), /* class_data */
139 sizeof (EelCanvasItem),
140 0, /* n_preallocs */
141 (GInstanceInitFunc) eel_canvas_item_init
142 };
143
144 canvas_item_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED(g_initially_unowned_get_type()),
145 "EelCanvasItem",
146 &canvas_item_info,
147 0);
148 }
149
150 return canvas_item_type;
151}
152
153/* Object initialization function for EelCanvasItem */
154static void
155eel_canvas_item_init (EelCanvasItem *item)
156{
157 item->flags |= EEL_CANVAS_ITEM_VISIBLE;
158}
159
160/**
161 * eel_canvas_item_new:
162 * @parent: The parent group for the new item.
163 * @type: The object type of the item.
164 * @first_arg_name: A list of object argument name/value pairs, NULL-terminated,
165 * used to configure the item. For example, "fill_color", "black",
166 * "width_units", 5.0, NULL.
167 * @Varargs:
168 *
169 * Creates a new canvas item with @parent as its parent group. The item is
170 * created at the top of its parent's stack, and starts up as visible. The item
171 * is of the specified @type, for example, it can be
172 * eel_canvas_rect_get_type(). The list of object arguments/value pairs is
173 * used to configure the item.
174 *
175 * Return value: The newly-created item.
176 **/
177EelCanvasItem *
178eel_canvas_item_new (EelCanvasGroup *parent, GType type, const gchar *first_arg_name, ...)
179{
180 EelCanvasItem *item;
181 va_list args;
182
183 g_return_val_if_fail (EEL_IS_CANVAS_GROUP (parent), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent)); GType __t = ((eel_canvas_group_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (parent)"); return (((void
*)0)); } } while (0)
;
184 g_return_val_if_fail (g_type_is_a (type, eel_canvas_item_get_type ()), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if (((type) == (eel_canvas_item_get_type ()) || (g_type_is_a
) ((type), (eel_canvas_item_get_type ())))) _g_boolean_var_105
= 1; else _g_boolean_var_105 = 0; _g_boolean_var_105; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "g_type_is_a (type, eel_canvas_item_get_type ())"
); return (((void*)0)); } } while (0)
;
185
186 item = EEL_CANVAS_ITEM (g_object_new (type, NULL))((((EelCanvasItem*) (void *) ((g_object_new (type, ((void*)0)
))))))
;
187
188 va_start (args, first_arg_name)__builtin_va_start(args, first_arg_name);
189 eel_canvas_item_construct (item, parent, first_arg_name, args);
190 va_end (args)__builtin_va_end(args);
191
192 return item;
193}
194
195
196/* Performs post-creation operations on a canvas item (adding it to its parent
197 * group, etc.)
198 */
199static void
200item_post_create_setup (EelCanvasItem *item)
201{
202 group_add (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent))))), item);
203
204 redraw_and_repick_if_mapped (item);
205}
206
207/* Set_property handler for canvas items */
208static void
209eel_canvas_item_set_property (GObject *gobject, guint param_id,
210 const GValue *value, GParamSpec *pspec)
211{
212 EelCanvasItem *item;
213
214 g_return_if_fail (EEL_IS_CANVAS_ITEM (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_106
= 1; else _g_boolean_var_106 = 0; _g_boolean_var_106; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (gobject)"); return; } } while
(0)
;
215
216 item = EEL_CANVAS_ITEM (gobject)((((EelCanvasItem*) (void *) ((gobject)))));
217
218 switch (param_id)
219 {
220 case ITEM_PROP_PARENT:
221 if (item->parent != NULL((void*)0))
222 {
223 g_warning ("Cannot set `parent' argument after item has "
224 "already been constructed.");
225 }
226 else if (g_value_get_object (value))
227 {
228 item->parent = EEL_CANVAS_ITEM (g_value_get_object (value))((((EelCanvasItem*) (void *) ((g_value_get_object (value)))))
)
;
229 item->canvas = item->parent->canvas;
230 item_post_create_setup (item);
231 }
232 break;
233 case ITEM_PROP_VISIBLE:
234 if (g_value_get_boolean (value))
235 {
236 eel_canvas_item_show (item);
237 }
238 else
239 {
240 eel_canvas_item_hide (item);
241 }
242 break;
243 default:
244 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 244, ("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)
;
245 break;
246 }
247}
248
249/* Get_property handler for canvas items */
250static void
251eel_canvas_item_get_property (GObject *gobject, guint param_id,
252 GValue *value, GParamSpec *pspec)
253{
254 EelCanvasItem *item;
255
256 g_return_if_fail (EEL_IS_CANVAS_ITEM (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_107
= 1; else _g_boolean_var_107 = 0; _g_boolean_var_107; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (gobject)"); return; } } while
(0)
;
257
258 item = EEL_CANVAS_ITEM (gobject)((((EelCanvasItem*) (void *) ((gobject)))));
259
260 switch (param_id)
261 {
262 case ITEM_PROP_VISIBLE:
263 g_value_set_boolean (value, item->flags & EEL_CANVAS_ITEM_VISIBLE);
264 break;
265 default:
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 266, ("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)
;
267 break;
268 }
269}
270
271/**
272 * eel_canvas_item_construct:
273 * @item: An unconstructed canvas item.
274 * @parent: The parent group for the item.
275 * @first_arg_name: The name of the first argument for configuring the item.
276 * @args: The list of arguments used to configure the item.
277 *
278 * Constructs a canvas item; meant for use only by item implementations.
279 **/
280void
281eel_canvas_item_construct (EelCanvasItem *item, EelCanvasGroup *parent,
282 const gchar *first_arg_name, va_list args)
283{
284 g_return_if_fail (EEL_IS_CANVAS_GROUP (parent))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent)); GType __t = ((eel_canvas_group_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (parent)"); return; } } while
(0)
;
285 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_109
= 1; else _g_boolean_var_109 = 0; _g_boolean_var_109; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
286
287 item->parent = EEL_CANVAS_ITEM (parent)((((EelCanvasItem*) (void *) ((parent)))));
288 item->canvas = item->parent->canvas;
289
290 g_object_set_valist (G_OBJECT (item)((((GObject*) (void *) ((item))))), first_arg_name, args);
291
292 item_post_create_setup (item);
293}
294
295
296static void
297redraw_and_repick_if_mapped (EelCanvasItem *item)
298{
299 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
300 {
301 eel_canvas_item_request_redraw (item);
302 item->canvas->need_repick = TRUE(!(0));
303 }
304}
305
306/* Dispose handler for canvas items */
307static void
308eel_canvas_item_dispose (GObject *object)
309{
310 EelCanvasItem *item;
311
312 g_return_if_fail (EEL_IS_CANVAS_ITEM (object))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_110
= 1; else _g_boolean_var_110 = 0; _g_boolean_var_110; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (object)"); return; } } while
(0)
;
313
314 item = EEL_CANVAS_ITEM (object)((((EelCanvasItem*) (void *) ((object)))));
315
316 if (item->canvas)
317 {
318 eel_canvas_item_request_redraw (item);
319
320 /* Make the canvas forget about us */
321
322 if (item == item->canvas->current_item)
323 {
324 item->canvas->current_item = NULL((void*)0);
325 item->canvas->need_repick = TRUE(!(0));
326 }
327
328 if (item == item->canvas->new_current_item)
329 {
330 item->canvas->new_current_item = NULL((void*)0);
331 item->canvas->need_repick = TRUE(!(0));
332 }
333
334 eel_canvas_item_ungrab (item);
335
336 if (item == item->canvas->focused_item)
337 item->canvas->focused_item = NULL((void*)0);
338
339 /* Normal destroy stuff */
340
341 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
342 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
343
344 if (item->flags & EEL_CANVAS_ITEM_REALIZED)
345 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unrealize) (item);
346
347 if (item->parent)
348 group_remove (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent))))), item);
349
350 item->canvas = NULL((void*)0);
351 }
352
353 g_object_set_data (object, "in-destruction", GINT_TO_POINTER (1)((gpointer) (glong) (1)));
354 g_signal_emit (object, item_signals[ITEM_DESTROY], 0);
355
356 g_object_set_data (object, "in-destruction", NULL((void*)0));
357
358 G_OBJECT_CLASS (item_parent_class)((((GObjectClass*) (void *) ((item_parent_class)))))->dispose (object);
359}
360
361void
362eel_canvas_item_destroy (EelCanvasItem *item)
363{
364 if (g_object_get_data (G_OBJECT (item)((((GObject*) (void *) ((item))))), "in-destruction") == NULL((void*)0)) {
365 g_object_run_dispose (G_OBJECT (item)((((GObject*) (void *) ((item))))));
366 }
367}
368
369/* Realize handler for canvas items */
370static void
371eel_canvas_item_realize (EelCanvasItem *item)
372{
373 if (item->parent && !(item->parent->flags & EEL_CANVAS_ITEM_REALIZED))
374 (* EEL_CANVAS_ITEM_GET_CLASS (item->parent)((((EelCanvasItemClass*) (((GTypeInstance*) ((item->parent
)))->g_class))))
->realize) (item->parent);
375
376 if (item->parent == NULL((void*)0) && !gtk_widget_get_realized (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))))))
377 gtk_widget_realize (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
378
379 item->flags |= EEL_CANVAS_ITEM_REALIZED;
380
381 eel_canvas_item_request_update (item);
382}
383
384/* Unrealize handler for canvas items */
385static void
386eel_canvas_item_unrealize (EelCanvasItem *item)
387{
388 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
389 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
390
391 item->flags &= ~(EEL_CANVAS_ITEM_REALIZED);
392}
393
394/* Map handler for canvas items */
395static void
396eel_canvas_item_map (EelCanvasItem *item)
397{
398 item->flags |= EEL_CANVAS_ITEM_MAPPED;
399}
400
401/* Unmap handler for canvas items */
402static void
403eel_canvas_item_unmap (EelCanvasItem *item)
404{
405 item->flags &= ~(EEL_CANVAS_ITEM_MAPPED);
406}
407
408/* Update handler for canvas items */
409static void
410eel_canvas_item_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags)
411{
412 item->flags &= ~(EEL_CANVAS_ITEM_NEED_UPDATE);
413 item->flags &= ~(EEL_CANVAS_ITEM_NEED_DEEP_UPDATE);
414}
415
416/*
417 * This routine invokes the update method of the item
418 * Please notice, that we take parent to canvas pixel matrix as argument
419 * unlike virtual method ::update, whose argument is item 2 canvas pixel
420 * matrix
421 *
422 * I will try to force somewhat meaningful naming for affines (Lauris)
423 * General naming rule is FROM2TO, where FROM and TO are abbreviations
424 * So p2cpx is Parent2CanvasPixel and i2cpx is Item2CanvasPixel
425 * I hope that this helps to keep track of what really happens
426 *
427 */
428
429static void
430eel_canvas_item_invoke_update (EelCanvasItem *item,
431 double i2w_dx,
432 double i2w_dy,
433 int flags)
434{
435 int child_flags;
436
437 child_flags = flags;
438
439 /* apply object flags to child flags */
440 child_flags &= ~EEL_CANVAS_UPDATE_REQUESTED;
441
442 if (item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)
443 child_flags |= EEL_CANVAS_UPDATE_REQUESTED;
444
445 if (item->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE)
446 child_flags |= EEL_CANVAS_UPDATE_DEEP;
447
448 if (child_flags & GCI_UPDATE_MASK(EEL_CANVAS_UPDATE_REQUESTED | EEL_CANVAS_UPDATE_DEEP))
449 {
450 if (EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->update)
451 EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->update (item, i2w_dx, i2w_dy, child_flags);
452 }
453
454 /* If this fail you probably forgot to chain up to
455 * EelCanvasItem::update from a derived class */
456 g_return_if_fail (!(item->flags & EEL_CANVAS_ITEM_NEED_UPDATE))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if (!(item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)) _g_boolean_var_111
= 1; else _g_boolean_var_111 = 0; _g_boolean_var_111; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "!(item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)"
); return; } } while (0)
;
457}
458
459/*
460 * This routine invokes the point method of the item.
461 * The arguments x, y should be in the parent item local coordinates.
462 */
463
464static double
465eel_canvas_item_invoke_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item)
466{
467 /* Calculate x & y in item local coordinates */
468
469 if (EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->point)
470 return EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->point (item, x, y, cx, cy, actual_item);
471
472 return 1e18;
473}
474
475/**
476 * eel_canvas_item_set:
477 * @item: A canvas item.
478 * @first_arg_name: The list of object argument name/value pairs used to configure the item.
479 * @Varargs:
480 *
481 * Configures a canvas item. The arguments in the item are set to the specified
482 * values, and the item is repainted as appropriate.
483 **/
484void
485eel_canvas_item_set (EelCanvasItem *item, const gchar *first_arg_name, ...)
486{
487 va_list args;
488
489 va_start (args, first_arg_name)__builtin_va_start(args, first_arg_name);
490 eel_canvas_item_set_valist (item, first_arg_name, args);
491 va_end (args)__builtin_va_end(args);
492}
493
494
495/**
496 * eel_canvas_item_set_valist:
497 * @item: A canvas item.
498 * @first_arg_name: The name of the first argument used to configure the item.
499 * @args: The list of object argument name/value pairs used to configure the item.
500 *
501 * Configures a canvas item. The arguments in the item are set to the specified
502 * values, and the item is repainted as appropriate.
503 **/
504void
505eel_canvas_item_set_valist (EelCanvasItem *item, const gchar *first_arg_name, va_list args)
506{
507 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_112
= 1; else _g_boolean_var_112 = 0; _g_boolean_var_112; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
508
509 g_object_set_valist (G_OBJECT (item)((((GObject*) (void *) ((item))))), first_arg_name, args);
510
511 item->canvas->need_repick = TRUE(!(0));
512}
513
514
515/**
516 * eel_canvas_item_move:
517 * @item: A canvas item.
518 * @dx: Horizontal offset.
519 * @dy: Vertical offset.
520 *
521 * Moves a canvas item by creating an affine transformation matrix for
522 * translation by using the specified values. This happens in item
523 * local coordinate system, so if you have nontrivial transform, it
524 * most probably does not do, what you want.
525 **/
526void
527eel_canvas_item_move (EelCanvasItem *item, double dx, double dy)
528{
529 g_return_if_fail (item != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if (item != ((void*)0)) _g_boolean_var_113 = 1; else _g_boolean_var_113
= 0; _g_boolean_var_113; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "item != NULL"); return;
} } while (0)
;
530 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_114
= 1; else _g_boolean_var_114 = 0; _g_boolean_var_114; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
531
532 if (!EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->translate)
533 {
534 g_warning ("Item type %s does not implement translate method.\n",
535 g_type_name (G_OBJECT_TYPE (item)(((((GTypeClass*) (((GTypeInstance*) (item))->g_class))->
g_type)))
));
536 return;
537 }
538
539 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->translate) (item, dx, dy);
540
541 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
542 item->canvas->need_repick = TRUE(!(0));
543
544 if (!(item->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
545 {
546 item->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
547 if (item->parent != NULL((void*)0))
548 eel_canvas_item_request_update (item->parent);
549 else
550 eel_canvas_request_update (item->canvas);
551 }
552
553}
554
555static void
556eel_canvas_queue_resize (EelCanvas *canvas)
557{
558 if (gtk_widget_is_drawable (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas)))))))
559 gtk_widget_queue_resize (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))));
560}
561
562/* Convenience function to reorder items in a group's child list. This puts the
563 * specified link after the "before" link. Returns TRUE if the list was changed.
564 */
565static gboolean
566put_item_after (GList *link, GList *before)
567{
568 EelCanvasGroup *parent;
569
570 if (link
53.1
'link' is not equal to 'before'
== before)
54
Taking false branch
571 return FALSE(0);
572
573 parent = EEL_CANVAS_GROUP (EEL_CANVAS_ITEM (link->data)->parent)((((EelCanvasGroup*) (void *) ((((((EelCanvasItem*) (void *) (
(link->data)))))->parent)))))
;
574
575 if (before
54.1
'before' is equal to NULL
== NULL((void*)0))
55
Taking true branch
576 {
577 if (link == parent->item_list)
56
Assuming 'link' is not equal to field 'item_list'
57
Taking false branch
578 return FALSE(0);
579
580 link->prev->next = link->next;
58
Access to field 'next' results in a dereference of a null pointer (loaded from field 'prev')
581
582 if (link->next)
583 link->next->prev = link->prev;
584 else
585 parent->item_list_end = link->prev;
586
587 link->prev = before;
588 link->next = parent->item_list;
589 link->next->prev = link;
590 parent->item_list = link;
591 }
592 else
593 {
594 if ((link == parent->item_list_end) && (before == parent->item_list_end->prev))
595 return FALSE(0);
596
597 if (link->next)
598 link->next->prev = link->prev;
599
600 if (link->prev)
601 link->prev->next = link->next;
602 else
603 {
604 parent->item_list = link->next;
605 parent->item_list->prev = NULL((void*)0);
606 }
607
608 link->prev = before;
609 link->next = before->next;
610
611 link->prev->next = link;
612
613 if (link->next)
614 link->next->prev = link;
615 else
616 parent->item_list_end = link;
617 }
618 return TRUE(!(0));
619}
620
621
622/**
623 * eel_canvas_item_raise:
624 * @item: A canvas item.
625 * @positions: Number of steps to raise the item.
626 *
627 * Raises the item in its parent's stack by the specified number of positions.
628 * If the number of positions is greater than the distance to the top of the
629 * stack, then the item is put at the top.
630 **/
631void
632eel_canvas_item_raise (EelCanvasItem *item, int positions)
633{
634 GList *link, *before;
635 EelCanvasGroup *parent;
636
637 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_115
= 1; else _g_boolean_var_115 = 0; _g_boolean_var_115; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
638 g_return_if_fail (positions >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if (positions >= 0) _g_boolean_var_116 = 1; else _g_boolean_var_116
= 0; _g_boolean_var_116; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "positions >= 0"); return
; } } while (0)
;
639
640 if (!item->parent || positions == 0)
641 return;
642
643 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
644 link = g_list_find (parent->item_list, item);
645 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if (link != ((void*)0)) _g_boolean_var_117 = 1; else _g_boolean_var_117
= 0; _g_boolean_var_117; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 645, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
646
647 for (before = link; positions && before; positions--)
648 before = before->next;
649
650 if (!before)
651 before = parent->item_list_end;
652
653 if (put_item_after (link, before))
654 {
655 redraw_and_repick_if_mapped (item);
656 }
657}
658
659
660/**
661 * eel_canvas_item_lower:
662 * @item: A canvas item.
663 * @positions: Number of steps to lower the item.
664 *
665 * Lowers the item in its parent's stack by the specified number of positions.
666 * If the number of positions is greater than the distance to the bottom of the
667 * stack, then the item is put at the bottom.
668 **/
669void
670eel_canvas_item_lower (EelCanvasItem *item, int positions)
671{
672 GList *link, *before;
673 EelCanvasGroup *parent;
674
675 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_118
= 1; else _g_boolean_var_118 = 0; _g_boolean_var_118; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
37
Taking false branch
38
Assuming the condition is true
39
Taking true branch
40
Taking true branch
41
Loop condition is false. Exiting loop
676 g_return_if_fail (positions >= 1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if (positions >= 1) _g_boolean_var_119 = 1; else _g_boolean_var_119
= 0; _g_boolean_var_119; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "positions >= 1"); return
; } } while (0)
;
42
Assuming 'positions' is >= 1
43
Taking true branch
44
Taking true branch
677
678 if (!item->parent
45.1
Field 'parent' is non-null
|| positions
45.2
'positions' is not equal to 0
== 0)
45
Loop condition is false. Exiting loop
46
Taking false branch
679 return;
680
681 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
682 link = g_list_find (parent->item_list, item);
683 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (link != ((void*)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120
= 0; _g_boolean_var_120; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 683, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
47
Assuming 'link' is not equal to null
48
Taking true branch
49
Taking true branch
50
Loop condition is false. Exiting loop
684
685 if (link->prev)
51
Assuming field 'prev' is null
52
Taking false branch
686 for (before = link->prev; positions && before; positions--)
687 before = before->prev;
688 else
689 before = NULL((void*)0);
690
691 if (put_item_after (link, before))
53
Calling 'put_item_after'
692 {
693 redraw_and_repick_if_mapped (item);
694 }
695}
696
697
698/**
699 * eel_canvas_item_raise_to_top:
700 * @item: A canvas item.
701 *
702 * Raises an item to the top of its parent's stack.
703 **/
704void
705eel_canvas_item_raise_to_top (EelCanvasItem *item)
706{
707 GList *link;
708 EelCanvasGroup *parent;
709
710 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_121
= 1; else _g_boolean_var_121 = 0; _g_boolean_var_121; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
711
712 if (!item->parent)
713 return;
714
715 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
716 link = g_list_find (parent->item_list, item);
717 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if (link != ((void*)0)) _g_boolean_var_122 = 1; else _g_boolean_var_122
= 0; _g_boolean_var_122; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 717, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
718
719 if (put_item_after (link, parent->item_list_end))
720 {
721 redraw_and_repick_if_mapped (item);
722 }
723}
724
725
726/**
727 * eel_canvas_item_lower_to_bottom:
728 * @item: A canvas item.
729 *
730 * Lowers an item to the bottom of its parent's stack.
731 **/
732void
733eel_canvas_item_lower_to_bottom (EelCanvasItem *item)
734{
735 GList *link;
736 EelCanvasGroup *parent;
737
738 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_123
= 1; else _g_boolean_var_123 = 0; _g_boolean_var_123; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
739
740 if (!item->parent)
741 return;
742
743 parent = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))));
744 link = g_list_find (parent->item_list, item);
745 g_assert (link != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (link != ((void*)0)) _g_boolean_var_124 = 1; else _g_boolean_var_124
= 0; _g_boolean_var_124; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 745, ((const char*) (__func__)), "link != NULL"
); } while (0)
;
746
747 if (put_item_after (link, NULL((void*)0)))
748 {
749 redraw_and_repick_if_mapped (item);
750 }
751}
752
753/**
754 * eel_canvas_item_send_behind:
755 * @item: A canvas item.
756 * @behind_item: The canvas item to put item behind, or NULL
757 *
758 * Moves item to a in the position in the stacking order so that
759 * it is placed immediately below behind_item, or at the top if
760 * behind_item is NULL.
761 **/
762void
763eel_canvas_item_send_behind (EelCanvasItem *item,
764 EelCanvasItem *behind_item)
765{
766 GList *item_list;
767 int item_position, behind_position;
768
769 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_125
= 1; else _g_boolean_var_125 = 0; _g_boolean_var_125; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } 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
770
771 if (behind_item == NULL((void*)0))
8
Assuming 'behind_item' is not equal to NULL
9
Taking false branch
772 {
773 eel_canvas_item_raise_to_top (item);
774 return;
775 }
776
777 g_return_if_fail (EEL_IS_CANVAS_ITEM (behind_item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((behind_item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_126 = 1; else _g_boolean_var_126 =
0; _g_boolean_var_126; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_CANVAS_ITEM (behind_item)"
); 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
778 g_return_if_fail (item->parent == behind_item->parent)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if (item->parent == behind_item->parent) _g_boolean_var_127
= 1; else _g_boolean_var_127 = 0; _g_boolean_var_127; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "item->parent == behind_item->parent"); return
; } } while (0)
;
16
Assuming 'item->parent' is equal to 'behind_item->parent'
17
Taking true branch
18
Taking true branch
19
Loop condition is false. Exiting loop
779
780 item_list = EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))))->item_list;
781
782 item_position = g_list_index (item_list, item);
783 g_assert (item_position != -1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (item_position != -1) _g_boolean_var_128 = 1; else _g_boolean_var_128
= 0; _g_boolean_var_128; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 783, ((const char*) (__func__)), "item_position != -1"
); } while (0)
;
20
Assuming the condition is true
21
Taking true branch
22
Taking true branch
23
Loop condition is false. Exiting loop
784 behind_position = g_list_index (item_list, behind_item);
785 g_assert (behind_position != -1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if (behind_position != -1) _g_boolean_var_129 = 1; else _g_boolean_var_129
= 0; _g_boolean_var_129; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-canvas.c", 785, ((const char*) (__func__)), "behind_position != -1"
); } while (0)
;
24
Assuming the condition is true
25
Taking true branch
26
Taking true branch
27
Loop condition is false. Exiting loop
786 g_assert (item_position != behind_position)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if (item_position != behind_position) _g_boolean_var_130 = 1
; else _g_boolean_var_130 = 0; _g_boolean_var_130; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-canvas.c", 786, ((const
char*) (__func__)), "item_position != behind_position"); } while
(0)
;
28
Assuming 'item_position' is not equal to 'behind_position'
29
Taking true branch
30
Taking true branch
31
Loop condition is false. Exiting loop
787
788 if (item_position == behind_position - 1)
32
Assuming the condition is false
33
Taking false branch
789 {
790 return;
791 }
792
793 if (item_position < behind_position)
34
Assuming 'item_position' is >= 'behind_position'
35
Taking false branch
794 {
795 eel_canvas_item_raise (item, (behind_position - 1) - item_position);
796 }
797 else
798 {
799 eel_canvas_item_lower (item, item_position - behind_position);
36
Calling 'eel_canvas_item_lower'
800 }
801}
802
803/**
804 * eel_canvas_item_show:
805 * @item: A canvas item.
806 *
807 * Shows a canvas item. If the item was already shown, then no action is taken.
808 **/
809void
810eel_canvas_item_show (EelCanvasItem *item)
811{
812 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_131
= 1; else _g_boolean_var_131 = 0; _g_boolean_var_131; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
813
814 if (!(item->flags & EEL_CANVAS_ITEM_VISIBLE))
815 {
816 item->flags |= EEL_CANVAS_ITEM_VISIBLE;
817
818 if (!(item->flags & EEL_CANVAS_ITEM_REALIZED))
819 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->realize) (item);
820
821 if (item->parent != NULL((void*)0))
822 {
823 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED) &&
824 item->parent->flags & EEL_CANVAS_ITEM_MAPPED)
825 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->map) (item);
826 }
827 else
828 {
829 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED) &&
830 gtk_widget_get_mapped (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))))))
831 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->map) (item);
832 }
833
834 redraw_and_repick_if_mapped (item);
835 eel_canvas_queue_resize (item->canvas);
836 }
837}
838
839
840/**
841 * eel_canvas_item_hide:
842 * @item: A canvas item.
843 *
844 * Hides a canvas item. If the item was already hidden, then no action is
845 * taken.
846 **/
847void
848eel_canvas_item_hide (EelCanvasItem *item)
849{
850 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_132
= 1; else _g_boolean_var_132 = 0; _g_boolean_var_132; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
851
852 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
853 {
854 item->flags &= ~EEL_CANVAS_ITEM_VISIBLE;
855
856 redraw_and_repick_if_mapped (item);
857
858 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
859 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
860
861 eel_canvas_queue_resize (item->canvas);
862
863 /* No need to unrealize when we just want to hide */
864 }
865}
866
867/*
868 * Prepare the window for grabbing, i.e. show it.
869 */
870static void
871seat_grab_prepare_window (GdkSeat *seat,
872 GdkWindow *window,
873 gpointer user_data)
874{
875 gdk_window_show (window);
876}
877
878/**
879 * eel_canvas_item_grab:
880 * @item: A canvas item.
881 * @event_mask: Mask of events that will be sent to this item.
882 * @cursor: If non-NULL, the cursor that will be used while the grab is active.
883 * @event: The event, triggering the grab, if any.
884 *
885 * Specifies that all events that match the specified event mask should be sent
886 * to the specified item, and also grabs the seat by calling gdk_seat_grab().
887 * If @cursor is not NULL, then that cursor is used while the grab is active.
888 *
889 * Return value: If an item was already grabbed, it returns %GDK_GRAB_ALREADY_GRABBED. If
890 * the specified item was hidden by calling eel_canvas_item_hide(), then it
891 * returns %GDK_GRAB_NOT_VIEWABLE. Else, it returns the result of calling
892 * gdk_seat_grab().
893 **/
894GdkGrabStatus
895eel_canvas_item_grab (EelCanvasItem *item,
896 GdkEventMask event_mask,
897 GdkCursor *cursor,
898 const GdkEvent *event)
899{
900 GdkGrabStatus retval;
901 GdkDisplay *display;
902 GdkSeat *seat;
903
904 g_return_val_if_fail (EEL_IS_CANVAS_ITEM (item), GDK_GRAB_NOT_VIEWABLE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_133
= 1; else _g_boolean_var_133 = 0; _g_boolean_var_133; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return (GDK_GRAB_NOT_VIEWABLE
); } } while (0)
;
905 g_return_val_if_fail (gtk_widget_get_mapped (GTK_WIDGET (item->canvas)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (gtk_widget_get_mapped (((((GtkWidget*) (void *) ((item->
canvas))))))) _g_boolean_var_134 = 1; else _g_boolean_var_134
= 0; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "gtk_widget_get_mapped (GTK_WIDGET (item->canvas))"
); return (GDK_GRAB_NOT_VIEWABLE); } } while (0)
906 GDK_GRAB_NOT_VIEWABLE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (gtk_widget_get_mapped (((((GtkWidget*) (void *) ((item->
canvas))))))) _g_boolean_var_134 = 1; else _g_boolean_var_134
= 0; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "gtk_widget_get_mapped (GTK_WIDGET (item->canvas))"
); return (GDK_GRAB_NOT_VIEWABLE); } } while (0)
;
907
908 if (item->canvas->grabbed_item)
909 return GDK_GRAB_ALREADY_GRABBED;
910
911 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED))
912 return GDK_GRAB_NOT_VIEWABLE;
913
914 display = gtk_widget_get_display (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
915 seat = gdk_display_get_default_seat (display);
916
917 retval = gdk_seat_grab (seat,
918 gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)((((GtkLayout*) (void *) ((item->canvas)))))),
919 GDK_SEAT_CAPABILITY_ALL_POINTING,
920 FALSE(0),
921 cursor,
922 event,
923 seat_grab_prepare_window,
924 NULL((void*)0));
925
926 if (retval != GDK_GRAB_SUCCESS)
927 return retval;
928
929 item->canvas->grabbed_item = item;
930 item->canvas->grabbed_event_mask = event_mask;
931 item->canvas->current_item = item; /* So that events go to the grabbed item */
932
933 return retval;
934}
935
936/**
937 * eel_canvas_item_ungrab:
938 * @item: A canvas item that holds a grab.
939 *
940 * Ungrabs the item, which must have been grabbed in the canvas, and ungrabs the
941 * seat.
942 **/
943void
944eel_canvas_item_ungrab (EelCanvasItem *item)
945{
946 GdkDisplay *display;
947 GdkSeat *seat;
948
949 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_135
= 1; else _g_boolean_var_135 = 0; _g_boolean_var_135; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
950
951 if (item->canvas->grabbed_item != item)
952 return;
953
954 display = gtk_widget_get_display (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
955 seat = gdk_display_get_default_seat (display);
956
957 item->canvas->grabbed_item = NULL((void*)0);
958 gdk_seat_ungrab (seat);
959}
960
961/**
962 * eel_canvas_item_w2i:
963 * @item: A canvas item.
964 * @x: X coordinate to convert (input/output value).
965 * @y: Y coordinate to convert (input/output value).
966 *
967 * Converts a coordinate pair from world coordinates to item-relative
968 * coordinates.
969 **/
970void
971eel_canvas_item_w2i (EelCanvasItem *item, double *x, double *y)
972{
973 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_136
= 1; else _g_boolean_var_136 = 0; _g_boolean_var_136; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
974 g_return_if_fail (x != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if (x != ((void*)0)) _g_boolean_var_137 = 1; else _g_boolean_var_137
= 0; _g_boolean_var_137; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "x != NULL"); return; } }
while (0)
;
975 g_return_if_fail (y != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if (y != ((void*)0)) _g_boolean_var_138 = 1; else _g_boolean_var_138
= 0; _g_boolean_var_138; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "y != NULL"); return; } }
while (0)
;
976
977 item = item->parent;
978 while (item)
979 {
980 if (EEL_IS_CANVAS_GROUP (item)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(item)); GType __t = ((eel_canvas_group_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; }))))
)
981 {
982 *x -= EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->xpos;
983 *y -= EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->ypos;
984 }
985
986 item = item->parent;
987 }
988}
989
990
991/**
992 * eel_canvas_item_i2w:
993 * @item: A canvas item.
994 * @x: X coordinate to convert (input/output value).
995 * @y: Y coordinate to convert (input/output value).
996 *
997 * Converts a coordinate pair from item-relative coordinates to world
998 * coordinates.
999 **/
1000void
1001eel_canvas_item_i2w (EelCanvasItem *item, double *x, double *y)
1002{
1003 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_139
= 1; else _g_boolean_var_139 = 0; _g_boolean_var_139; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1004 g_return_if_fail (x != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (x != ((void*)0)) _g_boolean_var_140 = 1; else _g_boolean_var_140
= 0; _g_boolean_var_140; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "x != NULL"); return; } }
while (0)
;
1005 g_return_if_fail (y != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (y != ((void*)0)) _g_boolean_var_141 = 1; else _g_boolean_var_141
= 0; _g_boolean_var_141; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "y != NULL"); return; } }
while (0)
;
1006
1007 item = item->parent;
1008 while (item)
1009 {
1010 if (EEL_IS_CANVAS_GROUP (item)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(item)); GType __t = ((eel_canvas_group_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; }))))
)
1011 {
1012 *x += EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->xpos;
1013 *y += EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))))->ypos;
1014 }
1015
1016 item = item->parent;
1017 }
1018}
1019
1020/* Returns whether the item is an inferior of or is equal to the parent. */
1021static int
1022is_descendant (EelCanvasItem *item, EelCanvasItem *parent)
1023{
1024 for (; item; item = item->parent)
1025 if (item == parent)
1026 return TRUE(!(0));
1027
1028 return FALSE(0);
1029}
1030
1031/**
1032 * eel_canvas_item_reparent:
1033 * @item: A canvas item.
1034 * @new_group: A canvas group.
1035 *
1036 * Changes the parent of the specified item to be the new group. The item keeps
1037 * its group-relative coordinates as for its old parent, so the item may change
1038 * its absolute position within the canvas.
1039 **/
1040void
1041eel_canvas_item_reparent (EelCanvasItem *item, EelCanvasGroup *new_group)
1042{
1043 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_142
= 1; else _g_boolean_var_142 = 0; _g_boolean_var_142; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1044 g_return_if_fail (EEL_IS_CANVAS_GROUP (new_group))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_group)); GType __t = ((eel_canvas_group_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
("Eel", ((const char*) (__func__)), "EEL_IS_CANVAS_GROUP (new_group)"
); return; } } while (0)
;
1045
1046 /* Both items need to be in the same canvas */
1047 g_return_if_fail (item->canvas == EEL_CANVAS_ITEM (new_group)->canvas)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if (item->canvas == ((((EelCanvasItem*) (void *) ((new_group
)))))->canvas) _g_boolean_var_144 = 1; else _g_boolean_var_144
= 0; _g_boolean_var_144; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "item->canvas == EEL_CANVAS_ITEM (new_group)->canvas"
); return; } } while (0)
;
1048
1049 /* The group cannot be an inferior of the item or be the item itself --
1050 * this also takes care of the case where the item is the root item of
1051 * the canvas. */
1052 g_return_if_fail (!is_descendant (EEL_CANVAS_ITEM (new_group), item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if (!is_descendant (((((EelCanvasItem*) (void *) ((new_group
))))), item)) _g_boolean_var_145 = 1; else _g_boolean_var_145
= 0; _g_boolean_var_145; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "!is_descendant (EEL_CANVAS_ITEM (new_group), item)"
); return; } } while (0)
;
1053
1054 /* Everything is ok, now actually reparent the item */
1055
1056 g_object_ref (G_OBJECT (item))((__typeof__ (((((GObject*) (void *) ((item))))))) (g_object_ref
) (((((GObject*) (void *) ((item)))))))
; /* protect it from the unref in group_remove */
1057
1058 eel_canvas_item_request_redraw (item);
1059
1060 group_remove (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent))))), item);
1061 item->parent = EEL_CANVAS_ITEM (new_group)((((EelCanvasItem*) (void *) ((new_group)))));
1062 /* item->canvas is unchanged. */
1063 group_add (new_group, item);
1064
1065 /* Redraw and repick */
1066
1067 redraw_and_repick_if_mapped (item);
1068
1069 g_object_unref (G_OBJECT (item)((((GObject*) (void *) ((item))))));
1070}
1071
1072/**
1073 * eel_canvas_item_grab_focus:
1074 * @item: A canvas item.
1075 *
1076 * Makes the specified item take the keyboard focus, so all keyboard events will
1077 * be sent to it. If the canvas widget itself did not have the focus, it grabs
1078 * it as well.
1079 **/
1080void
1081eel_canvas_item_grab_focus (EelCanvasItem *item)
1082{
1083 EelCanvasItem *focused_item;
1084 GdkEvent ev;
1085
1086 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_146
= 1; else _g_boolean_var_146 = 0; _g_boolean_var_146; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1087 g_return_if_fail (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas)))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if (gtk_widget_get_can_focus (((((GtkWidget*) (void *) ((item
->canvas))))))) _g_boolean_var_147 = 1; else _g_boolean_var_147
= 0; _g_boolean_var_147; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "gtk_widget_get_can_focus (GTK_WIDGET (item->canvas))"
); return; } } while (0)
;
1088
1089 focused_item = item->canvas->focused_item;
1090
1091 if (focused_item)
1092 {
1093 ev.focus_change.type = GDK_FOCUS_CHANGE;
1094 ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)((((GtkLayout*) (void *) ((item->canvas))))));
1095 ev.focus_change.send_event = FALSE(0);
1096 ev.focus_change.in = FALSE(0);
1097
1098 emit_event (item->canvas, &ev);
1099 }
1100
1101 item->canvas->focused_item = item;
1102 gtk_widget_grab_focus (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
1103
1104 if (focused_item)
1105 {
1106 ev.focus_change.type = GDK_FOCUS_CHANGE;
1107 ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)((((GtkLayout*) (void *) ((item->canvas))))));
1108 ev.focus_change.send_event = FALSE(0);
1109 ev.focus_change.in = TRUE(!(0));
1110
1111 emit_event (item->canvas, &ev);
1112 }
1113}
1114
1115
1116/**
1117 * eel_canvas_item_get_bounds:
1118 * @item: A canvas item.
1119 * @x1: Leftmost edge of the bounding box (return value).
1120 * @y1: Upper edge of the bounding box (return value).
1121 * @x2: Rightmost edge of the bounding box (return value).
1122 * @y2: Lower edge of the bounding box (return value).
1123 *
1124 * Queries the bounding box of a canvas item. The bounds are returned in the
1125 * coordinate system of the item's parent.
1126 **/
1127void
1128eel_canvas_item_get_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
1129{
1130 double tx1, ty1, tx2, ty2;
1131
1132 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_148
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_148
= 1; else _g_boolean_var_148 = 0; _g_boolean_var_148; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1133
1134 tx1 = ty1 = tx2 = ty2 = 0.0;
1135
1136 /* Get the item's bounds in its coordinate system */
1137
1138 if (EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->bounds)
1139 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->bounds) (item, &tx1, &ty1, &tx2, &ty2);
1140
1141 /* Return the values */
1142
1143 if (x1)
1144 *x1 = tx1;
1145
1146 if (y1)
1147 *y1 = ty1;
1148
1149 if (x2)
1150 *x2 = tx2;
1151
1152 if (y2)
1153 *y2 = ty2;
1154}
1155
1156
1157/**
1158 * eel_canvas_item_request_update
1159 * @item: A canvas item.
1160 *
1161 * To be used only by item implementations. Requests that the canvas queue an
1162 * update for the specified item.
1163 **/
1164void
1165eel_canvas_item_request_update (EelCanvasItem *item)
1166{
1167 if (NULL((void*)0) == item->canvas)
1168 return;
1169
1170 g_return_if_fail (!item->canvas->doing_update)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if (!item->canvas->doing_update) _g_boolean_var_149 =
1; else _g_boolean_var_149 = 0; _g_boolean_var_149; }), 1)))
{ } else { g_return_if_fail_warning ("Eel", ((const char*) (
__func__)), "!item->canvas->doing_update"); return; } }
while (0)
;
1171
1172 if (item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)
1173 return;
1174
1175 item->flags |= EEL_CANVAS_ITEM_NEED_UPDATE;
1176
1177 if (item->parent != NULL((void*)0))
1178 {
1179 /* Recurse up the tree */
1180 eel_canvas_item_request_update (item->parent);
1181 }
1182 else
1183 {
1184 /* Have reached the top of the tree, make sure the update call gets scheduled. */
1185 eel_canvas_request_update (item->canvas);
1186 }
1187}
1188
1189/**
1190 * eel_canvas_item_request_update
1191 * @item: A canvas item.
1192 *
1193 * Convenience function that informs a canvas that the specified item needs
1194 * to be repainted. To be used by item implementations
1195 **/
1196void
1197eel_canvas_item_request_redraw (EelCanvasItem *item)
1198{
1199 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
1200 eel_canvas_request_redraw (item->canvas,
1201 item->x1, item->y1,
1202 item->x2 + 1, item->y2 + 1);
1203}
1204
1205
1206
1207/*** EelCanvasGroup ***/
1208
1209
1210enum
1211{
1212 GROUP_PROP_0,
1213 GROUP_PROP_X,
1214 GROUP_PROP_Y
1215};
1216
1217
1218static void eel_canvas_group_class_init (EelCanvasGroupClass *klass);
1219static void eel_canvas_group_init (EelCanvasGroup *group);
1220static void eel_canvas_group_set_property(GObject *object,
1221 guint param_id,
1222 const GValue *value,
1223 GParamSpec *pspec);
1224static void eel_canvas_group_get_property(GObject *object,
1225 guint param_id,
1226 GValue *value,
1227 GParamSpec *pspec);
1228
1229static void eel_canvas_group_destroy (EelCanvasItem *object);
1230
1231static void eel_canvas_group_update (EelCanvasItem *item,
1232 double i2w_dx,
1233 double i2w_dy,
1234 int flags);
1235static void eel_canvas_group_unrealize (EelCanvasItem *item);
1236static void eel_canvas_group_map (EelCanvasItem *item);
1237static void eel_canvas_group_unmap (EelCanvasItem *item);
1238static void eel_canvas_group_draw (EelCanvasItem *item,
1239 cairo_t *cr,
1240 cairo_region_t *region);
1241static double eel_canvas_group_point (EelCanvasItem *item, double x, double y,
1242 int cx, int cy,
1243 EelCanvasItem **actual_item);
1244static void eel_canvas_group_translate (EelCanvasItem *item, double dx, double dy);
1245static void eel_canvas_group_bounds (EelCanvasItem *item, double *x1, double *y1,
1246 double *x2, double *y2);
1247
1248
1249static EelCanvasItemClass *group_parent_class;
1250
1251
1252/**
1253 * eel_canvas_group_get_type:
1254 *
1255 * Registers the &EelCanvasGroup class if necessary, and returns the type ID
1256 * associated to it.
1257 *
1258 * Return value: The type ID of the &EelCanvasGroup class.
1259 **/
1260GType
1261eel_canvas_group_get_type (void)
1262{
1263 static GType group_type = 0;
1264
1265 if (!group_type)
1266 {
1267 static const GTypeInfo group_info =
1268 {
1269 sizeof (EelCanvasGroupClass),
1270 (GBaseInitFunc) NULL((void*)0),
1271 (GBaseFinalizeFunc) NULL((void*)0),
1272 (GClassInitFunc) eel_canvas_group_class_init,
1273 NULL((void*)0), /* class_finalize */
1274 NULL((void*)0), /* class_data */
1275 sizeof (EelCanvasGroup),
1276 0, /* n_preallocs */
1277 (GInstanceInitFunc) eel_canvas_group_init
1278
1279
1280 };
1281
1282 group_type = g_type_register_static (eel_canvas_item_get_type (),
1283 "EelCanvasGroup",
1284 &group_info,
1285 0);
1286 }
1287
1288 return group_type;
1289}
1290
1291/* Class initialization function for EelCanvasGroupClass */
1292static void
1293eel_canvas_group_class_init (EelCanvasGroupClass *klass)
1294{
1295 GObjectClass *gobject_class;
1296 EelCanvasItemClass *item_class;
1297
1298 gobject_class = (GObjectClass *) klass;
1299 item_class = (EelCanvasItemClass *) klass;
1300
1301 group_parent_class = g_type_class_peek_parent (klass);
1302
1303 gobject_class->set_property = eel_canvas_group_set_property;
1304 gobject_class->get_property = eel_canvas_group_get_property;
1305
1306 g_object_class_install_property
1307 (gobject_class, GROUP_PROP_X,
1308 g_param_spec_double ("x",
1309 _("X")((char *) g_dgettext ("caja", "X")),
1310 _("X")((char *) g_dgettext ("caja", "X")),
1311 -G_MAXDOUBLE1.7976931348623157e+308, G_MAXDOUBLE1.7976931348623157e+308, 0.0,
1312 G_PARAM_READWRITE));
1313 g_object_class_install_property
1314 (gobject_class, GROUP_PROP_Y,
1315 g_param_spec_double ("y",
1316 _("Y")((char *) g_dgettext ("caja", "Y")),
1317 _("Y")((char *) g_dgettext ("caja", "Y")),
1318 -G_MAXDOUBLE1.7976931348623157e+308, G_MAXDOUBLE1.7976931348623157e+308, 0.0,
1319 G_PARAM_READWRITE));
1320
1321 item_class->destroy = eel_canvas_group_destroy;
1322 item_class->update = eel_canvas_group_update;
1323 item_class->unrealize = eel_canvas_group_unrealize;
1324 item_class->map = eel_canvas_group_map;
1325 item_class->unmap = eel_canvas_group_unmap;
1326 item_class->draw = eel_canvas_group_draw;
1327 item_class->point = eel_canvas_group_point;
1328 item_class->translate = eel_canvas_group_translate;
1329 item_class->bounds = eel_canvas_group_bounds;
1330}
1331
1332/* Object initialization function for EelCanvasGroup */
1333static void
1334eel_canvas_group_init (EelCanvasGroup *group)
1335{
1336 group->xpos = 0.0;
1337 group->ypos = 0.0;
1338}
1339
1340/* Set_property handler for canvas groups */
1341static void
1342eel_canvas_group_set_property (GObject *gobject, guint param_id,
1343 const GValue *value, GParamSpec *pspec)
1344{
1345 EelCanvasItem *item;
1346 EelCanvasGroup *group;
1347 double old;
1348 gboolean moved;
1349
1350 g_return_if_fail (EEL_IS_CANVAS_GROUP (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_group_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_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1))) { } else { g_return_if_fail_warning ("Eel", ((const
char*) (__func__)), "EEL_IS_CANVAS_GROUP (gobject)"); return
; } } while (0)
;
1351
1352 item = EEL_CANVAS_ITEM (gobject)((((EelCanvasItem*) (void *) ((gobject)))));
1353 group = EEL_CANVAS_GROUP (gobject)((((EelCanvasGroup*) (void *) ((gobject)))));
1354
1355 moved = FALSE(0);
1356 switch (param_id)
1357 {
1358 case GROUP_PROP_X:
1359 old = group->xpos;
1360 group->xpos = g_value_get_double (value);
1361 if (old != group->xpos)
1362 moved = TRUE(!(0));
1363 break;
1364
1365 case GROUP_PROP_Y:
1366 old = group->ypos;
1367 group->ypos = g_value_get_double (value);
1368 if (old != group->ypos)
1369 moved = TRUE(!(0));
1370 break;
1371
1372 default:
1373 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 1373, ("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)
;
1374 break;
1375 }
1376
1377 if (moved)
1378 {
1379 item->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
1380 if (item->parent != NULL((void*)0))
1381 eel_canvas_item_request_update (item->parent);
1382 else
1383 eel_canvas_request_update (item->canvas);
1384 }
1385}
1386
1387/* Get_property handler for canvas groups */
1388static void
1389eel_canvas_group_get_property (GObject *gobject, guint param_id,
1390 GValue *value, GParamSpec *pspec)
1391{
1392 EelCanvasGroup *group;
1393
1394 g_return_if_fail (EEL_IS_CANVAS_GROUP (gobject))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((gobject)); GType __t = ((eel_canvas_group_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_151 = 1; else _g_boolean_var_151 = 0; _g_boolean_var_151
; }), 1))) { } else { g_return_if_fail_warning ("Eel", ((const
char*) (__func__)), "EEL_IS_CANVAS_GROUP (gobject)"); return
; } } while (0)
;
1395
1396 group = EEL_CANVAS_GROUP (gobject)((((EelCanvasGroup*) (void *) ((gobject)))));
1397
1398 switch (param_id)
1399 {
1400 case GROUP_PROP_X:
1401 g_value_set_double (value, group->xpos);
1402 break;
1403
1404 case GROUP_PROP_Y:
1405 g_value_set_double (value, group->ypos);
1406 break;
1407
1408 default:
1409 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec)do { GObject *_glib__object = (GObject*) ((gobject)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "eel-canvas.c", 1409, ("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)
;
1410 break;
1411 }
1412}
1413
1414/* Destroy handler for canvas groups */
1415static void
1416eel_canvas_group_destroy (EelCanvasItem *object)
1417{
1418 EelCanvasGroup *group;
1419 GList *list;
1420 EelCanvasItem *child = NULL((void*)0);
1421
1422 g_return_if_fail (EEL_IS_CANVAS_GROUP (object))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eel_canvas_group_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_152
= 1; else _g_boolean_var_152 = 0; _g_boolean_var_152; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (object)"); return; } } while
(0)
;
1423
1424 group = EEL_CANVAS_GROUP (object)((((EelCanvasGroup*) (void *) ((object)))));
1425
1426 list = group->item_list;
1427 while (list)
1428 {
1429 child = list->data;
1430 list = list->next;
1431
1432 eel_canvas_item_destroy (child);
1433 }
1434
1435 if (EEL_CANVAS_ITEM_CLASS (group_parent_class)((((EelCanvasItemClass*) (void *) ((group_parent_class)))))->destroy)
1436 (* EEL_CANVAS_ITEM_CLASS (group_parent_class)((((EelCanvasItemClass*) (void *) ((group_parent_class)))))->destroy) (object);
1437}
1438
1439/* Update handler for canvas groups */
1440static void
1441eel_canvas_group_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags)
1442{
1443 EelCanvasGroup *group;
1444 GList *list;
1445 EelCanvasItem *i;
1446 double bbox_x0, bbox_y0, bbox_x1, bbox_y1;
1447 gboolean first = TRUE(!(0));
1448
1449 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1450
1451 (* group_parent_class->update) (item, i2w_dx, i2w_dy, flags);
1452
1453 bbox_x0 = 0;
1454 bbox_y0 = 0;
1455 bbox_x1 = 0;
1456 bbox_y1 = 0;
1457
1458 for (list = group->item_list; list; list = list->next)
1459 {
1460 i = list->data;
1461
1462 eel_canvas_item_invoke_update (i, i2w_dx + group->xpos, i2w_dy + group->ypos, flags);
1463
1464 if (first)
1465 {
1466 first = FALSE(0);
1467 bbox_x0 = i->x1;
1468 bbox_y0 = i->y1;
1469 bbox_x1 = i->x2;
1470 bbox_y1 = i->y2;
1471 }
1472 else
1473 {
1474 bbox_x0 = MIN (bbox_x0, i->x1)(((bbox_x0) < (i->x1)) ? (bbox_x0) : (i->x1));
1475 bbox_y0 = MIN (bbox_y0, i->y1)(((bbox_y0) < (i->y1)) ? (bbox_y0) : (i->y1));
1476 bbox_x1 = MAX (bbox_x1, i->x2)(((bbox_x1) > (i->x2)) ? (bbox_x1) : (i->x2));
1477 bbox_y1 = MAX (bbox_y1, i->y2)(((bbox_y1) > (i->y2)) ? (bbox_y1) : (i->y2));
1478 }
1479 }
1480 item->x1 = bbox_x0;
1481 item->y1 = bbox_y0;
1482 item->x2 = bbox_x1;
1483 item->y2 = bbox_y1;
1484}
1485
1486/* Unrealize handler for canvas groups */
1487static void
1488eel_canvas_group_unrealize (EelCanvasItem *item)
1489{
1490 EelCanvasGroup *group;
1491 GList *list;
1492 EelCanvasItem *i = NULL((void*)0);
1493
1494 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1495
1496 /* Unmap group before children to avoid flash */
1497 if (item->flags & EEL_CANVAS_ITEM_MAPPED)
1498 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
1499
1500 for (list = group->item_list; list; list = list->next)
1501 {
1502 i = list->data;
1503
1504 if (i->flags & EEL_CANVAS_ITEM_REALIZED)
1505 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->unrealize) (i);
1506 }
1507
1508 (* group_parent_class->unrealize) (item);
1509}
1510
1511/* Map handler for canvas groups */
1512static void
1513eel_canvas_group_map (EelCanvasItem *item)
1514{
1515 EelCanvasGroup *group;
1516 GList *list;
1517 EelCanvasItem *i = NULL((void*)0);
1518
1519 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1520
1521 for (list = group->item_list; list; list = list->next)
1522 {
1523 i = list->data;
1524
1525 if (i->flags & EEL_CANVAS_ITEM_VISIBLE &&
1526 !(i->flags & EEL_CANVAS_ITEM_MAPPED))
1527 {
1528 if (!(i->flags & EEL_CANVAS_ITEM_REALIZED))
1529 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->realize) (i);
1530
1531 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->map) (i);
1532 }
1533 }
1534
1535 (* group_parent_class->map) (item);
1536}
1537
1538/* Unmap handler for canvas groups */
1539static void
1540eel_canvas_group_unmap (EelCanvasItem *item)
1541{
1542 EelCanvasGroup *group;
1543 GList *list;
1544 EelCanvasItem *i = NULL((void*)0);
1545
1546 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1547
1548 for (list = group->item_list; list; list = list->next)
1549 {
1550 i = list->data;
1551
1552 if (i->flags & EEL_CANVAS_ITEM_MAPPED)
1553 (* EEL_CANVAS_ITEM_GET_CLASS (i)((((EelCanvasItemClass*) (((GTypeInstance*) ((i)))->g_class
))))
->unmap) (i);
1554 }
1555
1556 (* group_parent_class->unmap) (item);
1557}
1558
1559/* Draw handler for canvas groups */
1560static void
1561eel_canvas_group_draw (EelCanvasItem *item,
1562 cairo_t *cr,
1563 cairo_region_t *region)
1564{
1565 EelCanvasGroup *group;
1566 GList *list;
1567 EelCanvasItem *child = NULL((void*)0);
1568
1569 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1570
1571 for (list = group->item_list; list; list = list->next)
1572 {
1573 child = list->data;
1574
1575 if ((child->flags & EEL_CANVAS_ITEM_MAPPED) &&
1576 (EEL_CANVAS_ITEM_GET_CLASS (child)((((EelCanvasItemClass*) (((GTypeInstance*) ((child)))->g_class
))))
->draw))
1577 {
1578 GdkRectangle child_rect;
1579
1580 child_rect.x = child->x1;
1581 child_rect.y = child->y1;
1582 child_rect.width = child->x2 - child->x1 + 1;
1583 child_rect.height = child->y2 - child->y1 + 1;
1584
1585 if (cairo_region_contains_rectangle (region, &child_rect) != CAIRO_REGION_OVERLAP_OUT)
1586 EEL_CANVAS_ITEM_GET_CLASS (child)((((EelCanvasItemClass*) (((GTypeInstance*) ((child)))->g_class
))))
->draw (child, cr, region);
1587 }
1588 }
1589}
1590
1591/* Point handler for canvas groups */
1592static double
1593eel_canvas_group_point (EelCanvasItem *item, double x, double y, int cx, int cy,
1594 EelCanvasItem **actual_item)
1595{
1596 int x1, y1, x2, y2;
1597 double gx, gy;
1598 double dist, best;
1599 int has_point;
1600 EelCanvasGroup *group;
1601 GList *list;
1602 EelCanvasItem *point_item;
1603 EelCanvasItem *child = NULL((void*)0);
1604
1605 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1606
1607 x1 = cx - item->canvas->close_enough;
1608 y1 = cy - item->canvas->close_enough;
1609 x2 = cx + item->canvas->close_enough;
1610 y2 = cy + item->canvas->close_enough;
1611
1612 best = 0.0;
1613 *actual_item = NULL((void*)0);
1614
1615 gx = x - group->xpos;
1616 gy = y - group->ypos;
1617
1618 dist = 0.0; /* keep gcc happy */
1619
1620 for (list = group->item_list; list; list = list->next)
1621 {
1622 child = list->data;
1623
1624 if ((child->x1 > x2) || (child->y1 > y2) || (child->x2 < x1) || (child->y2 < y1))
1625 continue;
1626
1627 point_item = NULL((void*)0); /* cater for incomplete item implementations */
1628
1629 if ((child->flags & EEL_CANVAS_ITEM_MAPPED)
1630 && EEL_CANVAS_ITEM_GET_CLASS (child)((((EelCanvasItemClass*) (((GTypeInstance*) ((child)))->g_class
))))
->point)
1631 {
1632 dist = eel_canvas_item_invoke_point (child, gx, gy, cx, cy, &point_item);
1633 has_point = TRUE(!(0));
1634 }
1635 else
1636 has_point = FALSE(0);
1637
1638 if (has_point
1639 && point_item
1640 && ((int) (dist * item->canvas->pixels_per_unit + 0.5)
1641 <= item->canvas->close_enough))
1642 {
1643 best = dist;
1644 *actual_item = point_item;
1645 }
1646 }
1647
1648 return best;
1649}
1650
1651void
1652eel_canvas_group_translate (EelCanvasItem *item, double dx, double dy)
1653{
1654 EelCanvasGroup *group;
1655
1656 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1657
1658 group->xpos += dx;
1659 group->ypos += dy;
1660}
1661
1662/* Bounds handler for canvas groups */
1663static void
1664eel_canvas_group_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
1665{
1666 EelCanvasGroup *group;
1667 EelCanvasItem *child;
1668 GList *list;
1669 double tx1, ty1, tx2, ty2;
1670 double minx, miny, maxx, maxy;
1671 int set;
1672
1673 group = EEL_CANVAS_GROUP (item)((((EelCanvasGroup*) (void *) ((item)))));
1674
1675 /* Get the bounds of the first visible item */
1676
1677 child = NULL((void*)0); /* Unnecessary but eliminates a warning. */
1678
1679 set = FALSE(0);
1680
1681 for (list = group->item_list; list; list = list->next)
1682 {
1683 child = list->data;
1684
1685 if (child->flags & EEL_CANVAS_ITEM_MAPPED)
1686 {
1687 set = TRUE(!(0));
1688 eel_canvas_item_get_bounds (child, &minx, &miny, &maxx, &maxy);
1689 break;
1690 }
1691 }
1692
1693 /* If there were no visible items, return an empty bounding box */
1694
1695 if (!set)
1696 {
1697 *x1 = *y1 = *x2 = *y2 = 0.0;
1698 return;
1699 }
1700
1701 /* Now we can grow the bounds using the rest of the items */
1702
1703 list = list->next;
1704
1705 for (; list; list = list->next)
1706 {
1707 child = list->data;
1708
1709 if (!(child->flags & EEL_CANVAS_ITEM_MAPPED))
1710 continue;
1711
1712 eel_canvas_item_get_bounds (child, &tx1, &ty1, &tx2, &ty2);
1713
1714 if (tx1 < minx)
1715 minx = tx1;
1716
1717 if (ty1 < miny)
1718 miny = ty1;
1719
1720 if (tx2 > maxx)
1721 maxx = tx2;
1722
1723 if (ty2 > maxy)
1724 maxy = ty2;
1725 }
1726
1727 /* Make the bounds be relative to our parent's coordinate system */
1728
1729 if (item->parent)
1730 {
1731 minx += group->xpos;
1732 miny += group->ypos;
1733 maxx += group->xpos;
1734 maxy += group->ypos;
1735 }
1736
1737 *x1 = minx;
1738 *y1 = miny;
1739 *x2 = maxx;
1740 *y2 = maxy;
1741}
1742
1743/* Adds an item to a group */
1744static void
1745group_add (EelCanvasGroup *group, EelCanvasItem *item)
1746{
1747 g_object_ref_sink (item)((__typeof__ (item)) (g_object_ref_sink) (item));
1748
1749 if (!group->item_list)
1750 {
1751 group->item_list = g_list_append (group->item_list, item);
1752 group->item_list_end = group->item_list;
1753 }
1754 else
1755 group->item_list_end = g_list_append (group->item_list_end, item)->next;
1756
1757 if (item->flags & EEL_CANVAS_ITEM_VISIBLE &&
1758 group->item.flags & EEL_CANVAS_ITEM_MAPPED)
1759 {
1760 if (!(item->flags & EEL_CANVAS_ITEM_REALIZED))
1761 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->realize) (item);
1762
1763 if (!(item->flags & EEL_CANVAS_ITEM_MAPPED))
1764 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->map) (item);
1765 }
1766
1767 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
1768 eel_canvas_queue_resize (EEL_CANVAS_ITEM (group)((((EelCanvasItem*) (void *) ((group)))))->canvas);
1769}
1770
1771/* Removes an item from a group */
1772static void
1773group_remove (EelCanvasGroup *group, EelCanvasItem *item)
1774{
1775 GList *children;
1776
1777 g_return_if_fail (EEL_IS_CANVAS_GROUP (group))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((group)); GType __t = ((eel_canvas_group_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_153
= 1; else _g_boolean_var_153 = 0; _g_boolean_var_153; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_GROUP (group)"); return; } } while
(0)
;
1778 g_return_if_fail (EEL_IS_CANVAS_ITEM (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = ((eel_canvas_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; }))))) _g_boolean_var_154
= 1; else _g_boolean_var_154 = 0; _g_boolean_var_154; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS_ITEM (item)"); return; } } while
(0)
;
1779
1780 for (children = group->item_list; children; children = children->next)
1781 if (children->data == item)
1782 {
1783 if (item->flags & EEL_CANVAS_ITEM_MAPPED) {
1784 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unmap) (item);
1785 }
1786
1787 if (item->flags & EEL_CANVAS_ITEM_REALIZED)
1788 (* EEL_CANVAS_ITEM_GET_CLASS (item)((((EelCanvasItemClass*) (((GTypeInstance*) ((item)))->g_class
))))
->unrealize) (item);
1789
1790 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
1791 eel_canvas_queue_resize (item->canvas);
1792
1793 /* Unparent the child */
1794
1795 item->parent = NULL((void*)0);
1796 /* item->canvas = NULL; */
1797 g_object_unref (G_OBJECT (item)((((GObject*) (void *) ((item))))));
1798
1799 /* Remove it from the list */
1800
1801 if (children == group->item_list_end)
1802 group->item_list_end = children->prev;
1803
1804 group->item_list = g_list_remove_link (group->item_list, children);
1805 g_list_free (children);
1806 break;
1807 }
1808}
1809
1810
1811/*** EelCanvas ***/
1812
1813
1814enum
1815{
1816 DRAW_BACKGROUND,
1817 LAST_SIGNAL
1818};
1819
1820static void eel_canvas_class_init (EelCanvasClass *klass);
1821static void eel_canvas_init (EelCanvas *canvas);
1822static void eel_canvas_destroy (GtkWidget *object);
1823static void eel_canvas_map (GtkWidget *widget);
1824static void eel_canvas_unmap (GtkWidget *widget);
1825static void eel_canvas_realize (GtkWidget *widget);
1826static void eel_canvas_unrealize (GtkWidget *widget);
1827static void eel_canvas_size_allocate (GtkWidget *widget,
1828 GtkAllocation *allocation);
1829static gint eel_canvas_button (GtkWidget *widget,
1830 GdkEventButton *event);
1831static gint eel_canvas_motion (GtkWidget *widget,
1832 GdkEventMotion *event);
1833static gint eel_canvas_draw (GtkWidget *widget,
1834 cairo_t *cr);
1835static gint eel_canvas_key (GtkWidget *widget,
1836 GdkEventKey *event);
1837static gint eel_canvas_crossing (GtkWidget *widget,
1838 GdkEventCrossing *event);
1839static gint eel_canvas_focus_in (GtkWidget *widget,
1840 GdkEventFocus *event);
1841static gint eel_canvas_focus_out (GtkWidget *widget,
1842 GdkEventFocus *event);
1843static void eel_canvas_request_update_real (EelCanvas *canvas);
1844static void eel_canvas_draw_background (EelCanvas *canvas,
1845 cairo_t *cr);
1846
1847static GtkLayoutClass *canvas_parent_class;
1848
1849static guint canvas_signals[LAST_SIGNAL] = { 0 };
1850
1851/**
1852 * eel_canvas_get_type:
1853 *
1854 * Registers the &EelCanvas class if necessary, and returns the type ID
1855 * associated to it.
1856 *
1857 * Return value: The type ID of the &EelCanvas class.
1858 **/
1859GType
1860eel_canvas_get_type (void)
1861{
1862 static GType canvas_type = 0;
1863
1864 if (!canvas_type)
1865 {
1866 static const GTypeInfo canvas_info =
1867 {
1868 sizeof (EelCanvasClass),
1869 (GBaseInitFunc) NULL((void*)0),
1870 (GBaseFinalizeFunc) NULL((void*)0),
1871 (GClassInitFunc) eel_canvas_class_init,
1872 NULL((void*)0), /* class_finalize */
1873 NULL((void*)0), /* class_data */
1874 sizeof (EelCanvas),
1875 0, /* n_preallocs */
1876 (GInstanceInitFunc) eel_canvas_init
1877 };
1878
1879 canvas_type = g_type_register_static (gtk_layout_get_type (),
1880 "EelCanvas",
1881 &canvas_info,
1882 0);
1883 }
1884
1885 return canvas_type;
1886}
1887
1888static void
1889eel_canvas_get_property (GObject *object,
1890 guint prop_id,
1891 GValue *value,
1892 GParamSpec *pspec)
1893{
1894 switch (prop_id)
1895 {
1896 default:
1897 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'"
, "eel-canvas.c", 1897, ("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)
;
1898 break;
1899 }
1900}
1901
1902static void
1903eel_canvas_set_property (GObject *object,
1904 guint prop_id,
1905 const GValue *value,
1906 GParamSpec *pspec)
1907{
1908 switch (prop_id)
1909 {
1910 default:
1911 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'"
, "eel-canvas.c", 1911, ("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)
;
1912 break;
1913 }
1914}
1915
1916static void
1917eel_canvas_accessible_adjustment_changed (GtkAdjustment *adjustment,
1918 gpointer data)
1919{
1920 AtkObject *atk_obj;
1921
1922 /* The scrollbars have changed */
1923 atk_obj = ATK_OBJECT (data)((((AtkObject*) (void *) ((data)))));
1924
1925 g_signal_emit_by_name (atk_obj, "visible_data_changed");
1926}
1927
1928static void
1929eel_canvas_accessible_initialize (AtkObject *obj,
1930 gpointer data)
1931{
1932 EelCanvas *canvas;
1933
1934 if (ATK_OBJECT_CLASS (accessible_parent_class)((((AtkObjectClass*) (void *) ((accessible_parent_class)))))->initialize != NULL((void*)0))
1935 ATK_OBJECT_CLASS (accessible_parent_class)((((AtkObjectClass*) (void *) ((accessible_parent_class)))))->initialize (obj, data);
1936
1937 canvas = EEL_CANVAS (data)((((EelCanvas*) (void *) ((data)))));
1938 g_signal_connect (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)),g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1939 "value_changed",g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1940 G_CALLBACK (eel_canvas_accessible_adjustment_changed),g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1941 obj)g_signal_connect_data ((gtk_scrollable_get_hadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
;
1942 g_signal_connect (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)),g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1943 "value_changed",g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1944 G_CALLBACK (eel_canvas_accessible_adjustment_changed),g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
1945 obj)g_signal_connect_data ((gtk_scrollable_get_vadjustment (((((GtkScrollable
*) (void *) ((canvas))))))), ("value_changed"), (((GCallback)
(eel_canvas_accessible_adjustment_changed))), (obj), ((void*
)0), (GConnectFlags) 0)
;
1946
1947 obj->role = ATK_ROLE_LAYERED_PANE;
1948}
1949
1950static gint
1951eel_canvas_accessible_get_n_children (AtkObject* obj)
1952{
1953 GtkAccessible *accessible;
1954 GtkWidget *widget;
1955 EelCanvas *canvas;
1956 EelCanvasGroup *root_group;
1957
1958 accessible = GTK_ACCESSIBLE (obj)((((GtkAccessible*) (void *) ((obj)))));
1959 widget = gtk_accessible_get_widget (accessible);
1960 if (widget == NULL((void*)0))
1961 {
1962 /* State is defunct */
1963 return 0;
1964 }
1965
1966 g_return_val_if_fail (EEL_IS_CANVAS (widget), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return (0); } } while
(0)
;
1967
1968 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
1969 root_group = eel_canvas_root (canvas);
1970 g_return_val_if_fail (root_group, 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if (root_group) _g_boolean_var_156 = 1; else _g_boolean_var_156
= 0; _g_boolean_var_156; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "root_group"); return (0
); } } while (0)
;
1971 return 1;
1972}
1973
1974static AtkObject*
1975eel_canvas_accessible_ref_child (AtkObject *obj,
1976 gint i)
1977{
1978 GtkAccessible *accessible;
1979 GtkWidget *widget;
1980 EelCanvas *canvas;
1981 EelCanvasGroup *root_group;
1982 AtkObject *atk_object;
1983
1984 /* Canvas only has one child, so return NULL if index is non zero */
1985 if (i != 0)
1986 {
1987 return NULL((void*)0);
1988 }
1989
1990 accessible = GTK_ACCESSIBLE (obj)((((GtkAccessible*) (void *) ((obj)))));
1991 widget = gtk_accessible_get_widget (accessible);
1992 if (widget == NULL((void*)0))
1993 {
1994 /* State is defunct */
1995 return NULL((void*)0);
1996 }
1997
1998 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
1999 root_group = eel_canvas_root (canvas);
2000 g_return_val_if_fail (root_group, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if (root_group) _g_boolean_var_157 = 1; else _g_boolean_var_157
= 0; _g_boolean_var_157; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "root_group"); return ((
(void*)0)); } } while (0)
;
2001 atk_object = atk_gobject_accessible_for_object (G_OBJECT (root_group)((((GObject*) (void *) ((root_group))))));
2002 g_object_ref (atk_object)((__typeof__ (atk_object)) (g_object_ref) (atk_object));
2003
2004 g_warning ("Accessible support for FooGroup needs to be implemented");
2005
2006 return atk_object;
2007}
2008
2009G_DEFINE_TYPE (EelCanvasAccessible, eel_canvas_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE)static void eel_canvas_accessible_init (EelCanvasAccessible *
self); static void eel_canvas_accessible_class_init (EelCanvasAccessibleClass
*klass); static GType eel_canvas_accessible_get_type_once (void
); static gpointer eel_canvas_accessible_parent_class = ((void
*)0); static gint EelCanvasAccessible_private_offset; static void
eel_canvas_accessible_class_intern_init (gpointer klass) { eel_canvas_accessible_parent_class
= g_type_class_peek_parent (klass); if (EelCanvasAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelCanvasAccessible_private_offset
); eel_canvas_accessible_class_init ((EelCanvasAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_canvas_accessible_get_instance_private (EelCanvasAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelCanvasAccessible_private_offset
)))); } GType eel_canvas_accessible_get_type (void) { static GType
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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_accessible_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType eel_canvas_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelCanvasAccessible"), sizeof (EelCanvasAccessibleClass), (
GClassInitFunc)(void (*)(void)) eel_canvas_accessible_class_intern_init
, sizeof (EelCanvasAccessible), (GInstanceInitFunc)(void (*)(
void)) eel_canvas_accessible_init, (GTypeFlags) 0); { {{};} }
return g_define_type_id; }
2010
2011static void
2012eel_canvas_accessible_class_init (EelCanvasAccessibleClass *klass)
2013{
2014 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
2015 accessible_parent_class = g_type_class_peek_parent (atk_class);
2016
2017 atk_class->initialize = eel_canvas_accessible_initialize;
2018 atk_class->get_n_children = eel_canvas_accessible_get_n_children;
2019 atk_class->ref_child = eel_canvas_accessible_ref_child;
2020}
2021
2022static void
2023eel_canvas_accessible_init (EelCanvasAccessible *accessible)
2024{
2025}
2026
2027/* Class initialization function for EelCanvasClass */
2028static void
2029eel_canvas_class_init (EelCanvasClass *klass)
2030{
2031 GObjectClass *gobject_class;
2032 GtkWidgetClass *widget_class;
2033
2034 gobject_class = (GObjectClass *)klass;
2035 widget_class = (GtkWidgetClass *) klass;
2036
2037 canvas_parent_class = g_type_class_peek_parent (klass);
2038
2039 gobject_class->set_property = eel_canvas_set_property;
2040 gobject_class->get_property = eel_canvas_get_property;
2041
2042 widget_class->destroy = eel_canvas_destroy;
2043 widget_class->map = eel_canvas_map;
2044 widget_class->unmap = eel_canvas_unmap;
2045 widget_class->realize = eel_canvas_realize;
2046 widget_class->unrealize = eel_canvas_unrealize;
2047 widget_class->size_allocate = eel_canvas_size_allocate;
2048 widget_class->button_press_event = eel_canvas_button;
2049 widget_class->button_release_event = eel_canvas_button;
2050 widget_class->motion_notify_event = eel_canvas_motion;
2051 widget_class->draw = eel_canvas_draw;
2052 widget_class->key_press_event = eel_canvas_key;
2053 widget_class->key_release_event = eel_canvas_key;
2054 widget_class->enter_notify_event = eel_canvas_crossing;
2055 widget_class->leave_notify_event = eel_canvas_crossing;
2056 widget_class->focus_in_event = eel_canvas_focus_in;
2057 widget_class->focus_out_event = eel_canvas_focus_out;
2058
2059 klass->draw_background = eel_canvas_draw_background;
2060 klass->request_update = eel_canvas_request_update_real;
2061
2062 canvas_signals[DRAW_BACKGROUND] =
2063 g_signal_new ("draw_background",
2064 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
2065 G_SIGNAL_RUN_LAST,
2066 G_STRUCT_OFFSET (EelCanvasClass, draw_background)((glong) __builtin_offsetof(EelCanvasClass, draw_background)),
2067 NULL((void*)0), NULL((void*)0),
2068 g_cclosure_marshal_VOID__BOXED,
2069 G_TYPE_NONE((GType) ((1) << (2))), 1,
2070 CAIRO_GOBJECT_TYPE_CONTEXTcairo_gobject_context_get_type ());
2071
2072 gtk_widget_class_set_accessible_type (widget_class, eel_canvas_accessible_get_type ());
2073}
2074
2075/* Callback used when the root item of a canvas is destroyed. The user should
2076 * never ever do this, so we panic if this happens.
2077 */
2078static void
2079panic_root_destroyed (GtkWidget *object, gpointer data)
2080{
2081 g_error ("Eeeek, root item %p of canvas %p was destroyed!", object, data);
2082}
2083
2084/* Object initialization function for EelCanvas */
2085static void
2086eel_canvas_init (EelCanvas *canvas)
2087{
2088 guint width, height;
2089 gtk_widget_set_can_focus (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))), TRUE(!(0)));
2090
2091 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))), FALSE(0));
2092
2093 canvas->scroll_x1 = 0.0;
2094 canvas->scroll_y1 = 0.0;
2095 gtk_layout_get_size (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas))))),
2096 &width, &height);
2097 canvas->scroll_x2 = width;
2098 canvas->scroll_y2 = height;
2099
2100 canvas->pixels_per_unit = 1.0;
2101
2102 canvas->pick_event.type = GDK_LEAVE_NOTIFY;
2103 canvas->pick_event.crossing.x = 0;
2104 canvas->pick_event.crossing.y = 0;
2105
2106 gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))), NULL((void*)0));
2107 gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))), NULL((void*)0));
2108
2109 /* Create the root item as a special case */
2110
2111 canvas->root = EEL_CANVAS_ITEM (g_object_new (eel_canvas_group_get_type (), NULL))((((EelCanvasItem*) (void *) ((g_object_new (eel_canvas_group_get_type
(), ((void*)0)))))))
;
2112 canvas->root->canvas = canvas;
2113
2114 g_object_ref_sink (canvas->root)((__typeof__ (canvas->root)) (g_object_ref_sink) (canvas->
root))
;
2115
2116 canvas->root_destroy_id = g_signal_connect (G_OBJECT (canvas->root),g_signal_connect_data ((((((GObject*) (void *) ((canvas->root
)))))), ("destroy"), (((GCallback) (panic_root_destroyed))), (
canvas), ((void*)0), (GConnectFlags) 0)
2117 "destroy", G_CALLBACK (panic_root_destroyed), canvas)g_signal_connect_data ((((((GObject*) (void *) ((canvas->root
)))))), ("destroy"), (((GCallback) (panic_root_destroyed))), (
canvas), ((void*)0), (GConnectFlags) 0)
;
2118
2119 canvas->need_repick = TRUE(!(0));
2120 canvas->doing_update = FALSE(0);
2121}
2122
2123/* Convenience function to remove the idle handler of a canvas */
2124static void
2125remove_idle (EelCanvas *canvas)
2126{
2127 if (canvas->idle_id == 0)
2128 return;
2129
2130 g_source_remove (canvas->idle_id);
2131 canvas->idle_id = 0;
2132}
2133
2134/* Removes the transient state of the canvas (idle handler, grabs). */
2135static void
2136shutdown_transients (EelCanvas *canvas)
2137{
2138 /* We turn off the need_redraw flag, since if the canvas is mapped again
2139 * it will request a redraw anyways. We do not turn off the need_update
2140 * flag, though, because updates are not queued when the canvas remaps
2141 * itself.
2142 */
2143 if (canvas->need_redraw)
2144 {
2145 canvas->need_redraw = FALSE(0);
2146 }
2147
2148 if (canvas->grabbed_item)
2149 {
2150 eel_canvas_item_ungrab (canvas->grabbed_item);
2151 }
2152
2153 remove_idle (canvas);
2154}
2155
2156/* Destroy handler for EelCanvas */
2157static void
2158eel_canvas_destroy (GtkWidget *object)
2159{
2160 EelCanvas *canvas;
2161
2162 g_return_if_fail (EEL_IS_CANVAS (object))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (object)"); return; } } while (0
)
;
2163
2164 /* remember, destroy can be run multiple times! */
2165
2166 canvas = EEL_CANVAS (object)((((EelCanvas*) (void *) ((object)))));
2167
2168 if (canvas->root_destroy_id)
2169 {
2170 g_signal_handler_disconnect (G_OBJECT (canvas->root)((((GObject*) (void *) ((canvas->root))))), canvas->root_destroy_id);
2171 canvas->root_destroy_id = 0;
2172 }
2173 if (canvas->root)
2174 {
2175 EelCanvasItem *root = canvas->root;
2176 canvas->root = NULL((void*)0);
2177 eel_canvas_item_destroy (root);
2178 g_object_unref (root);
2179 }
2180
2181 shutdown_transients (canvas);
2182
2183 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->destroy)
2184 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->destroy) (object);
2185}
2186
2187/**
2188 * eel_canvas_new:
2189 * @void:
2190 *
2191 * Creates a new empty canvas. If you wish to use the
2192 * &EelCanvasImage item inside this canvas, then you must push the gdk_imlib
2193 * visual and colormap before calling this function, and they can be popped
2194 * afterwards.
2195 *
2196 * Return value: A newly-created canvas.
2197 **/
2198GtkWidget *
2199eel_canvas_new (void)
2200{
2201 return GTK_WIDGET (g_object_new (eel_canvas_get_type (), NULL))((((GtkWidget*) (void *) ((g_object_new (eel_canvas_get_type (
), ((void*)0)))))))
;
2202}
2203
2204/* Map handler for the canvas */
2205static void
2206eel_canvas_map (GtkWidget *widget)
2207{
2208 EelCanvas *canvas;
2209
2210 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2211
2212 /* Normal widget mapping stuff */
2213
2214 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->map)
2215 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->map) (widget);
2216
2217 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2218
2219 /* Map items */
2220
2221 if (canvas->root->flags & EEL_CANVAS_ITEM_VISIBLE &&
2222 !(canvas->root->flags & EEL_CANVAS_ITEM_MAPPED) &&
2223 EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->map)
2224 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->map) (canvas->root);
2225}
2226
2227/* Unmap handler for the canvas */
2228static void
2229eel_canvas_unmap (GtkWidget *widget)
2230{
2231 EelCanvas *canvas;
2232
2233 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_160
= 1; else _g_boolean_var_160 = 0; _g_boolean_var_160; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2234
2235 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2236
2237 shutdown_transients (canvas);
2238
2239 /* Unmap items */
2240
2241 if (EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->unmap)
2242 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->unmap) (canvas->root);
2243
2244 /* Normal widget unmapping stuff */
2245
2246 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unmap)
2247 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unmap) (widget);
2248}
2249
2250/* Realize handler for the canvas */
2251static void
2252eel_canvas_realize (GtkWidget *widget)
2253{
2254 EelCanvas *canvas;
2255
2256 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_161
= 1; else _g_boolean_var_161 = 0; _g_boolean_var_161; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2257
2258 /* Normal widget realization stuff */
2259
2260 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->realize)
2261 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->realize) (widget);
2262
2263 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2264
2265 gdk_window_set_events (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))),
2266 (gdk_window_get_events (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2267 | GDK_EXPOSURE_MASK
2268 | GDK_BUTTON_PRESS_MASK
2269 | GDK_BUTTON_RELEASE_MASK
2270 | GDK_POINTER_MOTION_MASK
2271 | GDK_KEY_PRESS_MASK
2272 | GDK_KEY_RELEASE_MASK
2273 | GDK_ENTER_NOTIFY_MASK
2274 | GDK_LEAVE_NOTIFY_MASK
2275 | GDK_FOCUS_CHANGE_MASK));
2276
2277 /* Create our own temporary pixmap gc and realize all the items */
2278
2279 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->realize) (canvas->root);
2280}
2281
2282/* Unrealize handler for the canvas */
2283static void
2284eel_canvas_unrealize (GtkWidget *widget)
2285{
2286 EelCanvas *canvas;
2287
2288 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2289
2290 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2291
2292 shutdown_transients (canvas);
2293
2294 /* Unrealize items and parent widget */
2295
2296 (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->unrealize) (canvas->root);
2297
2298 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unrealize)
2299 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->unrealize) (widget);
2300}
2301
2302/* Handles scrolling of the canvas. Adjusts the scrolling and zooming offset to
2303 * keep as much as possible of the canvas scrolling region in view.
2304 */
2305static void
2306scroll_to (EelCanvas *canvas, int cx, int cy)
2307{
2308 int scroll_width, scroll_height;
2309 int right_limit, bottom_limit;
2310 int old_zoom_xofs, old_zoom_yofs;
2311 int changed_x = FALSE(0), changed_y = FALSE(0);
2312 int canvas_width, canvas_height;
2313 GtkAllocation allocation;
2314 GtkAdjustment *vadjustment, *hadjustment;
2315 guint width, height;
2316
2317 gtk_widget_get_allocation (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))), &allocation);
2318 canvas_width = allocation.width;
2319 canvas_height = allocation.height;
2320
2321 scroll_width = floor ((canvas->scroll_x2 - canvas->scroll_x1) * canvas->pixels_per_unit + 0.5);
2322 scroll_height = floor ((canvas->scroll_y2 - canvas->scroll_y1) * canvas->pixels_per_unit + 0.5);
2323
2324 right_limit = scroll_width - canvas_width;
2325 bottom_limit = scroll_height - canvas_height;
2326
2327 old_zoom_xofs = canvas->zoom_xofs;
2328 old_zoom_yofs = canvas->zoom_yofs;
2329
2330 if (right_limit < 0)
2331 {
2332 cx = 0;
2333 if (canvas->center_scroll_region)
2334 {
2335 canvas->zoom_xofs = (canvas_width - scroll_width) / 2;
2336 scroll_width = canvas_width;
2337 }
2338 else
2339 {
2340 canvas->zoom_xofs = 0;
2341 }
2342 }
2343 else if (cx < 0)
2344 {
2345 cx = 0;
2346 canvas->zoom_xofs = 0;
2347 }
2348 else if (cx > right_limit)
2349 {
2350 cx = right_limit;
2351 canvas->zoom_xofs = 0;
2352 }
2353 else
2354 canvas->zoom_xofs = 0;
2355
2356 if (bottom_limit < 0)
2357 {
2358 cy = 0;
2359 if (canvas->center_scroll_region)
2360 {
2361 canvas->zoom_yofs = (canvas_height - scroll_height) / 2;
2362 scroll_height = canvas_height;
2363 }
2364 else
2365 {
2366 canvas->zoom_yofs = 0;
2367 }
2368 }
2369 else if (cy < 0)
2370 {
2371 cy = 0;
2372 canvas->zoom_yofs = 0;
2373 }
2374 else if (cy > bottom_limit)
2375 {
2376 cy = bottom_limit;
2377 canvas->zoom_yofs = 0;
2378 }
2379 else
2380 canvas->zoom_yofs = 0;
2381
2382 if ((canvas->zoom_xofs != old_zoom_xofs) || (canvas->zoom_yofs != old_zoom_yofs))
2383 {
2384 /* This can only occur, if either canvas size or widget size changes */
2385 /* So I think we can request full redraw here */
2386 /* More stuff - we have to mark root as needing fresh affine (Lauris) */
2387 if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
2388 {
2389 canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
2390 eel_canvas_request_update (canvas);
2391 }
2392 gtk_widget_queue_draw (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))));
2393 }
2394
2395 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2396 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2397
2398 if (((int) gtk_adjustment_get_value (hadjustment)) != cx)
2399 {
2400 gtk_adjustment_set_value (hadjustment, cx);
2401 changed_x = TRUE(!(0));
2402 }
2403
2404 if (((int) gtk_adjustment_get_value (vadjustment)) != cy)
2405 {
2406 gtk_adjustment_set_value (vadjustment, cy);
2407 changed_y = TRUE(!(0));
2408 }
2409
2410 gtk_layout_get_size (&canvas->layout, &width, &height);
2411 if ((scroll_width != (int) width )|| (scroll_height != (int) height))
2412 {
2413 gtk_layout_set_size (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas))))), scroll_width, scroll_height);
2414 }
2415
2416 /* Signal GtkLayout that it should do a redraw. */
2417 if (changed_x)
2418 g_signal_emit_by_name (hadjustment, "value_changed");
2419 if (changed_y)
2420 g_signal_emit_by_name (vadjustment, "value_changed");
2421}
2422
2423/* Size allocation handler for the canvas */
2424static void
2425eel_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
2426{
2427 EelCanvas *canvas;
2428 GtkAdjustment *vadjustment, *hadjustment;
2429
2430 g_return_if_fail (EEL_IS_CANVAS (widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_163
= 1; else _g_boolean_var_163 = 0; _g_boolean_var_163; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return; } } while (0
)
;
2431 g_return_if_fail (allocation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if (allocation != ((void*)0)) _g_boolean_var_164 = 1; else _g_boolean_var_164
= 0; _g_boolean_var_164; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "allocation != NULL"); return
; } } while (0)
;
2432
2433 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->size_allocate)
2434 (* GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->size_allocate) (widget, allocation);
2435
2436 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2437
2438 /* Recenter the view, if appropriate */
2439
2440 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2441 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
2442
2443 gtk_adjustment_set_page_size (hadjustment, allocation->width);
2444 gtk_adjustment_set_page_increment (hadjustment, allocation->width / 2);
2445
2446 gtk_adjustment_set_page_size (vadjustment, allocation->height);
2447 gtk_adjustment_set_page_increment (vadjustment, allocation->height / 2);
2448
2449 scroll_to (canvas,
2450 gtk_adjustment_get_value (hadjustment),
2451 gtk_adjustment_get_value (vadjustment));
2452
2453 g_signal_emit_by_name (hadjustment, "changed");
2454 g_signal_emit_by_name (vadjustment, "changed");
2455}
2456
2457/* Emits an event for an item in the canvas, be it the current item, grabbed
2458 * item, or focused item, as appropriate.
2459 */
2460
2461static int
2462emit_event (EelCanvas *canvas, GdkEvent *event)
2463{
2464 GdkEvent ev;
2465 gint finished;
2466 EelCanvasItem *item;
2467 EelCanvasItem *parent;
2468 guint mask;
2469
2470 /* Could be an old pick event */
2471 if (!gtk_widget_get_realized (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas)))))))
2472 {
2473 return FALSE(0);
2474 }
2475
2476 /* Perform checks for grabbed items */
2477
2478 if (canvas->grabbed_item &&
2479 !is_descendant (canvas->current_item, canvas->grabbed_item))
2480 {
2481 return FALSE(0);
2482 }
2483
2484 if (canvas->grabbed_item)
2485 {
2486 switch (event->type)
2487 {
2488 case GDK_ENTER_NOTIFY:
2489 mask = GDK_ENTER_NOTIFY_MASK;
2490 break;
2491
2492 case GDK_LEAVE_NOTIFY:
2493 mask = GDK_LEAVE_NOTIFY_MASK;
2494 break;
2495
2496 case GDK_MOTION_NOTIFY:
2497 mask = GDK_POINTER_MOTION_MASK;
2498 break;
2499
2500 case GDK_BUTTON_PRESS:
2501 case GDK_2BUTTON_PRESS:
2502 case GDK_3BUTTON_PRESS:
2503 mask = GDK_BUTTON_PRESS_MASK;
2504 break;
2505
2506 case GDK_BUTTON_RELEASE:
2507 mask = GDK_BUTTON_RELEASE_MASK;
2508 break;
2509
2510 case GDK_KEY_PRESS:
2511 mask = GDK_KEY_PRESS_MASK;
2512 break;
2513
2514 case GDK_KEY_RELEASE:
2515 mask = GDK_KEY_RELEASE_MASK;
2516 break;
2517
2518 default:
2519 mask = 0;
2520 break;
2521 }
2522
2523 if (!(mask & canvas->grabbed_event_mask))
2524 return FALSE(0);
2525 }
2526
2527 /* Convert to world coordinates -- we have two cases because of diferent
2528 * offsets of the fields in the event structures.
2529 */
2530
2531 ev = *event;
2532
2533 switch (ev.type)
2534 {
2535 case GDK_ENTER_NOTIFY:
2536 case GDK_LEAVE_NOTIFY:
2537 eel_canvas_window_to_world (canvas,
2538 ev.crossing.x, ev.crossing.y,
2539 &ev.crossing.x, &ev.crossing.y);
2540 break;
2541
2542 case GDK_MOTION_NOTIFY:
2543 case GDK_BUTTON_PRESS:
2544 case GDK_2BUTTON_PRESS:
2545 case GDK_3BUTTON_PRESS:
2546 case GDK_BUTTON_RELEASE:
2547 eel_canvas_window_to_world (canvas,
2548 ev.motion.x, ev.motion.y,
2549 &ev.motion.x, &ev.motion.y);
2550 break;
2551
2552 default:
2553 break;
2554 }
2555
2556 /* Choose where we send the event */
2557
2558 item = canvas->current_item;
2559
2560 if (canvas->focused_item
2561 && ((event->type == GDK_KEY_PRESS) ||
2562 (event->type == GDK_KEY_RELEASE) ||
2563 (event->type == GDK_FOCUS_CHANGE)))
2564 item = canvas->focused_item;
2565
2566 /* The event is propagated up the hierarchy (for if someone connected to
2567 * a group instead of a leaf event), and emission is stopped if a
2568 * handler returns TRUE, just like for GtkWidget events.
2569 */
2570
2571 finished = FALSE(0);
2572
2573 while (item && !finished)
2574 {
2575 g_object_ref (item)((__typeof__ (item)) (g_object_ref) (item));
2576
2577 g_signal_emit (
2578 G_OBJECT (item)((((GObject*) (void *) ((item))))), item_signals[ITEM_EVENT], 0,
2579 &ev, &finished);
2580
2581 parent = item->parent;
2582 g_object_unref (item);
2583
2584 item = parent;
2585 }
2586
2587 return finished;
2588}
2589
2590/* Re-picks the current item in the canvas, based on the event's coordinates.
2591 * Also emits enter/leave events for items as appropriate.
2592 */
2593static int
2594pick_current_item (EelCanvas *canvas, GdkEvent *event)
2595{
2596 int button_down;
2597 double x, y;
2598 int retval;
2599
2600 retval = FALSE(0);
2601
2602 /* If a button is down, we'll perform enter and leave events on the
2603 * current item, but not enter on any other item. This is more or less
2604 * like X pointer grabbing for canvas items.
2605 */
2606 button_down = canvas->state & (GDK_BUTTON1_MASK
2607 | GDK_BUTTON2_MASK
2608 | GDK_BUTTON3_MASK
2609 | GDK_BUTTON4_MASK
2610 | GDK_BUTTON5_MASK);
2611 if (!button_down)
2612 canvas->left_grabbed_item = FALSE(0);
2613
2614 /* Save the event in the canvas. This is used to synthesize enter and
2615 * leave events in case the current item changes. It is also used to
2616 * re-pick the current item if the current one gets deleted. Also,
2617 * synthesize an enter event.
2618 */
2619 if (event != &canvas->pick_event)
2620 {
2621 if ((event->type == GDK_MOTION_NOTIFY) || (event->type == GDK_BUTTON_RELEASE))
2622 {
2623 /* these fields have the same offsets in both types of events */
2624
2625 canvas->pick_event.crossing.type = GDK_ENTER_NOTIFY;
2626 canvas->pick_event.crossing.window = event->motion.window;
2627 canvas->pick_event.crossing.send_event = event->motion.send_event;
2628 canvas->pick_event.crossing.subwindow = NULL((void*)0);
2629 canvas->pick_event.crossing.x = event->motion.x;
2630 canvas->pick_event.crossing.y = event->motion.y;
2631 canvas->pick_event.crossing.mode = GDK_CROSSING_NORMAL;
2632 canvas->pick_event.crossing.detail = GDK_NOTIFY_NONLINEAR;
2633 canvas->pick_event.crossing.focus = FALSE(0);
2634 canvas->pick_event.crossing.state = event->motion.state;
2635
2636 /* these fields don't have the same offsets in both types of events */
2637
2638 if (event->type == GDK_MOTION_NOTIFY)
2639 {
2640 canvas->pick_event.crossing.x_root = event->motion.x_root;
2641 canvas->pick_event.crossing.y_root = event->motion.y_root;
2642 }
2643 else
2644 {
2645 canvas->pick_event.crossing.x_root = event->button.x_root;
2646 canvas->pick_event.crossing.y_root = event->button.y_root;
2647 }
2648 }
2649 else
2650 canvas->pick_event = *event;
2651 }
2652
2653 /* Don't do anything else if this is a recursive call */
2654
2655 if (canvas->in_repick)
2656 return retval;
2657
2658 /* LeaveNotify means that there is no current item, so we don't look for one */
2659
2660 if (canvas->pick_event.type != GDK_LEAVE_NOTIFY)
2661 {
2662 /* these fields don't have the same offsets in both types of events */
2663
2664 if (canvas->pick_event.type == GDK_ENTER_NOTIFY)
2665 {
2666 x = canvas->pick_event.crossing.x;
2667 y = canvas->pick_event.crossing.y;
2668 }
2669 else
2670 {
2671 x = canvas->pick_event.motion.x;
2672 y = canvas->pick_event.motion.y;
2673 }
2674
2675 /* canvas pixel coords */
2676 int cx, cy;
2677
2678 cx = (int) (x + 0.5);
2679 cy = (int) (y + 0.5);
2680
2681 /* world coords */
2682 eel_canvas_c2w (canvas, cx, cy, &x, &y);
2683
2684 /* find the closest item */
2685 if (canvas->root->flags & EEL_CANVAS_ITEM_MAPPED)
2686 eel_canvas_item_invoke_point (canvas->root, x, y, cx, cy,
2687 &canvas->new_current_item);
2688 else
2689 canvas->new_current_item = NULL((void*)0);
2690 }
2691 else
2692 canvas->new_current_item = NULL((void*)0);
2693
2694 if ((canvas->new_current_item == canvas->current_item) && !canvas->left_grabbed_item)
2695 return retval; /* current item did not change */
2696
2697 /* Synthesize events for old and new current items */
2698
2699 if ((canvas->new_current_item != canvas->current_item)
2700 && (canvas->current_item != NULL((void*)0))
2701 && !canvas->left_grabbed_item)
2702 {
2703 GdkEvent new_event;
2704
2705 new_event = canvas->pick_event;
2706 new_event.type = GDK_LEAVE_NOTIFY;
2707
2708 new_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
2709 new_event.crossing.subwindow = NULL((void*)0);
2710 canvas->in_repick = TRUE(!(0));
2711 retval = emit_event (canvas, &new_event);
2712 canvas->in_repick = FALSE(0);
2713 }
2714
2715 /* new_current_item may have been set to NULL during the call to emit_event() above */
2716
2717 if ((canvas->new_current_item != canvas->current_item) && button_down)
2718 {
2719 canvas->current_item = canvas->new_current_item;
2720 canvas->left_grabbed_item = TRUE(!(0));
2721 return retval;
2722 }
2723
2724 /* Handle the rest of cases */
2725
2726 canvas->left_grabbed_item = FALSE(0);
2727 canvas->current_item = canvas->new_current_item;
2728
2729 if (canvas->current_item != NULL((void*)0))
2730 {
2731 GdkEvent new_event;
2732
2733 new_event = canvas->pick_event;
2734 new_event.type = GDK_ENTER_NOTIFY;
2735 new_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
2736 new_event.crossing.subwindow = NULL((void*)0);
2737 retval = emit_event (canvas, &new_event);
2738 }
2739
2740 return retval;
2741}
2742
2743/* Button event handler for the canvas */
2744static gint
2745eel_canvas_button (GtkWidget *widget, GdkEventButton *event)
2746{
2747 EelCanvas *canvas;
2748 int mask;
2749 int retval;
2750
2751 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2752 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if (event != ((void*)0)) _g_boolean_var_166 = 1; else _g_boolean_var_166
= 0; _g_boolean_var_166; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2753
2754 retval = FALSE(0);
2755
2756 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2757
2758 /* Don't handle extra mouse button events */
2759 if (event->button > 5)
2760 return FALSE(0);
2761
2762 /*
2763 * dispatch normally regardless of the event's window if an item has
2764 * has a pointer grab in effect
2765 */
2766 if (!canvas->grabbed_item && event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2767 return retval;
2768
2769 switch (event->button)
2770 {
2771 case 1:
2772 mask = GDK_BUTTON1_MASK;
2773 break;
2774 case 2:
2775 mask = GDK_BUTTON2_MASK;
2776 break;
2777 case 3:
2778 mask = GDK_BUTTON3_MASK;
2779 break;
2780 case 4:
2781 mask = GDK_BUTTON4_MASK;
2782 break;
2783 case 5:
2784 mask = GDK_BUTTON5_MASK;
2785 break;
2786 default:
2787 mask = 0;
2788 }
2789
2790 switch (event->type)
2791 {
2792 case GDK_BUTTON_PRESS:
2793 case GDK_2BUTTON_PRESS:
2794 case GDK_3BUTTON_PRESS:
2795 /* Pick the current item as if the button were not pressed, and
2796 * then process the event.
2797 */
2798 event->state ^= mask;
2799 canvas->state = event->state;
2800 pick_current_item (canvas, (GdkEvent *) event);
2801 event->state ^= mask;
2802 canvas->state = event->state;
2803 retval = emit_event (canvas, (GdkEvent *) event);
2804 break;
2805
2806 case GDK_BUTTON_RELEASE:
2807 /* Process the event as if the button were pressed, then repick
2808 * after the button has been released
2809 */
2810 canvas->state = event->state;
2811 retval = emit_event (canvas, (GdkEvent *) event);
2812 event->state ^= mask;
2813 canvas->state = event->state;
2814 pick_current_item (canvas, (GdkEvent *) event);
2815 event->state ^= mask;
2816 break;
2817
2818 default:
2819 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-canvas.c", 2819, (
(const char*) (__func__)), ((void*)0)); } while (0)
;
2820 }
2821
2822 return retval;
2823}
2824
2825/* Motion event handler for the canvas */
2826static gint
2827eel_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
2828{
2829 EelCanvas *canvas;
2830
2831 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2832 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if (event != ((void*)0)) _g_boolean_var_168 = 1; else _g_boolean_var_168
= 0; _g_boolean_var_168; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2833
2834 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2835
2836 if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2837 return FALSE(0);
2838
2839 canvas->state = event->state;
2840 pick_current_item (canvas, (GdkEvent *) event);
2841 return emit_event (canvas, (GdkEvent *) event);
2842}
2843
2844/* Key event handler for the canvas */
2845static gint
2846eel_canvas_key (GtkWidget *widget, GdkEventKey *event)
2847{
2848 EelCanvas *canvas;
2849
2850 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_169
= 1; else _g_boolean_var_169 = 0; _g_boolean_var_169; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2851 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if (event != ((void*)0)) _g_boolean_var_170 = 1; else _g_boolean_var_170
= 0; _g_boolean_var_170; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2852
2853 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2854
2855 if (emit_event (canvas, (GdkEvent *) event))
2856 return TRUE(!(0));
2857 if (event->type == GDK_KEY_RELEASE)
2858 return GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->key_release_event (widget, event);
2859 else
2860 return GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->key_press_event (widget, event);
2861}
2862
2863
2864/* Crossing event handler for the canvas */
2865static gint
2866eel_canvas_crossing (GtkWidget *widget, GdkEventCrossing *event)
2867{
2868 EelCanvas *canvas;
2869
2870 g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((eel_canvas_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_171
= 1; else _g_boolean_var_171 = 0; _g_boolean_var_171; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (widget)"); return ((0)); } } while
(0)
;
2871 g_return_val_if_fail (event != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if (event != ((void*)0)) _g_boolean_var_172 = 1; else _g_boolean_var_172
= 0; _g_boolean_var_172; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "event != NULL"); return
((0)); } } while (0)
;
2872
2873 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2874
2875 if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))))
2876 return FALSE(0);
2877
2878 canvas->state = event->state;
2879 return pick_current_item (canvas, (GdkEvent *) event);
2880}
2881
2882/* Focus in handler for the canvas */
2883static gint
2884eel_canvas_focus_in (GtkWidget *widget, GdkEventFocus *event)
2885{
2886 EelCanvas *canvas;
2887
2888 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2889
2890 if (canvas->focused_item)
2891 return emit_event (canvas, (GdkEvent *) event);
2892 else
2893 return FALSE(0);
2894}
2895
2896/* Focus out handler for the canvas */
2897static gint
2898eel_canvas_focus_out (GtkWidget *widget, GdkEventFocus *event)
2899{
2900 EelCanvas *canvas;
2901
2902 canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2903
2904 if (canvas->focused_item)
2905 return emit_event (canvas, (GdkEvent *) event);
2906 else
2907 return FALSE(0);
2908}
2909
2910static cairo_region_t *
2911eel_cairo_get_clip_region (cairo_t *cr)
2912{
2913 cairo_rectangle_list_t *list;
2914 cairo_region_t *region;
2915 int i;
2916
2917 list = cairo_copy_clip_rectangle_list (cr);
2918 if (list->status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) {
2919 cairo_rectangle_int_t clip_rect;
2920
2921 cairo_rectangle_list_destroy (list);
2922
2923 if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
2924 return NULL((void*)0);
2925 return cairo_region_create_rectangle (&clip_rect);
2926 }
2927
2928
2929 region = cairo_region_create ();
2930 for (i = list->num_rectangles - 1; i >= 0; --i) {
2931 cairo_rectangle_t *rect = &list->rectangles[i];
2932 cairo_rectangle_int_t clip_rect;
2933
2934 clip_rect.x = floor (rect->x);
2935 clip_rect.y = floor (rect->y);
2936 clip_rect.width = ceil (rect->x + rect->width) - clip_rect.x;
2937 clip_rect.height = ceil (rect->y + rect->height) - clip_rect.y;
2938
2939 if (cairo_region_union_rectangle (region, &clip_rect) != CAIRO_STATUS_SUCCESS) {
2940 cairo_region_destroy (region);
2941 region = NULL((void*)0);
2942 break;
2943 }
2944 }
2945
2946 cairo_rectangle_list_destroy (list);
2947 return region;
2948}
2949
2950/* Expose handler for the canvas */
2951static gboolean
2952eel_canvas_draw (GtkWidget *widget, cairo_t *cr)
2953{
2954 EelCanvas *canvas = EEL_CANVAS (widget)((((EelCanvas*) (void *) ((widget)))));
2955 GdkWindow *bin_window;
2956 cairo_region_t *region;
2957
2958 if (!gdk_cairo_get_clip_rectangle (cr, NULL((void*)0)))
2959 return FALSE(0);
2960
2961 bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (widget)((((GtkLayout*) (void *) ((widget))))));
2962
2963 if (!gtk_cairo_should_draw_window (cr, bin_window))
2964 return FALSE(0);
2965
2966 cairo_save (cr);
2967
2968 gtk_cairo_transform_to_window (cr, widget, bin_window);
2969
2970 region = eel_cairo_get_clip_region (cr);
2971 if (region == NULL((void*)0)) {
2972 cairo_restore (cr);
2973 return FALSE(0);
2974 }
2975
2976#if defined VERBOSE
2977 g_print ("Draw\n");
2978#endif
2979 /* If there are any outstanding items that need updating, do them now */
2980 if (canvas->idle_id)
2981 {
2982 g_source_remove (canvas->idle_id);
2983 canvas->idle_id = 0;
2984 }
2985 if (canvas->need_update)
2986 {
2987 g_return_val_if_fail (!canvas->doing_update, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if (!canvas->doing_update) _g_boolean_var_173 = 1; else _g_boolean_var_173
= 0; _g_boolean_var_173; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "!canvas->doing_update"
); return ((0)); } } while (0)
;
2988
2989 canvas->doing_update = TRUE(!(0));
2990 eel_canvas_item_invoke_update (canvas->root, 0, 0, 0);
2991
2992 g_return_val_if_fail (canvas->doing_update, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if (canvas->doing_update) _g_boolean_var_174 = 1; else _g_boolean_var_174
= 0; _g_boolean_var_174; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "canvas->doing_update"
); return ((0)); } } while (0)
;
2993
2994 canvas->doing_update = FALSE(0);
2995
2996 canvas->need_update = FALSE(0);
2997 }
2998
2999 /* Hmmm. Would like to queue antiexposes if the update marked
3000 anything that is gonna get redrawn as invalid */
3001
3002 g_signal_emit (G_OBJECT (canvas)((((GObject*) (void *) ((canvas))))), canvas_signals[DRAW_BACKGROUND], 0,
3003 cr);
3004
3005 if (canvas->root->flags & EEL_CANVAS_ITEM_MAPPED)
3006 EEL_CANVAS_ITEM_GET_CLASS (canvas->root)((((EelCanvasItemClass*) (((GTypeInstance*) ((canvas->root
)))->g_class))))
->draw (canvas->root,
3007 cr, region);
3008
3009 /* Chain up to get exposes on child widgets */
3010 cairo_restore (cr);
3011
3012 if (GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->draw)
3013 GTK_WIDGET_CLASS (canvas_parent_class)((((GtkWidgetClass*) (void *) ((canvas_parent_class)))))->draw (widget, cr);
3014
3015 cairo_region_destroy (region);
3016
3017 return FALSE(0);
3018}
3019
3020static void
3021eel_canvas_draw_background (EelCanvas *canvas,
3022 cairo_t *cr)
3023{
3024 cairo_rectangle_int_t rect;
3025 GtkStyleContext *style_context;
3026 GdkRGBA color;
3027 GdkRGBA *c;
3028
3029 if (!gdk_cairo_get_clip_rectangle (cr, &rect))
3030 return;
3031
3032 cairo_save (cr);
3033 /* By default, we use the style background. */
3034 style_context = gtk_widget_get_style_context (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))));
3035
3036 gtk_style_context_get (style_context, GTK_STATE_FLAG_NORMAL,
3037 GTK_STYLE_PROPERTY_BACKGROUND_COLOR"background-color",
3038 &c, NULL((void*)0));
3039 color = *c;
3040 gdk_rgba_free (c);
3041
3042 gdk_cairo_set_source_rgba (cr, &color);
3043 gdk_cairo_rectangle (cr, &rect);
3044 cairo_fill (cr);
3045 cairo_restore (cr);
3046}
3047
3048static void
3049do_update (EelCanvas *canvas)
3050{
3051 /* Cause the update if necessary */
3052
3053update_again:
3054 if (canvas->need_update)
3055 {
3056 g_return_if_fail (!canvas->doing_update)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if (!canvas->doing_update) _g_boolean_var_175 = 1; else _g_boolean_var_175
= 0; _g_boolean_var_175; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "!canvas->doing_update"
); return; } } while (0)
;
3057
3058 canvas->doing_update = TRUE(!(0));
3059 eel_canvas_item_invoke_update (canvas->root, 0, 0, 0);
3060
3061 g_return_if_fail (canvas->doing_update)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if (canvas->doing_update) _g_boolean_var_176 = 1; else _g_boolean_var_176
= 0; _g_boolean_var_176; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "canvas->doing_update"
); return; } } while (0)
;
3062
3063 canvas->doing_update = FALSE(0);
3064
3065 canvas->need_update = FALSE(0);
3066 }
3067
3068 /* Pick new current item */
3069
3070 while (canvas->need_repick)
3071 {
3072 canvas->need_repick = FALSE(0);
3073 pick_current_item (canvas, &canvas->pick_event);
3074 }
3075
3076 /* it is possible that during picking we emitted an event in which
3077 the user then called some function which then requested update
3078 of something. Without this we'd be left in a state where
3079 need_update would have been left TRUE and the canvas would have
3080 been left unpainted. */
3081 if (canvas->need_update)
3082 {
3083 goto update_again;
3084 }
3085}
3086
3087/* Idle handler for the canvas. It deals with pending updates and redraws. */
3088static gint
3089idle_handler (gpointer data)
3090{
3091 EelCanvas *canvas;
3092
3093 canvas = EEL_CANVAS (data)((((EelCanvas*) (void *) ((data)))));
3094 do_update (canvas);
3095
3096 /* Reset idle id */
3097 canvas->idle_id = 0;
3098
3099 return FALSE(0);
3100}
3101
3102/* Convenience function to add an idle handler to a canvas */
3103static void
3104add_idle (EelCanvas *canvas)
3105{
3106 if (!canvas->idle_id)
3107 {
3108 /* We let the update idle handler have higher priority
3109 * than the redraw idle handler so the canvas state
3110 * will be updated during the expose event. canvas in
3111 * expose_event.
3112 */
3113 canvas->idle_id = g_idle_add_full (GDK_PRIORITY_REDRAW(100 + 20) - 20,
3114 idle_handler, canvas, NULL((void*)0));
3115 }
3116}
3117
3118/**
3119 * eel_canvas_root:
3120 * @canvas: A canvas.
3121 *
3122 * Queries the root group of a canvas.
3123 *
3124 * Return value: The root group of the specified canvas.
3125 **/
3126EelCanvasGroup *
3127eel_canvas_root (EelCanvas *canvas)
3128{
3129 g_return_val_if_fail (EEL_IS_CANVAS (canvas), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_177
= 1; else _g_boolean_var_177 = 0; _g_boolean_var_177; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return (((void*)0));
} } while (0)
;
3130
3131 return EEL_CANVAS_GROUP (canvas->root)((((EelCanvasGroup*) (void *) ((canvas->root)))));
3132}
3133
3134
3135/**
3136 * eel_canvas_set_scroll_region:
3137 * @canvas: A canvas.
3138 * @x1: Leftmost limit of the scrolling region.
3139 * @y1: Upper limit of the scrolling region.
3140 * @x2: Rightmost limit of the scrolling region.
3141 * @y2: Lower limit of the scrolling region.
3142 *
3143 * Sets the scrolling region of a canvas to the specified rectangle. The canvas
3144 * will then be able to scroll only within this region. The view of the canvas
3145 * is adjusted as appropriate to display as much of the new region as possible.
3146 **/
3147void
3148eel_canvas_set_scroll_region (EelCanvas *canvas, double x1, double y1, double x2, double y2)
3149{
3150 double wxofs, wyofs;
3151 int xofs, yofs;
3152 GtkAdjustment *vadjustment, *hadjustment;
3153
3154 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_178
= 1; else _g_boolean_var_178 = 0; _g_boolean_var_178; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3155
3156 if ((canvas->scroll_x1 == x1) && (canvas->scroll_y1 == y1) &&
3157 (canvas->scroll_x2 == x2) && (canvas->scroll_y2 == y2))
3158 {
3159 return;
3160 }
3161
3162 /*
3163 * Set the new scrolling region. If possible, do not move the visible contents of the
3164 * canvas.
3165 */
3166 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3167 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3168
3169 eel_canvas_c2w (canvas,
3170 gtk_adjustment_get_value (hadjustment) + canvas->zoom_xofs,
3171 gtk_adjustment_get_value (vadjustment) + canvas->zoom_yofs,
3172 /*canvas->zoom_xofs,
3173 canvas->zoom_yofs,*/
3174 &wxofs, &wyofs);
3175
3176 canvas->scroll_x1 = x1;
3177 canvas->scroll_y1 = y1;
3178 canvas->scroll_x2 = x2;
3179 canvas->scroll_y2 = y2;
3180
3181 eel_canvas_w2c (canvas, wxofs, wyofs, &xofs, &yofs);
3182
3183 scroll_to (canvas, xofs, yofs);
3184
3185 canvas->need_repick = TRUE(!(0));
3186
3187 if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
3188 {
3189 canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
3190 eel_canvas_request_update (canvas);
3191 }
3192}
3193
3194
3195/**
3196 * eel_canvas_get_scroll_region:
3197 * @canvas: A canvas.
3198 * @x1: Leftmost limit of the scrolling region (return value).
3199 * @y1: Upper limit of the scrolling region (return value).
3200 * @x2: Rightmost limit of the scrolling region (return value).
3201 * @y2: Lower limit of the scrolling region (return value).
3202 *
3203 * Queries the scrolling region of a canvas.
3204 **/
3205void
3206eel_canvas_get_scroll_region (EelCanvas *canvas, double *x1, double *y1, double *x2, double *y2)
3207{
3208 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_179
= 1; else _g_boolean_var_179 = 0; _g_boolean_var_179; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3209
3210 if (x1)
3211 *x1 = canvas->scroll_x1;
3212
3213 if (y1)
3214 *y1 = canvas->scroll_y1;
3215
3216 if (x2)
3217 *x2 = canvas->scroll_x2;
3218
3219 if (y2)
3220 *y2 = canvas->scroll_y2;
3221}
3222
3223void
3224eel_canvas_set_center_scroll_region (EelCanvas *canvas,
3225 gboolean center_scroll_region)
3226{
3227 GtkAdjustment *vadjustment, *hadjustment;
3228
3229 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_180
= 1; else _g_boolean_var_180 = 0; _g_boolean_var_180; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3230
3231 canvas->center_scroll_region = center_scroll_region != 0;
3232
3233 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (&canvas->layout)((((GtkScrollable*) (void *) ((&canvas->layout))))));
3234 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (&canvas->layout)((((GtkScrollable*) (void *) ((&canvas->layout))))));
3235
3236 scroll_to (canvas,
3237 gtk_adjustment_get_value (hadjustment),
3238 gtk_adjustment_get_value (vadjustment));
3239}
3240
3241
3242/**
3243 * eel_canvas_set_pixels_per_unit:
3244 * @canvas: A canvas.
3245 * @n: The number of pixels that correspond to one canvas unit.
3246 *
3247 * Sets the zooming factor of a canvas by specifying the number of pixels that
3248 * correspond to one canvas unit.
3249 **/
3250void
3251eel_canvas_set_pixels_per_unit (EelCanvas *canvas, double n)
3252{
3253 GtkWidget *widget;
3254 double cx, cy;
3255 int x1, y1;
3256 int center_x, center_y;
3257 GdkWindow *window;
3258 GdkWindowAttr attributes;
3259 gint attributes_mask;
3260 GtkAllocation allocation;
3261 GtkAdjustment *vadjustment, *hadjustment;
3262
3263 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3264 g_return_if_fail (n > EEL_CANVAS_EPSILON)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if (n > 1e-10) _g_boolean_var_182 = 1; else _g_boolean_var_182
= 0; _g_boolean_var_182; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "n > EEL_CANVAS_EPSILON"
); return; } } while (0)
;
3265
3266 widget = GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas)))));
3267
3268 gtk_widget_get_allocation (widget, &allocation);
3269 center_x = allocation.width / 2;
3270 center_y = allocation.height / 2;
3271
3272 /* Find the coordinates of the screen center in units. */
3273 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3274 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3275 cx = (gtk_adjustment_get_value (hadjustment) + center_x) / canvas->pixels_per_unit + canvas->scroll_x1 + canvas->zoom_xofs;
3276 cy = (gtk_adjustment_get_value (vadjustment) + center_y) / canvas->pixels_per_unit + canvas->scroll_y1 + canvas->zoom_yofs;
3277
3278 /* Now calculate the new offset of the upper left corner. (round not truncate) */
3279 x1 = ((cx - canvas->scroll_x1) * n) - center_x + .5;
3280 y1 = ((cy - canvas->scroll_y1) * n) - center_y + .5;
3281
3282 canvas->pixels_per_unit = n;
3283
3284 if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE))
3285 {
3286 canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE;
3287 eel_canvas_request_update (canvas);
3288 }
3289
3290 /* Map a background None window over the bin_window to avoid
3291 * scrolling the window scroll causing exposes.
3292 */
3293 window = NULL((void*)0);
3294 if (gtk_widget_get_mapped (widget))
3295 {
3296 attributes.window_type = GDK_WINDOW_CHILD;
3297 gtk_widget_get_allocation (widget, &allocation);
3298 attributes.x = allocation.x;
3299 attributes.y = allocation.y;
3300 attributes.width = allocation.width;
3301 attributes.height = allocation.height;
3302 attributes.wclass = GDK_INPUT_OUTPUT;
3303 attributes.visual = gtk_widget_get_visual (widget);
3304 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
3305
3306 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
3307
3308 window = gdk_window_new (gtk_widget_get_parent_window (widget),
3309 &attributes, attributes_mask);
3310
3311 gdk_window_set_user_data (window, widget);
3312
3313 gdk_window_show (window);
3314 }
3315
3316 scroll_to (canvas, x1, y1);
3317
3318 /* If we created a an overlapping background None window, remove it how.
3319 *
3320 * TODO: We would like to temporarily set the bin_window background to
3321 * None to avoid clearing the bin_window to the background, but gdk doesn't
3322 * expose enought to let us do this, so we get a flash-effect here. At least
3323 * it looks better than scroll + expose.
3324 */
3325 if (window != NULL((void*)0))
3326 {
3327 gdk_window_hide (window);
3328 gdk_window_set_user_data (window, NULL((void*)0));
3329 gdk_window_destroy (window);
3330 }
3331
3332 canvas->need_repick = TRUE(!(0));
3333}
3334
3335/**
3336 * eel_canvas_scroll_to:
3337 * @canvas: A canvas.
3338 * @cx: Horizontal scrolling offset in canvas pixel units.
3339 * @cy: Vertical scrolling offset in canvas pixel units.
3340 *
3341 * Makes a canvas scroll to the specified offsets, given in canvas pixel units.
3342 * The canvas will adjust the view so that it is not outside the scrolling
3343 * region. This function is typically not used, as it is better to hook
3344 * scrollbars to the canvas layout's scrolling adjusments.
3345 **/
3346void
3347eel_canvas_scroll_to (EelCanvas *canvas, int cx, int cy)
3348{
3349 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_183
= 1; else _g_boolean_var_183 = 0; _g_boolean_var_183; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3350
3351 scroll_to (canvas, cx, cy);
3352}
3353
3354/**
3355 * eel_canvas_get_scroll_offsets:
3356 * @canvas: A canvas.
3357 * @cx: Horizontal scrolling offset (return value).
3358 * @cy: Vertical scrolling offset (return value).
3359 *
3360 * Queries the scrolling offsets of a canvas. The values are returned in canvas
3361 * pixel units.
3362 **/
3363void
3364eel_canvas_get_scroll_offsets (EelCanvas *canvas, int *cx, int *cy)
3365{
3366 GtkAdjustment *vadjustment, *hadjustment;
3367
3368 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_184
= 1; else _g_boolean_var_184 = 0; _g_boolean_var_184; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3369
3370 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3371 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
3372
3373 if (cx)
3374 *cx = gtk_adjustment_get_value (hadjustment);
3375
3376 if (cy)
3377 *cy = gtk_adjustment_get_value (vadjustment);
3378}
3379
3380/**
3381 * eel_canvas_update_now:
3382 * @canvas: A canvas.
3383 *
3384 * Forces an immediate update and redraw of a canvas. If the canvas does not
3385 * have any pending update or redraw requests, then no action is taken. This is
3386 * typically only used by applications that need explicit control of when the
3387 * display is updated, like games. It is not needed by normal applications.
3388 */
3389void
3390eel_canvas_update_now (EelCanvas *canvas)
3391{
3392 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_185
= 1; else _g_boolean_var_185 = 0; _g_boolean_var_185; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3393
3394 if (!(canvas->need_update || canvas->need_redraw))
3395 return;
3396 remove_idle (canvas);
3397 do_update (canvas);
3398}
3399
3400/**
3401 * eel_canvas_get_item_at:
3402 * @canvas: A canvas.
3403 * @x: X position in world coordinates.
3404 * @y: Y position in world coordinates.
3405 *
3406 * Looks for the item that is under the specified position, which must be
3407 * specified in world coordinates.
3408 *
3409 * Return value: The sought item, or NULL if no item is at the specified
3410 * coordinates.
3411 **/
3412EelCanvasItem *
3413eel_canvas_get_item_at (EelCanvas *canvas, double x, double y)
3414{
3415 EelCanvasItem *item = NULL((void*)0);
3416 double dist;
3417 int cx, cy;
3418
3419 g_return_val_if_fail (EEL_IS_CANVAS (canvas), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return (((void*)0));
} } while (0)
;
3420
3421 eel_canvas_w2c (canvas, x, y, &cx, &cy);
3422
3423 dist = eel_canvas_item_invoke_point (canvas->root, x, y, cx, cy, &item);
3424 if ((int) (dist * canvas->pixels_per_unit + 0.5) <= canvas->close_enough)
3425 return item;
3426 else
3427 return NULL((void*)0);
3428}
3429
3430/* Queues an update of the canvas */
3431static void
3432eel_canvas_request_update (EelCanvas *canvas)
3433{
3434 EEL_CANVAS_GET_CLASS (canvas)((((EelCanvasClass*) (((GTypeInstance*) ((canvas)))->g_class
))))
->request_update (canvas);
3435}
3436
3437static void
3438eel_canvas_request_update_real (EelCanvas *canvas)
3439{
3440 canvas->need_update = TRUE(!(0));
3441 add_idle (canvas);
3442}
3443
3444/**
3445 * eel_canvas_request_redraw:
3446 * @canvas: A canvas.
3447 * @x1: Leftmost coordinate of the rectangle to be redrawn.
3448 * @y1: Upper coordinate of the rectangle to be redrawn.
3449 * @x2: Rightmost coordinate of the rectangle to be redrawn, plus 1.
3450 * @y2: Lower coordinate of the rectangle to be redrawn, plus 1.
3451 *
3452 * Convenience function that informs a canvas that the specified rectangle needs
3453 * to be repainted. The rectangle includes @x1 and @y1, but not @x2 and @y2.
3454 * To be used only by item implementations.
3455 **/
3456void
3457eel_canvas_request_redraw (EelCanvas *canvas, int x1, int y1, int x2, int y2)
3458{
3459 GdkRectangle bbox;
3460
3461 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3462
3463 if (!gtk_widget_is_drawable (GTK_WIDGET (canvas)((((GtkWidget*) (void *) ((canvas))))))
3464 || (x1 >= x2) || (y1 >= y2)) return;
3465
3466 bbox.x = x1;
3467 bbox.y = y1;
3468 bbox.width = x2 - x1;
3469 bbox.height = y2 - y1;
3470
3471 gdk_window_invalidate_rect (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)((((GtkLayout*) (void *) ((canvas)))))),
3472 &bbox, FALSE(0));
3473}
3474
3475/**
3476 * eel_canvas_w2c:
3477 * @canvas: A canvas.
3478 * @wx: World X coordinate.
3479 * @wy: World Y coordinate.
3480 * @cx: X pixel coordinate (return value).
3481 * @cy: Y pixel coordinate (return value).
3482 *
3483 * Converts world coordinates into canvas pixel coordinates.
3484 **/
3485void
3486eel_canvas_w2c (EelCanvas *canvas, double wx, double wy, int *cx, int *cy)
3487{
3488 double zoom;
3489
3490 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3491
3492 zoom = canvas->pixels_per_unit;
3493
3494 if (cx)
3495 *cx = floor ((wx - canvas->scroll_x1)*zoom + canvas->zoom_xofs + 0.5);
3496 if (cy)
3497 *cy = floor ((wy - canvas->scroll_y1)*zoom + canvas->zoom_yofs + 0.5);
3498}
3499
3500/**
3501 * eel_canvas_w2c:
3502 * @canvas: A canvas.
3503 * @world: rectangle in world coordinates.
3504 * @canvas: rectangle in canvase coordinates.
3505 *
3506 * Converts rectangles in world coordinates into canvas pixel coordinates.
3507 **/
3508void
3509eel_canvas_w2c_rect_d (EelCanvas *canvas,
3510 double *x1, double *y1,
3511 double *x2, double *y2)
3512{
3513 eel_canvas_w2c_d (canvas,
3514 *x1, *y1,
3515 x1, y1);
3516 eel_canvas_w2c_d (canvas,
3517 *x2, *y2,
3518 x2, y2);
3519}
3520
3521
3522
3523/**
3524 * eel_canvas_w2c_d:
3525 * @canvas: A canvas.
3526 * @wx: World X coordinate.
3527 * @wy: World Y coordinate.
3528 * @cx: X pixel coordinate (return value).
3529 * @cy: Y pixel coordinate (return value).
3530 *
3531 * Converts world coordinates into canvas pixel coordinates. This version
3532 * produces coordinates in floating point coordinates, for greater precision.
3533 **/
3534void
3535eel_canvas_w2c_d (EelCanvas *canvas, double wx, double wy, double *cx, double *cy)
3536{
3537 double zoom;
3538
3539 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_189
= 1; else _g_boolean_var_189 = 0; _g_boolean_var_189; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3540
3541 zoom = canvas->pixels_per_unit;
3542
3543 if (cx)
3544 *cx = (wx - canvas->scroll_x1)*zoom + canvas->zoom_xofs;
3545 if (cy)
3546 *cy = (wy - canvas->scroll_y1)*zoom + canvas->zoom_yofs;
3547}
3548
3549
3550/**
3551 * eel_canvas_c2w:
3552 * @canvas: A canvas.
3553 * @cx: Canvas pixel X coordinate.
3554 * @cy: Canvas pixel Y coordinate.
3555 * @wx: X world coordinate (return value).
3556 * @wy: Y world coordinate (return value).
3557 *
3558 * Converts canvas pixel coordinates to world coordinates.
3559 **/
3560void
3561eel_canvas_c2w (EelCanvas *canvas, int cx, int cy, double *wx, double *wy)
3562{
3563 double zoom;
3564
3565 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3566
3567 zoom = canvas->pixels_per_unit;
3568
3569 if (wx)
3570 *wx = (cx - canvas->zoom_xofs)/zoom + canvas->scroll_x1;
3571 if (wy)
3572 *wy = (cy - canvas->zoom_yofs)/zoom + canvas->scroll_y1;
3573}
3574
3575
3576/**
3577 * eel_canvas_window_to_world:
3578 * @canvas: A canvas.
3579 * @winx: Window-relative X coordinate.
3580 * @winy: Window-relative Y coordinate.
3581 * @worldx: X world coordinate (return value).
3582 * @worldy: Y world coordinate (return value).
3583 *
3584 * Converts window-relative coordinates into world coordinates. You can use
3585 * this when you need to convert mouse coordinates into world coordinates, for
3586 * example.
3587 * Window coordinates are really the same as canvas coordinates now, but this
3588 * function is here for backwards compatibility reasons.
3589 **/
3590void
3591eel_canvas_window_to_world (EelCanvas *canvas, double winx, double winy,
3592 double *worldx, double *worldy)
3593{
3594 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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_191
= 1; else _g_boolean_var_191 = 0; _g_boolean_var_191; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3595
3596 if (worldx)
3597 *worldx = canvas->scroll_x1 + ((winx - canvas->zoom_xofs)
3598 / canvas->pixels_per_unit);
3599
3600 if (worldy)
3601 *worldy = canvas->scroll_y1 + ((winy - canvas->zoom_yofs)
3602 / canvas->pixels_per_unit);
3603}
3604
3605
3606/**
3607 * eel_canvas_world_to_window:
3608 * @canvas: A canvas.
3609 * @worldx: World X coordinate.
3610 * @worldy: World Y coordinate.
3611 * @winx: X window-relative coordinate.
3612 * @winy: Y window-relative coordinate.
3613 *
3614 * Converts world coordinates into window-relative coordinates.
3615 * Window coordinates are really the same as canvas coordinates now, but this
3616 * function is here for backwards compatibility reasons.
3617 **/
3618void
3619eel_canvas_world_to_window (EelCanvas *canvas, double worldx, double worldy,
3620 double *winx, double *winy)
3621{
3622 g_return_if_fail (EEL_IS_CANVAS (canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((canvas)); GType __t = ((eel_canvas_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 ("Eel", ((const char*)
(__func__)), "EEL_IS_CANVAS (canvas)"); return; } } while (0
)
;
3623
3624 if (winx)
3625 *winx = (canvas->pixels_per_unit)*(worldx - canvas->scroll_x1) + canvas->zoom_xofs;
3626
3627 if (winy)
3628 *winy = (canvas->pixels_per_unit)*(worldy - canvas->scroll_y1) + canvas->zoom_yofs;
3629}
3630
3631static gboolean
3632boolean_handled_accumulator (GSignalInvocationHint *ihint,
3633 GValue *return_accu,
3634 const GValue *handler_return,
3635 gpointer dummy)
3636{
3637 gboolean continue_emission;
3638 gboolean signal_handled;
3639
3640 signal_handled = g_value_get_boolean (handler_return);
3641 g_value_set_boolean (return_accu, signal_handled);
3642 continue_emission = !signal_handled;
3643
3644 return continue_emission;
3645}
3646
3647static guint
3648eel_canvas_item_accessible_add_focus_handler (AtkComponent *component,
3649 AtkFocusHandler handler)
3650{
3651 GSignalMatchType match_type;
3652 guint signal_id;
3653
3654 match_type = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC;
3655 signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT(atk_object_get_type ()));
3656
3657 if (!g_signal_handler_find (component, match_type, signal_id, 0, NULL((void*)0),
3658 (gpointer) handler, NULL((void*)0)))
3659 {
3660 return g_signal_connect_closure_by_id (component,
3661 signal_id, 0,
3662 g_cclosure_new (
3663 G_CALLBACK (handler)((GCallback) (handler)), NULL((void*)0),
3664 (GClosureNotify) NULL((void*)0)),
3665 FALSE(0));
3666 }
3667 return 0;
3668}
3669
3670static void
3671eel_canvas_item_accessible_get_item_extents (EelCanvasItem *item,
3672 GdkRectangle *rect)
3673{
3674 double bx1, bx2, by1, by2;
3675 gint scroll_x, scroll_y;
3676 gint x1, x2, y1, y2;
3677
3678 eel_canvas_item_get_bounds (item, &bx1, &by1, &bx2, &by2);
3679 eel_canvas_w2c_rect_d (item->canvas, &bx1, &by1, &bx2, &by2);
3680 eel_canvas_get_scroll_offsets (item->canvas, &scroll_x, &scroll_y);
3681 x1 = floor (bx1 + .5);
3682 y1 = floor (by1 + .5);
3683 x2 = floor (bx2 + .5);
3684 y2 = floor (by2 + .5);
3685 rect->x = x1 - scroll_x;
3686 rect->y = y1 - scroll_y;
3687 rect->width = x2 - x1;
3688 rect->height = y2 - y1;
3689}
3690
3691static gboolean
3692eel_canvas_item_accessible_is_item_in_window (EelCanvasItem *item,
3693 GdkRectangle *rect)
3694{
3695 GtkWidget *widget;
3696 gboolean retval;
3697
3698 widget = GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))));
3699 if (gtk_widget_get_window (widget))
3700 {
3701 int window_width, window_height;
3702
3703 gdk_window_get_geometry (gtk_widget_get_window (widget), NULL((void*)0), NULL((void*)0),
3704 &window_width, &window_height);
3705 /*
3706 * Check whether rectangles intersect
3707 */
3708 if (rect->x + rect->width < 0 ||
3709 rect->y + rect->height < 0 ||
3710 rect->x > window_width ||
3711 rect->y > window_height)
3712 {
3713 retval = FALSE(0);
3714 }
3715 else
3716 {
3717 retval = TRUE(!(0));
3718 }
3719 }
3720 else
3721 {
3722 retval = FALSE(0);
3723 }
3724 return retval;
3725}
3726
3727
3728static void
3729eel_canvas_item_accessible_get_extents (AtkComponent *component,
3730 gint *x,
3731 gint *y,
3732 gint *width,
3733 gint *height,
3734 AtkCoordType coord_type)
3735{
3736 AtkGObjectAccessible *atk_gobj;
3737 GObject *obj;
3738 EelCanvasItem *item;
3739 gint window_x, window_y;
3740 gint toplevel_x, toplevel_y;
3741 GdkRectangle rect;
3742 GdkWindow *window;
3743 GtkWidget *canvas;
3744
3745 atk_gobj = ATK_GOBJECT_ACCESSIBLE (component)((((AtkGObjectAccessible*) (void *) ((component)))));
3746 obj = atk_gobject_accessible_get_object (atk_gobj);
3747
3748 if (obj == NULL((void*)0))
3749 {
3750 /* item is defunct */
3751 return;
3752 }
3753
3754 /* Get the CanvasItem */
3755 item = EEL_CANVAS_ITEM (obj)((((EelCanvasItem*) (void *) ((obj)))));
3756
3757 /* If this item has no parent canvas, something's broken */
3758 g_return_if_fail (GTK_IS_WIDGET (item->canvas))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item->canvas)); GType __t = ((gtk_widget_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_193 = 1; else _g_boolean_var_193 =
0; _g_boolean_var_193; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "GTK_IS_WIDGET (item->canvas)"
); return; } } while (0)
;
3759
3760 eel_canvas_item_accessible_get_item_extents (item, &rect);
3761 *width = rect.width;
3762 *height = rect.height;
3763 if (!eel_canvas_item_accessible_is_item_in_window (item, &rect))
3764 {
3765 *x = G_MININT(-2147483647 -1);
3766 *y = G_MININT(-2147483647 -1);
3767 return;
3768 }
3769
3770 canvas = GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))));
3771 window = gtk_widget_get_parent_window (canvas);
3772 gdk_window_get_origin (window, &window_x, &window_y);
3773 *x = rect.x + window_x;
3774 *y = rect.y + window_y;
3775 if (coord_type == ATK_XY_WINDOW)
3776 {
3777 window = gdk_window_get_toplevel (gtk_widget_get_window (canvas));
3778 gdk_window_get_origin (window, &toplevel_x, &toplevel_y);
3779 *x -= toplevel_x;
3780 *y -= toplevel_y;
3781 }
3782 return;
3783}
3784
3785static gint
3786eel_canvas_item_accessible_get_mdi_zorder (AtkComponent *component)
3787{
3788 AtkGObjectAccessible *atk_gobj;
3789 GObject *g_obj;
3790 EelCanvasItem *item;
3791
3792 atk_gobj = ATK_GOBJECT_ACCESSIBLE (component)((((AtkGObjectAccessible*) (void *) ((component)))));
3793 g_obj = atk_gobject_accessible_get_object (atk_gobj);
3794 if (g_obj == NULL((void*)0))
3795 {
3796 /* Object is defunct */
3797 return -1;
3798 }
3799
3800 item = EEL_CANVAS_ITEM (g_obj)((((EelCanvasItem*) (void *) ((g_obj)))));
3801 if (item->parent)
3802 {
3803 return g_list_index (EEL_CANVAS_GROUP (item->parent)((((EelCanvasGroup*) (void *) ((item->parent)))))->item_list, item);
3804 }
3805 else
3806 {
3807 g_return_val_if_fail (item->canvas->root == item, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (item->canvas->root == item) _g_boolean_var_194 = 1
; else _g_boolean_var_194 = 0; _g_boolean_var_194; }), 1))) {
} else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "item->canvas->root == item"); return (-1); } } while
(0)
;
3808 return 0;
3809 }
3810}
3811
3812static gboolean
3813eel_canvas_item_accessible_grab_focus (AtkComponent *component)
3814{
3815 AtkGObjectAccessible *atk_gobj;
3816 GObject *obj;
3817 EelCanvasItem *item;
3818 GtkWidget *toplevel;
3819
3820 atk_gobj = ATK_GOBJECT_ACCESSIBLE (component)((((AtkGObjectAccessible*) (void *) ((component)))));
3821 obj = atk_gobject_accessible_get_object (atk_gobj);
3822
3823 item = EEL_CANVAS_ITEM (obj)((((EelCanvasItem*) (void *) ((obj)))));
3824 if (item == NULL((void*)0))
3825 {
3826 /* item is defunct */
3827 return FALSE(0);
3828 }
3829
3830 eel_canvas_item_grab_focus (item);
3831 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas))))));
3832 if (gtk_widget_is_toplevel (toplevel))
3833 {
3834 gtk_window_present (GTK_WINDOW (toplevel)((((GtkWindow*) (void *) ((toplevel))))));
3835 }
3836
3837 return TRUE(!(0));
3838}
3839
3840static void
3841eel_canvas_item_accessible_remove_focus_handler (AtkComponent *component,
3842 guint handler_id)
3843{
3844 g_signal_handler_disconnect (component, handler_id);
3845}
3846
3847static void
3848eel_canvas_item_accessible_component_interface_init (AtkComponentIface *iface)
3849{
3850 g_return_if_fail (iface != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if (iface != ((void*)0)) _g_boolean_var_195 = 1; else _g_boolean_var_195
= 0; _g_boolean_var_195; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "iface != NULL"); return
; } } while (0)
;
3851
3852 iface->add_focus_handler = eel_canvas_item_accessible_add_focus_handler;
3853 iface->get_extents = eel_canvas_item_accessible_get_extents;
3854 iface->get_mdi_zorder = eel_canvas_item_accessible_get_mdi_zorder;
3855 iface->grab_focus = eel_canvas_item_accessible_grab_focus;
3856 iface->remove_focus_handler = eel_canvas_item_accessible_remove_focus_handler;
3857}
3858
3859static gboolean
3860eel_canvas_item_accessible_is_item_on_screen (EelCanvasItem *item)
3861{
3862 GdkRectangle rect;
3863
3864 eel_canvas_item_accessible_get_item_extents (item, &rect);
3865 return eel_canvas_item_accessible_is_item_in_window (item, &rect);
3866}
3867
3868static void
3869eel_canvas_item_accessible_initialize (AtkObject *obj, gpointer data)
3870{
3871 if (ATK_OBJECT_CLASS (accessible_item_parent_class)((((AtkObjectClass*) (void *) ((accessible_item_parent_class)
))))
->initialize != NULL((void*)0))
3872 ATK_OBJECT_CLASS (accessible_item_parent_class)((((AtkObjectClass*) (void *) ((accessible_item_parent_class)
))))
->initialize (obj, data);
3873 g_object_set_data (G_OBJECT (obj)((((GObject*) (void *) ((obj))))), "atk-component-layer",
3874 GINT_TO_POINTER (ATK_LAYER_MDI)((gpointer) (glong) (ATK_LAYER_MDI)));
3875}
3876
3877static AtkStateSet*
3878eel_canvas_item_accessible_ref_state_set (AtkObject *accessible)
3879{
3880 AtkGObjectAccessible *atk_gobj;
3881 GObject *obj;
3882 EelCanvasItem *item;
3883 AtkStateSet *state_set;
3884
3885 state_set = ATK_OBJECT_CLASS (accessible_item_parent_class)((((AtkObjectClass*) (void *) ((accessible_item_parent_class)
))))
->ref_state_set (accessible);
3886 atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible)((((AtkGObjectAccessible*) (void *) ((accessible)))));
3887 obj = atk_gobject_accessible_get_object (atk_gobj);
3888
3889 item = EEL_CANVAS_ITEM (obj)((((EelCanvasItem*) (void *) ((obj)))));
3890 if (item == NULL((void*)0))
3891 {
3892 atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
3893 }
3894 else
3895 {
3896 if (item->flags & EEL_CANVAS_ITEM_VISIBLE)
3897 {
3898 atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
3899
3900 if (eel_canvas_item_accessible_is_item_on_screen (item))
3901 {
3902 atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
3903 }
3904 }
3905 if (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas)((((GtkWidget*) (void *) ((item->canvas)))))))
3906 {
3907 atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
3908
3909 if (item->canvas->focused_item == item)
3910 {
3911 atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
3912 }
3913 }
3914 }
3915
3916 return state_set;
3917}
3918
3919G_DEFINE_TYPE_WITH_CODE (EelCanvasItemAccessible,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3920 eel_canvas_item_accessible,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3921 ATK_TYPE_GOBJECT_ACCESSIBLE,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3922 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT,static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
3923 eel_canvas_item_accessible_component_interface_init))static void eel_canvas_item_accessible_init (EelCanvasItemAccessible
*self); static void eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass
*klass); static GType eel_canvas_item_accessible_get_type_once
(void); static gpointer eel_canvas_item_accessible_parent_class
= ((void*)0); static gint EelCanvasItemAccessible_private_offset
; static void eel_canvas_item_accessible_class_intern_init (gpointer
klass) { eel_canvas_item_accessible_parent_class = g_type_class_peek_parent
(klass); if (EelCanvasItemAccessible_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelCanvasItemAccessible_private_offset); eel_canvas_item_accessible_class_init
((EelCanvasItemAccessibleClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_canvas_item_accessible_get_instance_private
(EelCanvasItemAccessible *self) { return (((gpointer) ((guint8
*) (self) + (glong) (EelCanvasItemAccessible_private_offset))
)); } GType eel_canvas_item_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_gobject_accessible_get_type ()), g_intern_static_string
("EelCanvasItemAccessible"), sizeof (EelCanvasItemAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_canvas_item_accessible_class_intern_init
, sizeof (EelCanvasItemAccessible), (GInstanceInitFunc)(void (
*)(void)) eel_canvas_item_accessible_init, (GTypeFlags) 0); {
{{ const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_component_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_component_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
3924
3925static void
3926eel_canvas_item_accessible_class_init (EelCanvasItemAccessibleClass *klass)
3927{
3928 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
3929 accessible_item_parent_class = g_type_class_peek_parent (atk_class);
3930
3931 atk_class->initialize = eel_canvas_item_accessible_initialize;
3932 atk_class->ref_state_set = eel_canvas_item_accessible_ref_state_set;
3933}
3934
3935static void
3936eel_canvas_item_accessible_init (EelCanvasItemAccessible *accessible)
3937{
3938}
3939
3940static AtkObject *
3941eel_canvas_item_accessible_create (GObject *for_object)
3942{
3943 GType type;
3944 AtkObject *accessible;
3945 EelCanvasItem *item;
3946
3947 item = EEL_CANVAS_ITEM (for_object)((((EelCanvasItem*) (void *) ((for_object)))));
3948 g_return_val_if_fail (item != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if (item != ((void*)0)) _g_boolean_var_196 = 1; else _g_boolean_var_196
= 0; _g_boolean_var_196; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "item != NULL"); return (
((void*)0)); } } while (0)
;
3949
3950 type = eel_canvas_item_accessible_get_type ();
3951 if (type == G_TYPE_INVALID((GType) ((0) << (2))))
3952 {
3953 return atk_no_op_object_new (for_object);
3954 }
3955
3956 accessible = g_object_new (type, NULL((void*)0));
3957 atk_object_initialize (accessible, for_object);
3958 return accessible;
3959}
3960
3961static GType
3962eel_canvas_item_accessible_factory_get_accessible_type (void)
3963{
3964 return eel_canvas_item_accessible_get_type ();
3965}
3966
3967static AtkObject*
3968eel_canvas_item_accessible_factory_create_accessible (GObject *obj)
3969{
3970 AtkObject *accessible;
3971
3972 g_return_val_if_fail (G_IS_OBJECT (obj), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if ((((g_type_check_instance_is_fundamentally_a ((GTypeInstance
*) ((obj)), (((GType) ((20) << (2))))))))) _g_boolean_var_197
= 1; else _g_boolean_var_197 = 0; _g_boolean_var_197; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "G_IS_OBJECT (obj)"); return (((void*)0)); } } while
(0)
;
3973
3974 accessible = eel_canvas_item_accessible_create (obj);
3975
3976 return accessible;
3977}
3978
3979static GType eel_canvas_item_accessible_factory_get_type (void);
3980
3981typedef AtkObjectFactory EelCanvasItemAccessibleFactory;
3982typedef AtkObjectFactoryClass EelCanvasItemAccessibleFactoryClass;
3983G_DEFINE_TYPE (EelCanvasItemAccessibleFactory, eel_canvas_item_accessible_factory,static void eel_canvas_item_accessible_factory_init (EelCanvasItemAccessibleFactory
*self); static void eel_canvas_item_accessible_factory_class_init
(EelCanvasItemAccessibleFactoryClass *klass); static GType eel_canvas_item_accessible_factory_get_type_once
(void); static gpointer eel_canvas_item_accessible_factory_parent_class
= ((void*)0); static gint EelCanvasItemAccessibleFactory_private_offset
; static void eel_canvas_item_accessible_factory_class_intern_init
(gpointer klass) { eel_canvas_item_accessible_factory_parent_class
= g_type_class_peek_parent (klass); if (EelCanvasItemAccessibleFactory_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelCanvasItemAccessibleFactory_private_offset
); eel_canvas_item_accessible_factory_class_init ((EelCanvasItemAccessibleFactoryClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_canvas_item_accessible_factory_get_instance_private (EelCanvasItemAccessibleFactory
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelCanvasItemAccessibleFactory_private_offset
)))); } GType eel_canvas_item_accessible_factory_get_type (void
) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_factory_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_factory_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_object_factory_get_type ()), g_intern_static_string ("EelCanvasItemAccessibleFactory"
), sizeof (EelCanvasItemAccessibleFactoryClass), (GClassInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_class_intern_init
, sizeof (EelCanvasItemAccessibleFactory), (GInstanceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_init, (GTypeFlags
) 0); { {{};} } return g_define_type_id; }
3984 ATK_TYPE_OBJECT_FACTORY)static void eel_canvas_item_accessible_factory_init (EelCanvasItemAccessibleFactory
*self); static void eel_canvas_item_accessible_factory_class_init
(EelCanvasItemAccessibleFactoryClass *klass); static GType eel_canvas_item_accessible_factory_get_type_once
(void); static gpointer eel_canvas_item_accessible_factory_parent_class
= ((void*)0); static gint EelCanvasItemAccessibleFactory_private_offset
; static void eel_canvas_item_accessible_factory_class_intern_init
(gpointer klass) { eel_canvas_item_accessible_factory_parent_class
= g_type_class_peek_parent (klass); if (EelCanvasItemAccessibleFactory_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelCanvasItemAccessibleFactory_private_offset
); eel_canvas_item_accessible_factory_class_init ((EelCanvasItemAccessibleFactoryClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_canvas_item_accessible_factory_get_instance_private (EelCanvasItemAccessibleFactory
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelCanvasItemAccessibleFactory_private_offset
)))); } GType eel_canvas_item_accessible_factory_get_type (void
) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_canvas_item_accessible_factory_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_canvas_item_accessible_factory_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((atk_object_factory_get_type ()), g_intern_static_string ("EelCanvasItemAccessibleFactory"
), sizeof (EelCanvasItemAccessibleFactoryClass), (GClassInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_class_intern_init
, sizeof (EelCanvasItemAccessibleFactory), (GInstanceInitFunc
)(void (*)(void)) eel_canvas_item_accessible_factory_init, (GTypeFlags
) 0); { {{};} } return g_define_type_id; }
3985
3986static void
3987eel_canvas_item_accessible_factory_class_init (AtkObjectFactoryClass *klass)
3988{
3989 klass->create_accessible = eel_canvas_item_accessible_factory_create_accessible;
3990 klass->get_accessible_type = eel_canvas_item_accessible_factory_get_accessible_type;
3991}
3992
3993static void
3994eel_canvas_item_accessible_factory_init (EelCanvasItemAccessibleFactory *accessible)
3995{
3996}
3997
3998/* Class initialization function for EelCanvasItemClass */
3999static void
4000eel_canvas_item_class_init (EelCanvasItemClass *klass)
4001{
4002 GObjectClass *gobject_class = (GObjectClass *) klass;
4003
4004 item_parent_class = g_type_class_peek_parent (klass);
4005
4006 gobject_class->set_property = eel_canvas_item_set_property;
4007 gobject_class->get_property = eel_canvas_item_get_property;
4008 gobject_class->dispose = eel_canvas_item_dispose;
4009
4010 g_object_class_install_property
4011 (gobject_class, ITEM_PROP_PARENT,
4012 g_param_spec_object ("parent", NULL((void*)0), NULL((void*)0),
4013 EEL_TYPE_CANVAS_ITEM(eel_canvas_item_get_type ()),
4014 G_PARAM_READWRITE));
4015
4016 g_object_class_install_property
4017 (gobject_class, ITEM_PROP_VISIBLE,
4018 g_param_spec_boolean ("visible", NULL((void*)0), NULL((void*)0),
4019 TRUE(!(0)),
4020 G_PARAM_READWRITE));
4021
4022 item_signals[ITEM_EVENT] =
4023 g_signal_new ("event",
4024 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
4025 G_SIGNAL_RUN_LAST,
4026 G_STRUCT_OFFSET (EelCanvasItemClass, event)((glong) __builtin_offsetof(EelCanvasItemClass, event)),
4027 boolean_handled_accumulator, NULL((void*)0),
4028 eel_marshal_BOOLEAN__BOXED,
4029 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1,
4030 GDK_TYPE_EVENT(gdk_event_get_type ()) | G_SIGNAL_TYPE_STATIC_SCOPE(((GType) (1 << 0))));
4031
4032 item_signals[ITEM_DESTROY] =
4033 g_signal_new ("destroy",
4034 G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type),
4035 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
4036 G_STRUCT_OFFSET (EelCanvasItemClass, destroy)((glong) __builtin_offsetof(EelCanvasItemClass, destroy)),
4037 NULL((void*)0), NULL((void*)0),
4038 g_cclosure_marshal_VOID__VOID,
4039 G_TYPE_NONE((GType) ((1) << (2))), 0);
4040
4041 klass->realize = eel_canvas_item_realize;
4042 klass->unrealize = eel_canvas_item_unrealize;
4043 klass->map = eel_canvas_item_map;
4044 klass->unmap = eel_canvas_item_unmap;
4045 klass->update = eel_canvas_item_update;
4046
4047 atk_registry_set_factory_type (atk_get_default_registry (),
4048 EEL_TYPE_CANVAS_ITEM(eel_canvas_item_get_type ()),
4049 eel_canvas_item_accessible_factory_get_type ());
4050}
diff --git a/2024-07-29-023715-6438-1/report-9f0261.html b/2024-07-29-023715-6438-1/report-9f0261.html new file mode 100644 index 000000000..866c0de00 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-9f0261.html @@ -0,0 +1,9689 @@ + + + +caja-file.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file.c
Warning:line 3387, column 6
Access of 'char' element in the region at index -1
+ +

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 caja-file.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-file.c: Caja file model.
4
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <grp.h>
27#include <gtk/gtk.h>
28#include <glib/gi18n.h>
29#include <glib/gstdio.h>
30#include <gio/gio.h>
31#include <glib.h>
32#include <libxml/parser.h>
33#include <pwd.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <sys/time.h>
37#include <time.h>
38#include <unistd.h>
39#include <sys/stat.h>
40
41#include <eel/eel-debug.h>
42#include <eel/eel-glib-extensions.h>
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-vfs-extensions.h>
45#include <eel/eel-gtk-macros.h>
46#include <eel/eel-string.h>
47
48#include <libcaja-extension/caja-file-info.h>
49#include <libcaja-extension/caja-extension-private.h>
50#include <libcaja-private/caja-extensions.h>
51
52#include "caja-file.h"
53#include "caja-directory-notify.h"
54#include "caja-directory-private.h"
55#include "caja-signaller.h"
56#include "caja-desktop-directory.h"
57#include "caja-desktop-directory-file.h"
58#include "caja-desktop-icon-file.h"
59#include "caja-file-attributes.h"
60#include "caja-file-private.h"
61#include "caja-file-operations.h"
62#include "caja-file-utilities.h"
63#include "caja-global-preferences.h"
64#include "caja-lib-self-check-functions.h"
65#include "caja-link.h"
66#include "caja-metadata.h"
67#include "caja-module.h"
68#include "caja-search-directory.h"
69#include "caja-search-directory-file.h"
70#include "caja-thumbnails.h"
71#include "caja-ui-utilities.h"
72#include "caja-vfs-file.h"
73#include "caja-saved-search-file.h"
74
75#ifdef HAVE_SELINUX1
76#include <selinux/selinux.h>
77#endif
78
79#define ICON_NAME_THUMBNAIL_LOADING"image-loading" "image-loading"
80
81#undef CAJA_FILE_DEBUG_REF
82#undef CAJA_FILE_DEBUG_REF_VALGRIND
83
84#ifdef CAJA_FILE_DEBUG_REF_VALGRIND
85#include <valgrind/valgrind.h>
86#define DEBUG_REF_PRINTFprintf VALGRIND_PRINTF_BACKTRACE
87#else
88#define DEBUG_REF_PRINTFprintf printf
89#endif
90
91/* Files that start with these characters sort after files that don't. */
92#define SORT_LAST_CHAR1'.' '.'
93#define SORT_LAST_CHAR2'#' '#'
94
95#define METADATA_ID_IS_LIST_MASK(1U<<31) (1U<<31)
96
97#define SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3 3
98#define SORT_BY_EXTENSION_MAX_SEGMENTS3 3
99
100typedef enum {
101 SHOW_HIDDEN = 1 << 0,
102 SHOW_BACKUP = 1 << 1,
103} FilterOptions;
104
105typedef void (* ModifyListFunction) (GList **list, CajaFile *file);
106
107enum {
108 CHANGED,
109 UPDATED_DEEP_COUNT_IN_PROGRESS,
110 LAST_SIGNAL
111};
112
113static int date_format_pref;
114
115static guint signals[LAST_SIGNAL] = { 0 };
116
117static GHashTable *symbolic_links;
118
119static GQuark attribute_name_q,
120 attribute_size_q,
121 attribute_size_on_disk_q,
122 attribute_type_q,
123 attribute_creation_date_q,
124 attribute_date_created_q,
125 attribute_modification_date_q,
126 attribute_date_modified_q,
127 attribute_accessed_date_q,
128 attribute_date_accessed_q,
129 attribute_emblems_q,
130 attribute_extension_q,
131 attribute_mime_type_q,
132 attribute_size_detail_q,
133 attribute_size_on_disk_detail_q,
134 attribute_deep_size_q,
135 attribute_deep_size_on_disk_q,
136 attribute_deep_file_count_q,
137 attribute_deep_directory_count_q,
138 attribute_deep_total_count_q,
139 attribute_date_changed_q,
140 attribute_trashed_on_q,
141 attribute_trash_orig_path_q,
142 attribute_date_permissions_q,
143 attribute_permissions_q,
144 attribute_selinux_context_q,
145 attribute_octal_permissions_q,
146 attribute_owner_q,
147 attribute_group_q,
148 attribute_uri_q,
149 attribute_where_q,
150 attribute_link_target_q,
151 attribute_volume_q,
152 attribute_free_space_q;
153
154static void caja_file_info_iface_init (CajaFileInfoIface *iface);
155static char * caja_file_get_owner_as_string (CajaFile *file,
156 gboolean include_real_name);
157static char * caja_file_get_type_as_string (CajaFile *file);
158static gboolean update_info_and_name (CajaFile *file,
159 GFileInfo *info);
160static const char * caja_file_peek_display_name (CajaFile *file);
161static const char * caja_file_peek_display_name_collation_key (CajaFile *file);
162static void file_mount_unmounted (GMount *mount, gpointer data);
163static void metadata_hash_free (GHashTable *hash);
164
165G_DEFINE_TYPE_WITH_CODE (CajaFile, caja_file, G_TYPE_OBJECT,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
166 G_ADD_PRIVATE (CajaFile)static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
167 G_IMPLEMENT_INTERFACE (CAJA_TYPE_FILE_INFO,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
168 caja_file_info_iface_init))static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
169
170static void
171caja_file_init (CajaFile *file)
172{
173 file->details = caja_file_get_instance_private (file);
174
175 caja_file_clear_info (file);
176 caja_file_invalidate_extension_info_internal (file);
177}
178
179static GObject*
180caja_file_constructor (GType type,
181 guint n_construct_properties,
182 GObjectConstructParam *construct_params)
183{
184 GObject *object;
185 CajaFile *file;
186
187 object = (* G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->constructor) (type,
188 n_construct_properties,
189 construct_params);
190
191 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
192
193 /* Set to default type after full construction */
194 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type != G_FILE_TYPE_UNKNOWN) {
195 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
196 }
197
198 return object;
199}
200
201gboolean
202caja_file_set_display_name (CajaFile *file,
203 const char *display_name,
204 const char *edit_name,
205 gboolean custom)
206{
207 gboolean changed;
208
209 if (custom && display_name == NULL((void*)0)) {
210 /* We're re-setting a custom display name, invalidate it if
211 we already set it so that the old one is re-read */
212 if (file->details->got_custom_display_name) {
213 file->details->got_custom_display_name = FALSE(0);
214 caja_file_invalidate_attributes (file,
215 CAJA_FILE_ATTRIBUTE_INFO);
216 }
217 return FALSE(0);
218 }
219
220 if (display_name == NULL((void*)0) || *display_name == 0) {
221 return FALSE(0);
222 }
223
224 if (!custom && file->details->got_custom_display_name) {
225 return FALSE(0);
226 }
227
228 if (edit_name == NULL((void*)0)) {
229 edit_name = display_name;
230 }
231
232 changed = FALSE(0);
233
234 if (eel_strcmp (file->details->display_name, display_name) != 0) {
235 changed = TRUE(!(0));
236
237 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
238
239 if (eel_strcmp (file->details->name, display_name) == 0) {
240 file->details->display_name = g_ref_string_acquire (file->details->name);
241 } else {
242 file->details->display_name = g_ref_string_new (display_name);
243 }
244
245 g_free (file->details->display_name_collation_key);
246 file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
247 }
248
249 if (eel_strcmp (file->details->edit_name, edit_name) != 0) {
250 changed = TRUE(!(0));
251
252 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
253 if (eel_strcmp (file->details->display_name, edit_name) == 0) {
254 file->details->edit_name = g_ref_string_acquire (file->details->display_name);
255 } else {
256 file->details->edit_name = g_ref_string_new (edit_name);
257 }
258 }
259
260 file->details->got_custom_display_name = custom;
261 return changed;
262}
263
264static void
265caja_file_clear_display_name (CajaFile *file)
266{
267 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
268 file->details->display_name = NULL((void*)0);
269 g_free (file->details->display_name_collation_key);
270 file->details->display_name_collation_key = NULL((void*)0);
271 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
272 file->details->edit_name = NULL((void*)0);
273}
274
275static gboolean
276foreach_metadata_free (gpointer key,
277 gpointer value,
278 gpointer user_data)
279{
280 guint id;
281
282 id = GPOINTER_TO_UINT (key)((guint) (gulong) (key));
283
284 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
285 g_strfreev ((char **)value);
286 } else {
287 g_free ((char *)value);
288 }
289 return TRUE(!(0));
290}
291
292
293static void
294metadata_hash_free (GHashTable *hash)
295{
296 g_hash_table_foreach_remove (hash,
297 foreach_metadata_free,
298 NULL((void*)0));
299 g_hash_table_destroy (hash);
300}
301
302static gboolean
303metadata_hash_equal (GHashTable *hash1,
304 GHashTable *hash2)
305{
306 GHashTableIter iter;
307 gpointer key1, value1, value2;
308 guint id;
309
310 if (hash1 == NULL((void*)0) && hash2 == NULL((void*)0)) {
311 return TRUE(!(0));
312 }
313
314 if (hash1 == NULL((void*)0) || hash2 == NULL((void*)0)) {
315 return FALSE(0);
316 }
317
318 if (g_hash_table_size (hash1) !=
319 g_hash_table_size (hash2)) {
320 return FALSE(0);
321 }
322
323 g_hash_table_iter_init (&iter, hash1);
324 while (g_hash_table_iter_next (&iter, &key1, &value1)) {
325 value2 = g_hash_table_lookup (hash2, key1);
326 if (value2 == NULL((void*)0)) {
327 return FALSE(0);
328 }
329 id = GPOINTER_TO_UINT (key1)((guint) (gulong) (key1));
330 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
331 if (!eel_g_strv_equal ((char **)value1, (char **)value2)) {
332 return FALSE(0);
333 }
334 } else {
335 if (strcmp ((char *)value1, (char *)value2) != 0) {
336 return FALSE(0);
337 }
338 }
339 }
340
341 return TRUE(!(0));
342}
343
344static void
345clear_metadata (CajaFile *file)
346{
347 if (file->details->metadata) {
348 metadata_hash_free (file->details->metadata);
349 file->details->metadata = NULL((void*)0);
350 }
351}
352
353static GHashTable *
354get_metadata_from_info (GFileInfo *info)
355{
356 GHashTable *metadata;
357 char **attrs;
358 guint id;
359 int i;
360 GFileAttributeType type;
361 gpointer value;
362
363 attrs = g_file_info_list_attributes (info, "metadata");
364
365 metadata = g_hash_table_new (NULL((void*)0), NULL((void*)0));
366
367 for (i = 0; attrs[i] != NULL((void*)0); i++) {
368 id = caja_metadata_get_id (attrs[i] + strlen ("metadata::"));
369 if (id == 0) {
370 continue;
371 }
372
373 if (!g_file_info_get_attribute_data (info, attrs[i],
374 &type, &value, NULL((void*)0))) {
375 continue;
376 }
377
378 if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
379 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
380 g_strdup ((char *)value)g_strdup_inline ((char *)value));
381 } else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) {
382 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
383 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
384 g_strdupv ((char **)value));
385 }
386 }
387
388 g_strfreev (attrs);
389
390 return metadata;
391}
392
393gboolean
394caja_file_update_metadata_from_info (CajaFile *file,
395 GFileInfo *info)
396{
397 gboolean changed = FALSE(0);
398
399 if (g_file_info_has_namespace (info, "metadata")) {
400 GHashTable *metadata;
401
402 metadata = get_metadata_from_info (info);
403 if (!metadata_hash_equal (metadata,
404 file->details->metadata)) {
405 changed = TRUE(!(0));
406 clear_metadata (file);
407 file->details->metadata = metadata;
408 } else {
409 metadata_hash_free (metadata);
410 }
411 } else if (file->details->metadata) {
412 changed = TRUE(!(0));
413 clear_metadata (file);
414 }
415 return changed;
416}
417
418void
419caja_file_clear_info (CajaFile *file)
420{
421 file->details->got_file_info = FALSE(0);
422 if (file->details->get_info_error) {
423 g_error_free (file->details->get_info_error);
424 file->details->get_info_error = NULL((void*)0);
425 }
426 /* Reset to default type, which might be other than unknown for
427 special kinds of files like the desktop or a search directory */
428 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
429
430 if (!file->details->got_custom_display_name) {
431 caja_file_clear_display_name (file);
432 }
433
434 if (!file->details->got_custom_activation_uri &&
435 file->details->activation_uri != NULL((void*)0)) {
436 g_free (file->details->activation_uri);
437 file->details->activation_uri = NULL((void*)0);
438 }
439
440 if (file->details->icon != NULL((void*)0)) {
441 g_object_unref (file->details->icon);
442 file->details->icon = NULL((void*)0);
443 }
444
445 g_free (file->details->thumbnail_path);
446 file->details->thumbnail_path = NULL((void*)0);
447 file->details->thumbnailing_failed = FALSE(0);
448
449 file->details->is_launcher = FALSE(0);
450 file->details->is_foreign_link = FALSE(0);
451 file->details->is_trusted_link = FALSE(0);
452 file->details->is_symlink = FALSE(0);
453 file->details->is_hidden = FALSE(0);
454 file->details->is_backup = FALSE(0);
455 file->details->is_mountpoint = FALSE(0);
456 file->details->uid = -1;
457 file->details->gid = -1;
458 file->details->can_read = TRUE(!(0));
459 file->details->can_write = TRUE(!(0));
460 file->details->can_execute = TRUE(!(0));
461 file->details->can_delete = TRUE(!(0));
462 file->details->can_trash = TRUE(!(0));
463 file->details->can_rename = TRUE(!(0));
464 file->details->can_mount = FALSE(0);
465 file->details->can_unmount = FALSE(0);
466 file->details->can_eject = FALSE(0);
467 file->details->can_start = FALSE(0);
468 file->details->can_start_degraded = FALSE(0);
469 file->details->can_stop = FALSE(0);
470 file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
471 file->details->can_poll_for_media = FALSE(0);
472 file->details->is_media_check_automatic = FALSE(0);
473 file->details->has_permissions = FALSE(0);
474 file->details->permissions = 0;
475 file->details->size = -1;
476 file->details->size_on_disk = -1;
477 file->details->sort_order = 0;
478 file->details->mtime = 0;
479 file->details->atime = 0;
480 file->details->ctime = 0;
481 file->details->btime = 0;
482 file->details->trash_time = 0;
483 g_free (file->details->symlink_name);
484 file->details->symlink_name = NULL((void*)0);
485 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
486 file->details->mime_type = NULL((void*)0);
487 g_free (file->details->selinux_context);
488 file->details->selinux_context = NULL((void*)0);
489 g_free (file->details->description);
490 file->details->description = NULL((void*)0);
491 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
492 file->details->owner = NULL((void*)0);
493 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
494 file->details->owner_real = NULL((void*)0);
495 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
496 file->details->group = NULL((void*)0);
497
498 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
499 file->details->filesystem_id = NULL((void*)0);
500
501 clear_metadata (file);
502}
503
504static CajaFile *
505caja_file_new_from_filename (CajaDirectory *directory,
506 const char *filename,
507 gboolean self_owned)
508{
509 CajaFile *file;
510
511 g_assert (CAJA_IS_DIRECTORY (directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_558
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_558
= 1; else _g_boolean_var_558 = 0; _g_boolean_var_558; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 511, ((const char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"
); } while (0)
;
512 g_assert (filename != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_559
; if (filename != ((void*)0)) _g_boolean_var_559 = 1; else _g_boolean_var_559
= 0; _g_boolean_var_559; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 512, ((const char*) (__func__)
), "filename != NULL"); } while (0)
;
513 g_assert (filename[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_560
; if (filename[0] != '\0') _g_boolean_var_560 = 1; else _g_boolean_var_560
= 0; _g_boolean_var_560; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 513, ((const char*) (__func__)
), "filename[0] != '\\0'"); } while (0)
;
514
515 if (CAJA_IS_DESKTOP_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_desktop_directory_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; }
))))
) {
516 if (self_owned) {
517 file = CAJA_FILE (g_object_new (CAJA_TYPE_DESKTOP_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_desktop_directory_file_get_type
(), ((void*)0)))))))
;
518 } else {
519 /* This doesn't normally happen, unless the user somehow types in a uri
520 * that references a file like this. (See #349840) */
521 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
522 }
523 } else if (CAJA_IS_SEARCH_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_search_directory_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; }
))))
) {
524 if (self_owned) {
525 file = CAJA_FILE (g_object_new (CAJA_TYPE_SEARCH_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_search_directory_file_get_type
(), ((void*)0)))))))
;
526 } else {
527 /* This doesn't normally happen, unless the user somehow types in a uri
528 * that references a file like this. (See #349840) */
529 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
530 }
531 } else if (g_str_has_suffix (filename, CAJA_SAVED_SEARCH_EXTENSION)(__builtin_constant_p (".savedSearch")? __extension__ ({ const
char * const __str = (filename); const char * const __suffix
= (".savedSearch"); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_561; if (__str == ((void
*)0) || __suffix == ((void*)0)) _g_boolean_var_561 = 1; else _g_boolean_var_561
= 0; _g_boolean_var_561; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".savedSearch") )
) {
532 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
533 } else {
534 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
535 }
536
537 file->details->directory = caja_directory_ref (directory);
538
539 file->details->name = g_ref_string_new (filename);
540
541#ifdef CAJA_FILE_DEBUG_REF
542 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
543#endif
544
545 return file;
546}
547
548static void
549modify_link_hash_table (CajaFile *file,
550 ModifyListFunction modify_function)
551{
552 char *target_uri;
553 gboolean found;
554 gpointer original_key;
555 GList **list_ptr;
556
557 /* Check if there is a symlink name. If none, we are OK. */
558 if (file->details->symlink_name == NULL((void*)0) || !caja_file_is_symbolic_link (file)) {
559 return;
560 }
561
562 /* Create the hash table first time through. */
563 if (symbolic_links == NULL((void*)0)) {
564 symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
565 }
566
567 target_uri = caja_file_get_symbolic_link_target_uri (file);
568
569 /* Find the old contents of the hash table. */
570 found = g_hash_table_lookup_extended
571 (symbolic_links, target_uri,
572 &original_key, (gpointer *)&list_ptr);
573 if (!found) {
574 list_ptr = g_new0 (GList *, 1)(GList * *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (GList *); 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
; }))
;
575 original_key = g_strdup (target_uri)g_strdup_inline (target_uri);
576 g_hash_table_insert (symbolic_links, original_key, list_ptr);
577 }
578 (* modify_function) (list_ptr, file);
579 if (*list_ptr == NULL((void*)0)) {
580 g_hash_table_remove (symbolic_links, target_uri);
581 g_free (list_ptr);
582 g_free (original_key);
583 }
584 g_free (target_uri);
585}
586
587static void
588symbolic_link_weak_notify (gpointer data,
589 GObject *where_the_object_was)
590{
591 GList **list = data;
592 /* This really shouldn't happen, but we're seeing some strange things in
593 bug #358172 where the symlink hashtable isn't correctly updated. */
594 *list = g_list_remove (*list, where_the_object_was);
595}
596
597static void
598add_to_link_hash_table_list (GList **list, CajaFile *file)
599{
600 if (g_list_find (*list, file) != NULL((void*)0)) {
601 g_warning ("Adding file to symlink_table multiple times. "
602 "Please add feedback of what you were doing at https://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
603 return;
604 }
605 g_object_weak_ref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
606 *list = g_list_prepend (*list, file);
607}
608
609static void
610add_to_link_hash_table (CajaFile *file)
611{
612 modify_link_hash_table (file, add_to_link_hash_table_list);
613}
614
615static void
616remove_from_link_hash_table_list (GList **list, CajaFile *file)
617{
618 if (g_list_find (*list, file) != NULL((void*)0)) {
619 g_object_weak_unref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
620 *list = g_list_remove (*list, file);
621 }
622}
623
624static void
625remove_from_link_hash_table (CajaFile *file)
626{
627 modify_link_hash_table (file, remove_from_link_hash_table_list);
628}
629
630CajaFile *
631caja_file_new_from_info (CajaDirectory *directory,
632 GFileInfo *info)
633{
634 CajaFile *file;
635 const char *mime_type;
636
637 g_return_val_if_fail (CAJA_IS_DIRECTORY (directory), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_562
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_562
= 1; else _g_boolean_var_562 = 0; _g_boolean_var_562; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"); return
(((void*)0)); } } while (0)
;
638 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_563
; if (info != ((void*)0)) _g_boolean_var_563 = 1; else _g_boolean_var_563
= 0; _g_boolean_var_563; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "info != NULL"); return
(((void*)0)); } } while (0)
;
639
640 mime_type = g_file_info_get_content_type (info);
641 if (mime_type &&
642 strcmp (mime_type, CAJA_SAVED_SEARCH_MIMETYPE"application/x-mate-saved-search") == 0) {
643 g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
644 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
645 } else {
646 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
647 }
648
649 file->details->directory = caja_directory_ref (directory);
650
651 update_info_and_name (file, info);
652
653#ifdef CAJA_FILE_DEBUG_REF
654 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
655#endif
656
657 return file;
658}
659
660static CajaFile *
661caja_file_get_internal (GFile *location, gboolean create)
662{
663 gboolean self_owned;
664 CajaDirectory *directory;
665 CajaFile *file;
666 GFile *parent;
667 char *basename;
668
669 g_assert (location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_564
; if (location != ((void*)0)) _g_boolean_var_564 = 1; else _g_boolean_var_564
= 0; _g_boolean_var_564; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 669, ((const char*) (__func__)
), "location != NULL"); } while (0)
;
670
671 parent = g_file_get_parent (location);
672
673 self_owned = FALSE(0);
674 if (parent == NULL((void*)0)) {
675 self_owned = TRUE(!(0));
676 parent = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
677 }
678
679 /* Get object that represents the directory. */
680 directory = caja_directory_get_internal (parent, create);
681
682 g_object_unref (parent);
683
684 /* Get the name for the file. */
685 if (self_owned && directory != NULL((void*)0)) {
686 basename = caja_directory_get_name_for_self_as_new_file (directory);
687 } else {
688 basename = g_file_get_basename (location);
689 }
690 /* Check to see if it's a file that's already known. */
691 if (directory == NULL((void*)0)) {
692 file = NULL((void*)0);
693 } else if (self_owned) {
694 file = directory->details->as_file;
695 } else {
696 file = caja_directory_find_file_by_name (directory, basename);
697 }
698
699 /* Ref or create the file. */
700 if (file != NULL((void*)0)) {
701 caja_file_ref (file);
702 } else if (create && directory != NULL((void*)0)) {
703 file = caja_file_new_from_filename (directory, basename, self_owned);
704 if (self_owned) {
705 g_assert (directory->details->as_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_565
; if (directory->details->as_file == ((void*)0)) _g_boolean_var_565
= 1; else _g_boolean_var_565 = 0; _g_boolean_var_565; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 705, ((const char*) (__func__)), "directory->details->as_file == NULL"
); } while (0)
;
706 directory->details->as_file = file;
707 } else {
708 caja_directory_add_file (directory, file);
709 }
710 }
711
712 g_free (basename);
713 caja_directory_unref (directory);
714
715 return file;
716}
717
718CajaFile *
719caja_file_get (GFile *location)
720{
721 return caja_file_get_internal (location, TRUE(!(0)));
722}
723
724CajaFile *
725caja_file_get_existing (GFile *location)
726{
727 return caja_file_get_internal (location, FALSE(0));
728}
729
730CajaFile *
731caja_file_get_existing_by_uri (const char *uri)
732{
733 GFile *location;
734 CajaFile *file;
735
736 location = g_file_new_for_uri (uri);
737 file = caja_file_get_internal (location, FALSE(0));
738 g_object_unref (location);
739
740 return file;
741}
742
743CajaFile *
744caja_file_get_by_uri (const char *uri)
745{
746 GFile *location;
747 CajaFile *file;
748
749 location = g_file_new_for_uri (uri);
750 file = caja_file_get_internal (location, TRUE(!(0)));
751 g_object_unref (location);
752
753 return file;
754}
755
756gboolean
757caja_file_is_self_owned (CajaFile *file)
758{
759 return file->details->directory->details->as_file == file;
760}
761
762static void
763finalize (GObject *object)
764{
765 CajaDirectory *directory;
766 CajaFile *file;
767
768 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
769
770 g_assert (file->details->operations_in_progress == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_566
; if (file->details->operations_in_progress == ((void*)
0)) _g_boolean_var_566 = 1; else _g_boolean_var_566 = 0; _g_boolean_var_566
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 770, ((const char*) (__func__)), "file->details->operations_in_progress == NULL"
); } while (0)
;
771
772 if (file->details->is_thumbnailing) {
773 char *uri;
774
775 uri = caja_file_get_uri (file);
776 caja_thumbnail_remove_from_queue (uri);
777 g_free (uri);
778 }
779
780 caja_async_destroying_file (file);
781
782 remove_from_link_hash_table (file);
783
784 directory = file->details->directory;
785
786 if (caja_file_is_self_owned (file)) {
787 directory->details->as_file = NULL((void*)0);
788 } else {
789 if (!file->details->is_gone) {
790 caja_directory_remove_file (directory, file);
791 }
792 }
793
794 if (file->details->get_info_error) {
795 g_error_free (file->details->get_info_error);
796 }
797
798 caja_directory_unref (directory);
799 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
800 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
801 g_free (file->details->display_name_collation_key);
802 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
803 if (file->details->icon) {
804 g_object_unref (file->details->icon);
805 }
806 g_free (file->details->thumbnail_path);
807 g_free (file->details->symlink_name);
808 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
809 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
810 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
811 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
812 g_free (file->details->selinux_context);
813 g_free (file->details->description);
814 g_free (file->details->top_left_text);
815 g_free (file->details->custom_icon);
816 g_free (file->details->activation_uri);
817 g_free (file->details->compare_by_emblem_cache);
818
819 if (file->details->thumbnail) {
820 g_object_unref (file->details->thumbnail);
821 }
822 if (file->details->mount) {
823 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
824 g_object_unref (file->details->mount);
825 }
826
827 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
828
829 g_list_free_full (file->details->mime_list, g_free);
830 g_list_free_full (file->details->pending_extension_emblems, g_free);
831 g_list_free_full (file->details->extension_emblems, g_free);
832 g_list_free_full (file->details->pending_info_providers, g_object_unref);
833
834 if (file->details->pending_extension_attributes) {
835 g_hash_table_destroy (file->details->pending_extension_attributes);
836 }
837
838 if (file->details->extension_attributes) {
839 g_hash_table_destroy (file->details->extension_attributes);
840 }
841
842 if (file->details->metadata) {
843 metadata_hash_free (file->details->metadata);
844 }
845
846 G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->finalize (object);
847}
848
849CajaFile *
850caja_file_ref (CajaFile *file)
851{
852 if (file == NULL((void*)0)) {
853 return NULL((void*)0);
854 }
855 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_567
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_567
= 1; else _g_boolean_var_567 = 0; _g_boolean_var_567; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
856
857#ifdef CAJA_FILE_DEBUG_REF
858 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
859#endif
860
861 return g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
862}
863
864void
865caja_file_unref (CajaFile *file)
866{
867 if (file == NULL((void*)0)) {
868 return;
869 }
870
871 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_568
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_568
= 1; else _g_boolean_var_568 = 0; _g_boolean_var_568; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
872
873#ifdef CAJA_FILE_DEBUG_REF
874 DEBUG_REF_PRINTFprintf("%10p unref'd", file);
875#endif
876
877 g_object_unref (file);
878}
879
880/**
881 * caja_file_get_parent_uri_for_display:
882 *
883 * Get the uri for the parent directory.
884 *
885 * @file: The file in question.
886 *
887 * Return value: A string representing the parent's location,
888 * formatted for user display (including stripping "file://").
889 * If the parent is NULL, returns the empty string.
890 */
891char *
892caja_file_get_parent_uri_for_display (CajaFile *file)
893{
894 GFile *parent;
895 char *result;
896
897 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_569
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_569
= 1; else _g_boolean_var_569 = 0; _g_boolean_var_569; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 897, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
898
899 parent = caja_file_get_parent_location (file);
900 if (parent) {
901 result = g_file_get_parse_name (parent);
902 g_object_unref (parent);
903 } else {
904 result = g_strdup ("")g_strdup_inline ("");
905 }
906
907 return result;
908}
909
910/**
911 * caja_file_get_parent_uri:
912 *
913 * Get the uri for the parent directory.
914 *
915 * @file: The file in question.
916 *
917 * Return value: A string for the parent's location, in "raw URI" form.
918 * Use caja_file_get_parent_uri_for_display instead if the
919 * result is to be displayed on-screen.
920 * If the parent is NULL, returns the empty string.
921 */
922char *
923caja_file_get_parent_uri (CajaFile *file)
924{
925 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_570
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_570
= 1; else _g_boolean_var_570 = 0; _g_boolean_var_570; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 925, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
926
927 if (caja_file_is_self_owned (file)) {
928 /* Callers expect an empty string, not a NULL. */
929 return g_strdup ("")g_strdup_inline ("");
930 }
931
932 return caja_directory_get_uri (file->details->directory);
933}
934
935GFile *
936caja_file_get_parent_location (CajaFile *file)
937{
938 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_571
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_571
= 1; else _g_boolean_var_571 = 0; _g_boolean_var_571; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 938, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
939
940 if (caja_file_is_self_owned (file)) {
941 /* Callers expect an empty string, not a NULL. */
942 return NULL((void*)0);
943 }
944
945 return caja_directory_get_location (file->details->directory);
946}
947
948CajaFile *
949caja_file_get_parent (CajaFile *file)
950{
951 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_572
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_572
= 1; else _g_boolean_var_572 = 0; _g_boolean_var_572; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 951, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
952
953 if (caja_file_is_self_owned (file)) {
954 return NULL((void*)0);
955 }
956
957 return caja_directory_get_corresponding_file (file->details->directory);
958}
959
960/**
961 * caja_file_can_read:
962 *
963 * Check whether the user is allowed to read the contents of this file.
964 *
965 * @file: The file to check.
966 *
967 * Return value: FALSE if the user is definitely not allowed to read
968 * the contents of the file. If the user has read permission, or
969 * the code can't tell whether the user has read permission,
970 * returns TRUE (so failures must always be handled).
971 */
972gboolean
973caja_file_can_read (CajaFile *file)
974{
975 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_573
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_573
= 1; else _g_boolean_var_573 = 0; _g_boolean_var_573; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
976
977 return file->details->can_read;
978}
979
980/**
981 * caja_file_can_write:
982 *
983 * Check whether the user is allowed to write to this file.
984 *
985 * @file: The file to check.
986 *
987 * Return value: FALSE if the user is definitely not allowed to write
988 * to the file. If the user has write permission, or
989 * the code can't tell whether the user has write permission,
990 * returns TRUE (so failures must always be handled).
991 */
992gboolean
993caja_file_can_write (CajaFile *file)
994{
995 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_574
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_574
= 1; else _g_boolean_var_574 = 0; _g_boolean_var_574; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
996
997 return file->details->can_write;
998}
999
1000/**
1001 * caja_file_can_execute:
1002 *
1003 * Check whether the user is allowed to execute this file.
1004 *
1005 * @file: The file to check.
1006 *
1007 * Return value: FALSE if the user is definitely not allowed to execute
1008 * the file. If the user has execute permission, or
1009 * the code can't tell whether the user has execute permission,
1010 * returns TRUE (so failures must always be handled).
1011 */
1012gboolean
1013caja_file_can_execute (CajaFile *file)
1014{
1015 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_575
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_575
= 1; else _g_boolean_var_575 = 0; _g_boolean_var_575; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1016
1017 return file->details->can_execute;
1018}
1019
1020gboolean
1021caja_file_can_mount (CajaFile *file)
1022{
1023 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_576
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_576
= 1; else _g_boolean_var_576 = 0; _g_boolean_var_576; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1024
1025 return file->details->can_mount;
1026}
1027
1028gboolean
1029caja_file_can_unmount (CajaFile *file)
1030{
1031 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_577
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_577
= 1; else _g_boolean_var_577 = 0; _g_boolean_var_577; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1032
1033 return file->details->can_unmount ||
1034 (file->details->mount != NULL((void*)0) &&
1035 g_mount_can_unmount (file->details->mount));
1036}
1037
1038gboolean
1039caja_file_can_eject (CajaFile *file)
1040{
1041 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_578
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_578
= 1; else _g_boolean_var_578 = 0; _g_boolean_var_578; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1042
1043 return file->details->can_eject ||
1044 (file->details->mount != NULL((void*)0) &&
1045 g_mount_can_eject (file->details->mount));
1046}
1047
1048gboolean
1049caja_file_can_start (CajaFile *file)
1050{
1051 gboolean ret;
1052 GDrive *drive;
1053
1054 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_579
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_579
= 1; else _g_boolean_var_579 = 0; _g_boolean_var_579; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1055
1056 ret = FALSE(0);
1057
1058 if (file->details->can_start) {
1059 ret = TRUE(!(0));
1060 goto out;
1061 }
1062
1063 if (file->details->mount != NULL((void*)0)) {
1064 drive = g_mount_get_drive (file->details->mount);
1065 if (drive != NULL((void*)0)) {
1066 ret = g_drive_can_start (drive);
1067 g_object_unref (drive);
1068 }
1069 }
1070
1071 out:
1072 return ret;
1073}
1074
1075gboolean
1076caja_file_can_start_degraded (CajaFile *file)
1077{
1078 gboolean ret;
1079 GDrive *drive;
1080
1081 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_580
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_580
= 1; else _g_boolean_var_580 = 0; _g_boolean_var_580; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1082
1083 ret = FALSE(0);
1084
1085 if (file->details->can_start_degraded) {
1086 ret = TRUE(!(0));
1087 goto out;
1088 }
1089
1090 if (file->details->mount != NULL((void*)0)) {
1091 drive = g_mount_get_drive (file->details->mount);
1092 if (drive != NULL((void*)0)) {
1093 ret = g_drive_can_start_degraded (drive);
1094 g_object_unref (drive);
1095 }
1096 }
1097
1098 out:
1099 return ret;
1100}
1101
1102gboolean
1103caja_file_can_poll_for_media (CajaFile *file)
1104{
1105 gboolean ret;
1106 GDrive *drive;
1107
1108 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_581
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_581
= 1; else _g_boolean_var_581 = 0; _g_boolean_var_581; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1109
1110 ret = FALSE(0);
1111
1112 if (file->details->can_poll_for_media) {
1113 ret = TRUE(!(0));
1114 goto out;
1115 }
1116
1117 if (file->details->mount != NULL((void*)0)) {
1118 drive = g_mount_get_drive (file->details->mount);
1119 if (drive != NULL((void*)0)) {
1120 ret = g_drive_can_poll_for_media (drive);
1121 g_object_unref (drive);
1122 }
1123 }
1124
1125 out:
1126 return ret;
1127}
1128
1129gboolean
1130caja_file_is_media_check_automatic (CajaFile *file)
1131{
1132 gboolean ret;
1133 GDrive *drive;
1134
1135 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_582
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_582
= 1; else _g_boolean_var_582 = 0; _g_boolean_var_582; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1136
1137 ret = FALSE(0);
1138
1139 if (file->details->is_media_check_automatic) {
1140 ret = TRUE(!(0));
1141 goto out;
1142 }
1143
1144 if (file->details->mount != NULL((void*)0)) {
1145 drive = g_mount_get_drive (file->details->mount);
1146 if (drive != NULL((void*)0)) {
1147 ret = g_drive_is_media_check_automatic (drive);
1148 g_object_unref (drive);
1149 }
1150 }
1151
1152 out:
1153 return ret;
1154}
1155
1156
1157gboolean
1158caja_file_can_stop (CajaFile *file)
1159{
1160 gboolean ret;
1161 GDrive *drive;
1162
1163 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_583
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_583
= 1; else _g_boolean_var_583 = 0; _g_boolean_var_583; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1164
1165 ret = FALSE(0);
1166
1167 if (file->details->can_stop) {
1168 ret = TRUE(!(0));
1169 goto out;
1170 }
1171
1172 if (file->details->mount != NULL((void*)0)) {
1173 drive = g_mount_get_drive (file->details->mount);
1174 if (drive != NULL((void*)0)) {
1175 ret = g_drive_can_stop (drive);
1176 g_object_unref (drive);
1177 }
1178 }
1179
1180 out:
1181 return ret;
1182}
1183
1184GDriveStartStopType
1185caja_file_get_start_stop_type (CajaFile *file)
1186{
1187 GDriveStartStopType ret;
1188 GDrive *drive;
1189
1190 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_584
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_584
= 1; else _g_boolean_var_584 = 0; _g_boolean_var_584; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1191
1192 ret = G_DRIVE_START_STOP_TYPE_UNKNOWN;
1193
1194 ret = file->details->start_stop_type;
1195 if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1196 goto out;
1197
1198 if (file->details->mount != NULL((void*)0)) {
1199 drive = g_mount_get_drive (file->details->mount);
1200 if (drive != NULL((void*)0)) {
1201 ret = g_drive_get_start_stop_type (drive);
1202 g_object_unref (drive);
1203 }
1204 }
1205
1206 out:
1207 return ret;
1208}
1209
1210void
1211caja_file_mount (CajaFile *file,
1212 GMountOperation *mount_op,
1213 GCancellable *cancellable,
1214 CajaFileOperationCallback callback,
1215 gpointer callback_data)
1216{
1217 GError *error;
1218
1219 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount == NULL((void*)0)) {
1220 if (callback) {
1221 error = NULL((void*)0);
1222 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1223 _("This file cannot be mounted")dcgettext (((void*)0), "This file cannot be mounted", 5));
1224 callback (file, NULL((void*)0), error, callback_data);
1225 g_error_free (error);
1226 }
1227 } else {
1228 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount (file, mount_op, cancellable, callback, callback_data);
1229 }
1230}
1231
1232typedef struct {
1233 CajaFile *file;
1234 CajaFileOperationCallback callback;
1235 gpointer callback_data;
1236} UnmountData;
1237
1238static void
1239unmount_done (void *callback_data)
1240{
1241 UnmountData *data;
1242
1243 data = (UnmountData *)callback_data;
1244 if (data->callback) {
1245 data->callback (data->file, NULL((void*)0), NULL((void*)0), data->callback_data);
1246 }
1247 caja_file_unref (data->file);
1248 g_free (data);
1249}
1250
1251void
1252caja_file_unmount (CajaFile *file,
1253 GMountOperation *mount_op,
1254 GCancellable *cancellable,
1255 CajaFileOperationCallback callback,
1256 gpointer callback_data)
1257{
1258 GError *error;
1259 UnmountData *data;
1260
1261 if (file->details->can_unmount) {
1262 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount != NULL((void*)0)) {
1263 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount (file, mount_op, cancellable, callback, callback_data);
1264 } else {
1265 if (callback) {
1266 error = NULL((void*)0);
1267 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1268 _("This file cannot be unmounted")dcgettext (((void*)0), "This file cannot be unmounted", 5));
1269 callback (file, NULL((void*)0), error, callback_data);
1270 g_error_free (error);
1271 }
1272 }
1273 } else if (file->details->mount != NULL((void*)0) &&
1274 g_mount_can_unmount (file->details->mount)) {
1275 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1276 data->file = caja_file_ref (file);
1277 data->callback = callback;
1278 data->callback_data = callback_data;
1279 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, FALSE(0), TRUE(!(0)), unmount_done, data);
1280 } else if (callback) {
1281 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1282 }
1283}
1284
1285void
1286caja_file_eject (CajaFile *file,
1287 GMountOperation *mount_op,
1288 GCancellable *cancellable,
1289 CajaFileOperationCallback callback,
1290 gpointer callback_data)
1291{
1292 GError *error;
1293 UnmountData *data;
1294
1295 if (file->details->can_eject) {
1296 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject != NULL((void*)0)) {
1297 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject (file, mount_op, cancellable, callback, callback_data);
1298 } else {
1299 if (callback) {
1300 error = NULL((void*)0);
1301 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1302 _("This file cannot be ejected")dcgettext (((void*)0), "This file cannot be ejected", 5));
1303 callback (file, NULL((void*)0), error, callback_data);
1304 g_error_free (error);
1305 }
1306 }
1307 } else if (file->details->mount != NULL((void*)0) &&
1308 g_mount_can_eject (file->details->mount)) {
1309 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1310 data->file = caja_file_ref (file);
1311 data->callback = callback;
1312 data->callback_data = callback_data;
1313 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, TRUE(!(0)), TRUE(!(0)), unmount_done, data);
1314 } else if (callback) {
1315 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1316 }
1317}
1318
1319void
1320caja_file_start (CajaFile *file,
1321 GMountOperation *start_op,
1322 GCancellable *cancellable,
1323 CajaFileOperationCallback callback,
1324 gpointer callback_data)
1325{
1326 GError *error;
1327
1328 if ((file->details->can_start || file->details->can_start_degraded) &&
1329 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start != NULL((void*)0)) {
1330 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start (file, start_op, cancellable, callback, callback_data);
1331 } else {
1332 if (callback) {
1333 error = NULL((void*)0);
1334 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1335 _("This file cannot be started")dcgettext (((void*)0), "This file cannot be started", 5));
1336 callback (file, NULL((void*)0), error, callback_data);
1337 g_error_free (error);
1338 }
1339 }
1340}
1341
1342static void
1343file_stop_callback (GObject *source_object,
1344 GAsyncResult *res,
1345 gpointer callback_data)
1346{
1347 CajaFileOperation *op;
1348 gboolean stopped;
1349 GError *error;
1350
1351 op = callback_data;
1352
1353 error = NULL((void*)0);
1354 stopped = g_drive_stop_finish (G_DRIVE (source_object)((((GDrive*) (void *) ((source_object))))),
1355 res, &error);
1356
1357 if (!stopped &&
1358 error->domain == G_IO_ERRORg_io_error_quark() &&
1359 (error->code == G_IO_ERROR_FAILED_HANDLED ||
1360 error->code == G_IO_ERROR_CANCELLED)) {
1361 g_error_free (error);
1362 error = NULL((void*)0);
1363 }
1364
1365 caja_file_operation_complete (op, NULL((void*)0), error);
1366 if (error) {
1367 g_error_free (error);
1368 }
1369}
1370
1371void
1372caja_file_stop (CajaFile *file,
1373 GMountOperation *mount_op,
1374 GCancellable *cancellable,
1375 CajaFileOperationCallback callback,
1376 gpointer callback_data)
1377{
1378 GError *error;
1379
1380 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1381 if (file->details->can_stop) {
1382 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop (file, mount_op, cancellable, callback, callback_data);
1383 } else {
1384 if (callback) {
1385 error = NULL((void*)0);
1386 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1387 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1388 callback (file, NULL((void*)0), error, callback_data);
1389 g_error_free (error);
1390 }
1391 }
1392 } else {
1393 GDrive *drive;
1394
1395 drive = NULL((void*)0);
1396 if (file->details->mount != NULL((void*)0))
1397 drive = g_mount_get_drive (file->details->mount);
1398
1399 if (drive != NULL((void*)0) && g_drive_can_stop (drive)) {
1400 CajaFileOperation *op;
1401
1402 op = caja_file_operation_new (file, callback, callback_data);
1403 if (cancellable) {
1404 g_object_unref (op->cancellable);
1405 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
1406 }
1407
1408 g_drive_stop (drive,
1409 G_MOUNT_UNMOUNT_NONE,
1410 mount_op,
1411 op->cancellable,
1412 file_stop_callback,
1413 op);
1414 } else {
1415 if (callback) {
1416 error = NULL((void*)0);
1417 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1418 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1419 callback (file, NULL((void*)0), error, callback_data);
1420 g_error_free (error);
1421 }
1422 }
1423
1424 if (drive != NULL((void*)0)) {
1425 g_object_unref (drive);
1426 }
1427 }
1428}
1429
1430void
1431caja_file_poll_for_media (CajaFile *file)
1432{
1433 if (file->details->can_poll_for_media) {
1434 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1435 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->poll_for_media (file);
1436 }
1437 } else if (file->details->mount != NULL((void*)0)) {
1438 GDrive *drive;
1439 drive = g_mount_get_drive (file->details->mount);
1440 if (drive != NULL((void*)0)) {
1441 g_drive_poll_for_media (drive,
1442 NULL((void*)0), /* cancellable */
1443 NULL((void*)0), /* GAsyncReadyCallback */
1444 NULL((void*)0)); /* user_data */
1445 g_object_unref (drive);
1446 }
1447 }
1448}
1449
1450/**
1451 * caja_file_is_desktop_directory:
1452 *
1453 * Check whether this file is the desktop directory.
1454 *
1455 * @file: The file to check.
1456 *
1457 * Return value: TRUE if this is the physical desktop directory.
1458 */
1459gboolean
1460caja_file_is_desktop_directory (CajaFile *file)
1461{
1462 GFile *dir;
1463
1464 dir = file->details->directory->details->location;
1465
1466 if (dir == NULL((void*)0)) {
1467 return FALSE(0);
1468 }
1469
1470 return caja_is_desktop_directory_file (dir, file->details->name);
1471}
1472
1473static gboolean
1474is_desktop_file (CajaFile *file)
1475{
1476 return caja_file_is_mime_type (file, "application/x-desktop");
1477}
1478
1479static gboolean
1480can_rename_desktop_file (CajaFile *file)
1481{
1482 GFile *location;
1483 gboolean res;
1484
1485 location = caja_file_get_location (file);
1486 res = g_file_is_native (location);
1487 g_object_unref (location);
1488 return res;
1489}
1490
1491/**
1492 * caja_file_can_rename:
1493 *
1494 * Check whether the user is allowed to change the name of the file.
1495 *
1496 * @file: The file to check.
1497 *
1498 * Return value: FALSE if the user is definitely not allowed to change
1499 * the name of the file. If the user is allowed to change the name, or
1500 * the code can't tell whether the user is allowed to change the name,
1501 * returns TRUE (so rename failures must always be handled).
1502 */
1503gboolean
1504caja_file_can_rename (CajaFile *file)
1505{
1506 gboolean can_rename;
1507
1508 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_585
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_585
= 1; else _g_boolean_var_585 = 0; _g_boolean_var_585; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1509
1510 /* Nonexistent files can't be renamed. */
1511 if (caja_file_is_gone (file)) {
1512 return FALSE(0);
1513 }
1514
1515 /* Self-owned files can't be renamed */
1516 if (caja_file_is_self_owned (file)) {
1517 return FALSE(0);
1518 }
1519
1520 if ((is_desktop_file (file) && !can_rename_desktop_file (file)) ||
1521 caja_file_is_home (file)) {
1522 return FALSE(0);
1523 }
1524
1525 can_rename = TRUE(!(0));
1526
1527 /* Certain types of links can't be renamed */
1528 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1529 CajaDesktopLink *link;
1530
1531 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1532
1533 if (link != NULL((void*)0)) {
1534 can_rename = caja_desktop_link_can_rename (link);
1535 g_object_unref (link);
1536 }
1537 }
1538
1539 if (!can_rename) {
1540 return FALSE(0);
1541 }
1542
1543 return file->details->can_rename;
1544}
1545
1546gboolean
1547caja_file_can_delete (CajaFile *file)
1548{
1549 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_586
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_586
= 1; else _g_boolean_var_586 = 0; _g_boolean_var_586; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1550
1551 /* Nonexistent files can't be deleted. */
1552 if (caja_file_is_gone (file)) {
1553 return FALSE(0);
1554 }
1555
1556 /* Self-owned files can't be deleted */
1557 if (caja_file_is_self_owned (file)) {
1558 return FALSE(0);
1559 }
1560
1561 return file->details->can_delete;
1562}
1563
1564gboolean
1565caja_file_can_trash (CajaFile *file)
1566{
1567 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_587
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_587
= 1; else _g_boolean_var_587 = 0; _g_boolean_var_587; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1568
1569 /* Nonexistent files can't be deleted. */
1570 if (caja_file_is_gone (file)) {
1571 return FALSE(0);
1572 }
1573
1574 /* Self-owned files can't be deleted */
1575 if (caja_file_is_self_owned (file)) {
1576 return FALSE(0);
1577 }
1578
1579 return file->details->can_trash;
1580}
1581
1582GFile *
1583caja_file_get_location (CajaFile *file)
1584{
1585 GFile *dir;
1586
1587 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_588
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_588
= 1; else _g_boolean_var_588 = 0; _g_boolean_var_588; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1588
1589 dir = file->details->directory->details->location;
1590
1591 if (caja_file_is_self_owned (file)) {
1592 return g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir));
1593 }
1594
1595 return g_file_get_child (dir, file->details->name);
1596}
1597
1598/* Return the actual uri associated with the passed-in file. */
1599char *
1600caja_file_get_uri (CajaFile *file)
1601{
1602 char *uri;
1603 GFile *loc;
1604
1605 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_589
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_589
= 1; else _g_boolean_var_589 = 0; _g_boolean_var_589; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1606
1607 loc = caja_file_get_location (file);
1608 uri = g_file_get_uri (loc);
1609 g_object_unref (loc);
1610
1611 return uri;
1612}
1613
1614char *
1615caja_file_get_uri_scheme (CajaFile *file)
1616{
1617 GFile *loc;
1618 char *scheme;
1619
1620 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_590
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_590
= 1; else _g_boolean_var_590 = 0; _g_boolean_var_590; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1621
1622 if (file->details->directory == NULL((void*)0) ||
1623 file->details->directory->details->location == NULL((void*)0)) {
1624 return NULL((void*)0);
1625 }
1626
1627 loc = caja_directory_get_location (file->details->directory);
1628 scheme = g_file_get_uri_scheme (loc);
1629 g_object_unref (loc);
1630
1631 return scheme;
1632}
1633
1634CajaFileOperation *
1635caja_file_operation_new (CajaFile *file,
1636 CajaFileOperationCallback callback,
1637 gpointer callback_data)
1638{
1639 CajaFileOperation *op;
1640
1641 op = g_new0 (CajaFileOperation, 1)(CajaFileOperation *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (CajaFileOperation); 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; }))
;
1642 op->file = caja_file_ref (file);
1643 op->callback = callback;
1644 op->callback_data = callback_data;
1645 op->cancellable = g_cancellable_new ();
1646
1647 op->file->details->operations_in_progress = g_list_prepend
1648 (op->file->details->operations_in_progress, op);
1649
1650 return op;
1651}
1652
1653static void
1654caja_file_operation_remove (CajaFileOperation *op)
1655{
1656 op->file->details->operations_in_progress = g_list_remove
1657 (op->file->details->operations_in_progress, op);
1658}
1659
1660void
1661caja_file_operation_free (CajaFileOperation *op)
1662{
1663 caja_file_operation_remove (op);
1664 caja_file_unref (op->file);
1665 g_object_unref (op->cancellable);
1666 if (op->free_data) {
1667 op->free_data (op->data);
1668 }
1669 // Start UNDO-REDO
1670 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1671 op->undo_redo_data);
1672 // End UNDO-REDO
1673 g_free (op);
1674}
1675
1676void
1677caja_file_operation_complete (CajaFileOperation *op, GFile *result_file, GError *error)
1678{
1679 /* Claim that something changed even if the operation failed.
1680 * This makes it easier for some clients who see the "reverting"
1681 * as "changing back".
1682 */
1683 caja_file_operation_remove (op);
1684 caja_file_changed (op->file);
1685 if (op->callback) {
1686 (* op->callback) (op->file, result_file, error, op->callback_data);
1687 }
1688 caja_file_operation_free (op);
1689}
1690
1691void
1692caja_file_operation_cancel (CajaFileOperation *op)
1693{
1694 /* Cancel the operation if it's still in progress. */
1695 g_cancellable_cancel (op->cancellable);
1696}
1697
1698static void
1699rename_get_info_callback (GObject *source_object,
1700 GAsyncResult *res,
1701 gpointer callback_data)
1702{
1703 CajaFileOperation *op;
1704 GFileInfo *new_info;
1705 GError *error;
1706
1707 op = callback_data;
1708
1709 error = NULL((void*)0);
1710 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
1711 if (new_info != NULL((void*)0)) {
1712 CajaDirectory *directory;
1713 CajaFile *existing_file;
1714 char *old_name;
1715 char *old_uri;
1716 char *new_uri;
1717 const char *new_name;
1718
1719 directory = op->file->details->directory;
1720
1721 new_name = g_file_info_get_name (new_info);
1722
1723 /* If there was another file by the same name in this
1724 * directory, mark it gone.
1725 */
1726 existing_file = caja_directory_find_file_by_name (directory, new_name);
1727 if (existing_file != NULL((void*)0)) {
1728 caja_file_mark_gone (existing_file);
1729 caja_file_changed (existing_file);
1730 }
1731
1732 old_uri = caja_file_get_uri (op->file);
1733 old_name = g_strdup (op->file->details->name)g_strdup_inline (op->file->details->name);
1734
1735 update_info_and_name (op->file, new_info);
1736
1737 g_free (old_name);
1738
1739 new_uri = caja_file_get_uri (op->file);
1740 caja_directory_moved (old_uri, new_uri);
1741 g_free (new_uri);
1742 g_free (old_uri);
1743
1744 /* the rename could have affected the display name if e.g.
1745 * we're in a vfolder where the name comes from a desktop file
1746 * and a rename affects the contents of the desktop file.
1747 */
1748 if (op->file->details->got_custom_display_name) {
1749 caja_file_invalidate_attributes (op->file,
1750 CAJA_FILE_ATTRIBUTE_INFO |
1751 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1752 }
1753
1754 g_object_unref (new_info);
1755 }
1756 caja_file_operation_complete (op, NULL((void*)0), error);
1757 if (error) {
1758 g_error_free (error);
1759 }
1760}
1761
1762static void
1763rename_callback (GObject *source_object,
1764 GAsyncResult *res,
1765 gpointer callback_data)
1766{
1767 CajaFileOperation *op;
1768 GFile *new_file;
1769 GError *error;
1770
1771 op = callback_data;
1772
1773 error = NULL((void*)0);
1774 new_file = g_file_set_display_name_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
1775 res, &error);
1776
1777 if (new_file != NULL((void*)0)) {
1778 // Start UNDO-REDO
1779 caja_undostack_manager_data_set_rename_information(op->undo_redo_data, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), new_file);
1780 // End UNDO-REDO
1781 g_file_query_info_async (new_file,
1782 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
1783 0,
1784 G_PRIORITY_DEFAULT0,
1785 op->cancellable,
1786 rename_get_info_callback, op);
1787 } else {
1788 caja_file_operation_complete (op, NULL((void*)0), error);
1789 g_error_free (error);
1790 }
1791}
1792
1793static gboolean
1794name_is (CajaFile *file, const char *new_name)
1795{
1796 const char *old_name;
1797 old_name = file->details->name;
1798 return strcmp (new_name, old_name) == 0;
1799}
1800
1801void
1802caja_file_rename (CajaFile *file,
1803 const char *new_name,
1804 CajaFileOperationCallback callback,
1805 gpointer callback_data)
1806{
1807 CajaFileOperation *op;
1808 char *old_name;
1809 char *new_file_name;
1810 gboolean success, name_changed;
1811 gboolean is_renameable_desktop_file;
1812 GFile *location;
1813 GError *error;
1814
1815 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_591
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_591
= 1; else _g_boolean_var_591 = 0; _g_boolean_var_591; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
1816 g_return_if_fail (new_name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_592
; if (new_name != ((void*)0)) _g_boolean_var_592 = 1; else _g_boolean_var_592
= 0; _g_boolean_var_592; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "new_name != NULL"
); return; } } while (0)
;
1817 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_593
; if (callback != ((void*)0)) _g_boolean_var_593 = 1; else _g_boolean_var_593
= 0; _g_boolean_var_593; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
1818
1819 is_renameable_desktop_file =
1820 is_desktop_file (file) && can_rename_desktop_file (file);
1821
1822 /* Return an error for incoming names containing path separators.
1823 * But not for .desktop files as '/' are allowed for them */
1824 if (strstr (new_name, "/") != NULL((void*)0) && !is_renameable_desktop_file) {
1825 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
1826 _("Slashes are not allowed in filenames")dcgettext (((void*)0), "Slashes are not allowed in filenames"
, 5)
);
1827 (* callback) (file, NULL((void*)0), error, callback_data);
1828 g_error_free (error);
1829 return;
1830 }
1831
1832 /* Can't rename a file that's already gone.
1833 * We need to check this here because there may be a new
1834 * file with the same name.
1835 */
1836 if (caja_file_is_gone (file)) {
1837 /* Claim that something changed even if the rename
1838 * failed. This makes it easier for some clients who
1839 * see the "reverting" to the old name as "changing
1840 * back".
1841 */
1842 caja_file_changed (file);
1843 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_FOUND,
1844 _("File not found")dcgettext (((void*)0), "File not found", 5));
1845 (* callback) (file, NULL((void*)0), error, callback_data);
1846 g_error_free (error);
1847 return;
1848 }
1849
1850 /* Test the name-hasn't-changed case explicitly, for two reasons.
1851 * (1) rename returns an error if new & old are same.
1852 * (2) We don't want to send file-changed signal if nothing changed.
1853 */
1854 if (!CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
&&
1855 !is_renameable_desktop_file &&
1856 name_is (file, new_name)) {
1857 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1858 return;
1859 }
1860
1861 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1862 * case before this case.
1863 */
1864 if (caja_file_is_self_owned (file)) {
1865 /* Claim that something changed even if the rename
1866 * failed. This makes it easier for some clients who
1867 * see the "reverting" to the old name as "changing
1868 * back".
1869 */
1870 caja_file_changed (file);
1871 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1872 _("Toplevel files cannot be renamed")dcgettext (((void*)0), "Toplevel files cannot be renamed", 5));
1873
1874 (* callback) (file, NULL((void*)0), error, callback_data);
1875 g_error_free (error);
1876 return;
1877 }
1878
1879 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1880 CajaDesktopLink *link;
1881
1882 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1883 old_name = caja_file_get_display_name (file);
1884
1885 if ((old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0)) {
1886 success = TRUE(!(0));
1887 } else {
1888 success = (link != NULL((void*)0) && caja_desktop_link_rename (link, new_name));
1889 }
1890
1891 if (success) {
1892 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1893 } else {
1894 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1895 _("Unable to rename desktop icon")dcgettext (((void*)0), "Unable to rename desktop icon", 5));
1896 (* callback) (file, NULL((void*)0), error, callback_data);
1897 g_error_free (error);
1898 }
1899
1900 g_free (old_name);
1901 g_object_unref (link);
1902 return;
1903 }
1904
1905 if (is_renameable_desktop_file) {
1906 char *uri;
1907
1908 /* Don't actually change the name if the new name is the same.
1909 * This helps for the vfolder method where this can happen and
1910 * we want to minimize actual changes
1911 */
1912 uri = caja_file_get_uri (file);
1913 old_name = caja_link_local_get_text (uri);
1914 if (old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0) {
1915 success = TRUE(!(0));
1916 name_changed = FALSE(0);
1917 } else {
1918 success = caja_link_local_set_text (uri, new_name);
1919 name_changed = TRUE(!(0));
1920 }
1921 g_free (old_name);
1922 g_free (uri);
1923
1924 if (!success) {
1925 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1926 _("Unable to rename desktop file")dcgettext (((void*)0), "Unable to rename desktop file", 5));
1927 (* callback) (file, NULL((void*)0), error, callback_data);
1928 g_error_free (error);
1929 return;
1930 }
1931 if (!g_str_has_suffix(new_name, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (new_name); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_594; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_594 = 1; else _g_boolean_var_594
= 0; _g_boolean_var_594; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (new_name, ".desktop") )
)
1932 new_file_name = g_strdup_printf ("%s.desktop", new_name);
1933 else
1934 new_file_name = g_strdup_printf("%s", new_name);
1935 new_file_name = g_strdelimit (new_file_name, "/", '-');
1936
1937 if (name_is (file, new_file_name)) {
1938 if (name_changed) {
1939 caja_file_invalidate_attributes (file,
1940 CAJA_FILE_ATTRIBUTE_INFO |
1941 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1942 }
1943
1944 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1945 g_free (new_file_name);
1946 return;
1947 }
1948 } else {
1949 new_file_name = g_strdup (new_name)g_strdup_inline (new_name);
1950 }
1951
1952 /* Set up a renaming operation. */
1953 op = caja_file_operation_new (file, callback, callback_data);
1954 op->is_rename = TRUE(!(0));
1955
1956 /* Do the renaming. */
1957
1958 location = caja_file_get_location (file);
1959
1960 // Start UNDO-REDO
1961 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
1962 op->undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RENAME, 1);
1963 }
1964 // End UNDO-REDO
1965
1966 g_file_set_display_name_async (location,
1967 new_file_name,
1968 G_PRIORITY_DEFAULT0,
1969 op->cancellable,
1970 rename_callback,
1971 op);
1972 g_free (new_file_name);
1973 g_object_unref (location);
1974}
1975
1976gboolean
1977caja_file_rename_in_progress (CajaFile *file)
1978{
1979 GList *node;
1980 CajaFileOperation *op = NULL((void*)0);
1981
1982 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = node->next) {
1983 op = node->data;
1984 if (op->is_rename) {
1985 return TRUE(!(0));
1986 }
1987 }
1988 return FALSE(0);
1989}
1990
1991void
1992caja_file_cancel (CajaFile *file,
1993 CajaFileOperationCallback callback,
1994 gpointer callback_data)
1995{
1996 GList *node, *next;
1997 CajaFileOperation *op = NULL((void*)0);
1998
1999 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = next) {
2000 next = node->next;
2001 op = node->data;
2002
2003 g_assert (op->file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_595
; if (op->file == file) _g_boolean_var_595 = 1; else _g_boolean_var_595
= 0; _g_boolean_var_595; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2003, ((const char*) (__func__
)), "op->file == file"); } while (0)
;
2004 if (op->callback == callback && op->callback_data == callback_data) {
2005 caja_file_operation_cancel (op);
2006 }
2007 }
2008}
2009
2010gboolean
2011caja_file_matches_uri (CajaFile *file, const char *match_uri)
2012{
2013 GFile *match_file, *location;
2014 gboolean result;
2015
2016 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_596
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_596
= 1; else _g_boolean_var_596 = 0; _g_boolean_var_596; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2017 g_return_val_if_fail (match_uri != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_597
; if (match_uri != ((void*)0)) _g_boolean_var_597 = 1; else _g_boolean_var_597
= 0; _g_boolean_var_597; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "match_uri != NULL"
); return ((0)); } } while (0)
;
2018
2019 location = caja_file_get_location (file);
2020 match_file = g_file_new_for_uri (match_uri);
2021 result = g_file_equal (location, match_file);
2022 g_object_unref (location);
2023 g_object_unref (match_file);
2024
2025 return result;
2026}
2027
2028int
2029caja_file_compare_location (CajaFile *file_1,
2030 CajaFile *file_2)
2031{
2032 GFile *loc_a, *loc_b;
2033 gboolean res;
2034
2035 loc_a = caja_file_get_location (file_1);
2036 loc_b = caja_file_get_location (file_2);
2037
2038 res = !g_file_equal (loc_a, loc_b);
2039
2040 g_object_unref (loc_a);
2041 g_object_unref (loc_b);
2042
2043 return (gint) res;
2044}
2045
2046gboolean
2047caja_file_is_local (CajaFile *file)
2048{
2049 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_598
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_598
= 1; else _g_boolean_var_598 = 0; _g_boolean_var_598; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2050
2051 return caja_directory_is_local (file->details->directory);
2052}
2053
2054static void
2055update_link (CajaFile *link_file, CajaFile *target_file)
2056{
2057 g_assert (CAJA_IS_FILE (link_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_599
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((link_file)); GType __t = (caja_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_599
= 1; else _g_boolean_var_599 = 0; _g_boolean_var_599; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2057, ((const char*) (__func__)), "CAJA_IS_FILE (link_file)"
); } while (0)
;
2058 g_assert (CAJA_IS_FILE (target_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_600
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_file)); GType __t = (caja_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_600
= 1; else _g_boolean_var_600 = 0; _g_boolean_var_600; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2058, ((const char*) (__func__)), "CAJA_IS_FILE (target_file)"
); } while (0)
;
2059
2060 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
2061 * here then the hash table is a waste of time.
2062 */
2063}
2064
2065static GList *
2066get_link_files (CajaFile *target_file)
2067{
2068 GList **link_files;
2069
2070 if (symbolic_links == NULL((void*)0)) {
2071 link_files = NULL((void*)0);
2072 } else {
2073 char *uri;
2074
2075 uri = caja_file_get_uri (target_file);
2076 link_files = g_hash_table_lookup (symbolic_links, uri);
2077 g_free (uri);
2078 }
2079 if (link_files) {
2080 return caja_file_list_copy (*link_files);
2081 }
2082 return NULL((void*)0);
2083}
2084
2085static void
2086update_links_if_target (CajaFile *target_file)
2087{
2088 GList *link_files, *p;
2089
2090 link_files = get_link_files (target_file);
2091 for (p = link_files; p != NULL((void*)0); p = p->next) {
2092 update_link (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))), target_file);
2093 }
2094 caja_file_list_free (link_files);
2095}
2096
2097static gboolean
2098update_info_internal (CajaFile *file,
2099 GFileInfo *info,
2100 gboolean update_name)
2101{
2102 gboolean changed;
2103 gboolean is_symlink, is_hidden, is_backup, is_mountpoint;
2104 gboolean has_permissions;
2105 guint32 permissions;
2106 gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2107 gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2108 GDriveStartStopType start_stop_type;
2109 gboolean thumbnailing_failed;
2110 int uid, gid;
2111 goffset size;
2112 goffset size_on_disk;
2113 int sort_order;
2114 time_t atime, mtime, ctime, btime;
2115 time_t trash_time;
2116 const char * time_string;
2117 const char *symlink_name, *mime_type, *selinux_context, *thumbnail_path;
2118 GFileType file_type;
2119 GIcon *icon;
2120 const char *description;
2121 const char *filesystem_id;
2122 const char *trash_orig_path;
2123 const char *group, *owner, *owner_real;
2124 gboolean free_owner, free_group;
2125
2126 if (file->details->is_gone) {
2127 return FALSE(0);
2128 }
2129
2130 if (info == NULL((void*)0)) {
2131 caja_file_mark_gone (file);
2132 return TRUE(!(0));
2133 }
2134
2135 file->details->file_info_is_up_to_date = TRUE(!(0));
2136
2137 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2138 * point to the old name know that the file has been renamed.
2139 */
2140
2141 remove_from_link_hash_table (file);
2142
2143 changed = FALSE(0);
2144
2145 if (!file->details->got_file_info) {
2146 changed = TRUE(!(0));
2147 }
2148 file->details->got_file_info = TRUE(!(0));
2149
2150 changed |= caja_file_set_display_name (file,
2151 g_file_info_get_display_name (info),
2152 g_file_info_get_edit_name (info),
2153 FALSE(0));
2154
2155 file_type = g_file_info_get_file_type (info);
2156 if (file->details->type != file_type) {
2157 changed = TRUE(!(0));
2158 }
2159 file->details->type = file_type;
2160
2161 if (!file->details->got_custom_activation_uri) {
2162 const char *activation_uri;
2163
2164 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri");
2165 if (activation_uri == NULL((void*)0)) {
2166 if (file->details->activation_uri) {
2167 g_free (file->details->activation_uri);
2168 file->details->activation_uri = NULL((void*)0);
2169 changed = TRUE(!(0));
2170 }
2171 } else {
2172 char *old_activation_uri;
2173
2174 old_activation_uri = file->details->activation_uri;
2175 file->details->activation_uri = g_strdup (activation_uri)g_strdup_inline (activation_uri);
2176
2177 if (old_activation_uri) {
2178 if (strcmp (old_activation_uri,
2179 file->details->activation_uri) != 0) {
2180 changed = TRUE(!(0));
2181 }
2182 g_free (old_activation_uri);
2183 } else {
2184 changed = TRUE(!(0));
2185 }
2186 }
2187 }
2188
2189 is_symlink = g_file_info_get_is_symlink (info);
2190 if (file->details->is_symlink != is_symlink) {
2191 changed = TRUE(!(0));
2192 }
2193 file->details->is_symlink = is_symlink;
2194
2195 is_hidden = g_file_info_get_is_hidden (info);
2196 is_backup = g_file_info_get_is_backup (info);
2197 if (file->details->is_hidden != is_hidden ||
2198 file->details->is_backup != is_backup) {
2199 changed = TRUE(!(0));
2200 }
2201 file->details->is_hidden = is_hidden;
2202 file->details->is_backup = is_backup;
2203
2204 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT"unix::is-mountpoint");
2205 if (file->details->is_mountpoint != is_mountpoint) {
2206 changed = TRUE(!(0));
2207 }
2208 file->details->is_mountpoint = is_mountpoint;
2209
2210 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
2211 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");;
2212 if (file->details->has_permissions != has_permissions ||
2213 file->details->permissions != permissions) {
2214 changed = TRUE(!(0));
2215 }
2216 file->details->has_permissions = has_permissions;
2217 file->details->permissions = permissions;
2218
2219 /* We default to TRUE for this if we can't know */
2220 can_read = TRUE(!(0));
2221 can_write = TRUE(!(0));
2222 can_execute = TRUE(!(0));
2223 can_delete = TRUE(!(0));
2224 can_trash = TRUE(!(0));
2225 can_rename = TRUE(!(0));
2226 can_mount = FALSE(0);
2227 can_unmount = FALSE(0);
2228 can_eject = FALSE(0);
2229 can_start = FALSE(0);
2230 can_start_degraded = FALSE(0);
2231 can_stop = FALSE(0);
2232 can_poll_for_media = FALSE(0);
2233 is_media_check_automatic = FALSE(0);
2234 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2235 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read")) {
2236 can_read = g_file_info_get_attribute_boolean (info,
2237 G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read");
2238 }
2239 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write")) {
2240 can_write = g_file_info_get_attribute_boolean (info,
2241 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write");
2242 }
2243 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute")) {
2244 can_execute = g_file_info_get_attribute_boolean (info,
2245 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute");
2246 }
2247 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete")) {
2248 can_delete = g_file_info_get_attribute_boolean (info,
2249 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete");
2250 }
2251 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash")) {
2252 can_trash = g_file_info_get_attribute_boolean (info,
2253 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash");
2254 }
2255 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename")) {
2256 can_rename = g_file_info_get_attribute_boolean (info,
2257 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename");
2258 }
2259 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount")) {
2260 can_mount = g_file_info_get_attribute_boolean (info,
2261 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount");
2262 }
2263 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount")) {
2264 can_unmount = g_file_info_get_attribute_boolean (info,
2265 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount");
2266 }
2267 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject")) {
2268 can_eject = g_file_info_get_attribute_boolean (info,
2269 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject");
2270 }
2271 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start")) {
2272 can_start = g_file_info_get_attribute_boolean (info,
2273 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start");
2274 }
2275 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded")) {
2276 can_start_degraded = g_file_info_get_attribute_boolean (info,
2277 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded");
2278 }
2279 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop")) {
2280 can_stop = g_file_info_get_attribute_boolean (info,
2281 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop");
2282 }
2283 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type")) {
2284 start_stop_type = g_file_info_get_attribute_uint32 (info,
2285 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type");
2286 }
2287 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll")) {
2288 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2289 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll");
2290 }
2291 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic")) {
2292 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2293 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic");
2294 }
2295 if (file->details->can_read != can_read ||
2296 file->details->can_write != can_write ||
2297 file->details->can_execute != can_execute ||
2298 file->details->can_delete != can_delete ||
2299 file->details->can_trash != can_trash ||
2300 file->details->can_rename != can_rename ||
2301 file->details->can_mount != can_mount ||
2302 file->details->can_unmount != can_unmount ||
2303 file->details->can_eject != can_eject ||
2304 file->details->can_start != can_start ||
2305 file->details->can_start_degraded != can_start_degraded ||
2306 file->details->can_stop != can_stop ||
2307 file->details->start_stop_type != start_stop_type ||
2308 file->details->can_poll_for_media != can_poll_for_media ||
2309 file->details->is_media_check_automatic != is_media_check_automatic) {
2310 changed = TRUE(!(0));
2311 }
2312
2313 file->details->can_read = can_read;
2314 file->details->can_write = can_write;
2315 file->details->can_execute = can_execute;
2316 file->details->can_delete = can_delete;
2317 file->details->can_trash = can_trash;
2318 file->details->can_rename = can_rename;
2319 file->details->can_mount = can_mount;
2320 file->details->can_unmount = can_unmount;
2321 file->details->can_eject = can_eject;
2322 file->details->can_start = can_start;
2323 file->details->can_start_degraded = can_start_degraded;
2324 file->details->can_stop = can_stop;
2325 file->details->start_stop_type = start_stop_type;
2326 file->details->can_poll_for_media = can_poll_for_media;
2327 file->details->is_media_check_automatic = is_media_check_automatic;
2328
2329 free_owner = FALSE(0);
2330 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER"owner::user");
2331 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL"owner::user-real");
2332 free_group = FALSE(0);
2333 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
2334
2335 uid = -1;
2336 gid = -1;
2337 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid")) {
2338 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid");
2339 if (owner == NULL((void*)0)) {
2340 free_owner = TRUE(!(0));
2341 owner = g_strdup_printf ("%d", uid);
2342 }
2343 }
2344 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid")) {
2345 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid");
2346 if (group == NULL((void*)0)) {
2347 free_group = TRUE(!(0));
2348 group = g_strdup_printf ("%d", gid);
2349 }
2350 }
2351 if (file->details->uid != uid ||
2352 file->details->gid != gid) {
2353 changed = TRUE(!(0));
2354 }
2355 file->details->uid = uid;
2356 file->details->gid = gid;
2357
2358 if (eel_strcmp (file->details->owner, owner) != 0) {
2359 changed = TRUE(!(0));
2360 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2361 file->details->owner = g_ref_string_new_intern (owner);
2362 }
2363
2364 if (eel_strcmp (file->details->owner_real, owner_real) != 0) {
2365 changed = TRUE(!(0));
2366 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2367 file->details->owner_real = g_ref_string_new_intern (owner_real);
2368 }
2369
2370 if (eel_strcmp (file->details->group, group) != 0) {
2371 changed = TRUE(!(0));
2372 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2373 file->details->group = g_ref_string_new_intern (group);
2374 }
2375
2376 if (free_owner) {
2377 g_free ((char *)owner);
2378 }
2379 if (free_group) {
2380 g_free ((char *)group);
2381 }
2382
2383 size = -1;
2384 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size")) {
2385 size = g_file_info_get_size (info);
2386 }
2387 if (file->details->size != size) {
2388 changed = TRUE(!(0));
2389 }
2390 file->details->size = size;
2391
2392 size_on_disk = -1;
2393 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size")) {
2394 size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size");
2395 }
2396 if (file->details->size_on_disk != size_on_disk) {
2397 changed = TRUE(!(0));
2398 }
2399 file->details->size_on_disk = size_on_disk;
2400
2401 sort_order = g_file_info_get_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER"standard::sort-order");
2402 if (file->details->sort_order != sort_order) {
2403 changed = TRUE(!(0));
2404 }
2405 file->details->sort_order = sort_order;
2406
2407 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS"time::access");
2408 ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED"time::changed");
2409 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
2410 btime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED"time::created");
2411 if (file->details->atime != atime ||
2412 file->details->mtime != mtime ||
2413 file->details->ctime != ctime ||
2414 file->details->btime != btime) {
2415 if (file->details->thumbnail == NULL((void*)0)) {
2416 file->details->thumbnail_is_up_to_date = FALSE(0);
2417 }
2418
2419 changed = TRUE(!(0));
2420 }
2421 file->details->atime = atime;
2422 file->details->ctime = ctime;
2423 file->details->mtime = mtime;
2424 file->details->btime = btime;
2425
2426 if (file->details->thumbnail != NULL((void*)0) &&
2427 file->details->thumbnail_mtime != 0 &&
2428 file->details->thumbnail_mtime != mtime) {
2429 file->details->thumbnail_is_up_to_date = FALSE(0);
2430 changed = TRUE(!(0));
2431 }
2432
2433 icon = g_file_info_get_icon (info);
2434 if (!g_icon_equal (icon, file->details->icon)) {
2435 changed = TRUE(!(0));
2436
2437 if (file->details->icon) {
2438 g_object_unref (file->details->icon);
2439 }
2440 file->details->icon = g_object_ref (icon)((__typeof__ (icon)) (g_object_ref) (icon));
2441 }
2442
2443 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
2444 if (eel_strcmp (file->details->thumbnail_path, thumbnail_path) != 0) {
2445 changed = TRUE(!(0));
2446 g_free (file->details->thumbnail_path);
2447 file->details->thumbnail_path = g_strdup (thumbnail_path)g_strdup_inline (thumbnail_path);
2448 }
2449
2450 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED"thumbnail::failed");
2451 if (file->details->thumbnailing_failed != thumbnailing_failed) {
2452 changed = TRUE(!(0));
2453 file->details->thumbnailing_failed = thumbnailing_failed;
2454 }
2455
2456 symlink_name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET"standard::symlink-target");
2457
2458 if (eel_strcmp (file->details->symlink_name, symlink_name) != 0) {
2459 changed = TRUE(!(0));
2460 g_free (file->details->symlink_name);
2461 file->details->symlink_name = g_strdup (symlink_name)g_strdup_inline (symlink_name);
2462 }
2463
2464 mime_type = g_file_info_get_content_type (info);
2465 if (eel_strcmp (file->details->mime_type, mime_type) != 0) {
2466 changed = TRUE(!(0));
2467 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2468 file->details->mime_type = g_ref_string_new_intern (mime_type);
2469 }
2470
2471 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT"selinux::context");
2472 if (eel_strcmp (file->details->selinux_context, selinux_context) != 0) {
2473 changed = TRUE(!(0));
2474 g_free (file->details->selinux_context);
2475 file->details->selinux_context = g_strdup (selinux_context)g_strdup_inline (selinux_context);
2476 }
2477
2478 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION"standard::description");
2479 if (eel_strcmp (file->details->description, description) != 0) {
2480 changed = TRUE(!(0));
2481 g_free (file->details->description);
2482 file->details->description = g_strdup (description)g_strdup_inline (description);
2483 }
2484
2485 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
2486 if (eel_strcmp (file->details->filesystem_id, filesystem_id) != 0) {
2487 changed = TRUE(!(0));
2488 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
2489 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2490 }
2491
2492 trash_time = 0;
2493 time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"trash::deletion-date");
2494 if (time_string != NULL((void*)0)) {
2495#if GLIB_CHECK_VERSION(2,61,2)(2 > (2) || (2 == (2) && 80 > (61)) || (2 == (2
) && 80 == (61) && 3 >= (2)))
2496 GDateTime *dt;
2497 GTimeZone *tz;
2498 tz = g_time_zone_new_local ();
2499 dt = g_date_time_new_from_iso8601 (time_string, tz);
2500 if (dt) {
2501 trash_time = (time_t) g_date_time_to_unix (dt);
2502 g_date_time_unref (dt);
2503 }
2504 g_time_zone_unref (tz);
2505#else
2506 GTimeVal g_trash_time;
2507 g_time_val_from_iso8601 (time_string, &g_trash_time);
2508 trash_time = g_trash_time.tv_sec;
2509#endif
2510 }
2511 if (file->details->trash_time != trash_time) {
2512 changed = TRUE(!(0));
2513 file->details->trash_time = trash_time;
2514 }
2515
2516 trash_orig_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path");
2517 if (eel_strcmp (file->details->trash_orig_path, trash_orig_path) != 0) {
2518 changed = TRUE(!(0));
2519 g_free (file->details->trash_orig_path);
2520 file->details->trash_orig_path = g_strdup (trash_orig_path)g_strdup_inline (trash_orig_path);
2521 }
2522
2523 changed |=
2524 caja_file_update_metadata_from_info (file, info);
2525
2526 if (update_name) {
2527 const char *name;
2528
2529 name = g_file_info_get_name (info);
2530 if (file->details->name == NULL((void*)0) ||
2531 strcmp (file->details->name, name) != 0) {
2532 GList *node;
2533
2534 changed = TRUE(!(0));
2535
2536 node = caja_directory_begin_file_name_change
2537 (file->details->directory, file);
2538
2539 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2540 if (eel_strcmp (file->details->display_name, name) == 0) {
2541 file->details->name = g_ref_string_acquire (file->details->display_name);
2542 } else {
2543 file->details->name = g_ref_string_new (name);
2544 }
2545
2546 if (!file->details->got_custom_display_name &&
2547 g_file_info_get_display_name (info) == NULL((void*)0)) {
2548 /* If the file info's display name is NULL,
2549 * caja_file_set_display_name() did
2550 * not unset the display name.
2551 */
2552 caja_file_clear_display_name (file);
2553 }
2554
2555 caja_directory_end_file_name_change
2556 (file->details->directory, file, node);
2557 }
2558 }
2559
2560 if (changed) {
2561 add_to_link_hash_table (file);
2562
2563 update_links_if_target (file);
2564 }
2565
2566 return changed;
2567}
2568
2569static gboolean
2570update_info_and_name (CajaFile *file,
2571 GFileInfo *info)
2572{
2573 return update_info_internal (file, info, TRUE(!(0)));
2574}
2575
2576gboolean
2577caja_file_update_info (CajaFile *file,
2578 GFileInfo *info)
2579{
2580 return update_info_internal (file, info, FALSE(0));
2581}
2582
2583void
2584caja_file_refresh_info (CajaFile *file)
2585{
2586 GFile *gfile;
2587 GFileInfo *new_info;
2588
2589 gfile = caja_file_get_location (file);
2590 new_info = g_file_query_info (gfile, CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
2591 G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
2592 if (new_info != NULL((void*)0)) {
2593 if (caja_file_update_info (file, new_info)) {
2594 caja_file_changed (file);
2595 }
2596 g_object_unref (new_info);
2597 }
2598 g_object_unref (gfile);
2599}
2600
2601static gboolean
2602update_name_internal (CajaFile *file,
2603 const char *name,
2604 gboolean in_directory)
2605{
2606 GList *node;
2607
2608 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_601
; if (name != ((void*)0)) _g_boolean_var_601 = 1; else _g_boolean_var_601
= 0; _g_boolean_var_601; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2608, ((const char*) (__func__
)), "name != NULL"); } while (0)
;
2609
2610 if (file->details->is_gone) {
2611 return FALSE(0);
2612 }
2613
2614 if (name_is (file, name)) {
2615 return FALSE(0);
2616 }
2617
2618 node = NULL((void*)0);
2619 if (in_directory) {
2620 node = caja_directory_begin_file_name_change
2621 (file->details->directory, file);
2622 }
2623
2624 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2625 file->details->name = g_ref_string_new (name);
2626
2627 if (!file->details->got_custom_display_name) {
2628 caja_file_clear_display_name (file);
2629 }
2630
2631 if (in_directory) {
2632 caja_directory_end_file_name_change
2633 (file->details->directory, file, node);
2634 }
2635
2636 return TRUE(!(0));
2637}
2638
2639gboolean
2640caja_file_update_name (CajaFile *file, const char *name)
2641{
2642 gboolean ret;
2643
2644 ret = update_name_internal (file, name, TRUE(!(0)));
2645
2646 if (ret) {
2647 update_links_if_target (file);
2648 }
2649
2650 return ret;
2651}
2652
2653gboolean
2654caja_file_update_name_and_directory (CajaFile *file,
2655 const char *name,
2656 CajaDirectory *new_directory)
2657{
2658 CajaDirectory *old_directory;
2659 FileMonitors *monitors;
2660
2661 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_602
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_602
= 1; else _g_boolean_var_602 = 0; _g_boolean_var_602; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2662 g_return_val_if_fail (CAJA_IS_DIRECTORY (file->details->directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_603
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file->details->directory)); GType __t = (caja_directory_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_603 = 1; else _g_boolean_var_603 =
0; _g_boolean_var_603; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_DIRECTORY (file->details->directory)"
); return ((0)); } } while (0)
;
2663 g_return_val_if_fail (!file->details->is_gone, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_604
; if (!file->details->is_gone) _g_boolean_var_604 = 1; else
_g_boolean_var_604 = 0; _g_boolean_var_604; }), 1))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "!file->details->is_gone"); return ((0)); } } while
(0)
;
2664 g_return_val_if_fail (!caja_file_is_self_owned (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_605
; if (!caja_file_is_self_owned (file)) _g_boolean_var_605 = 1
; else _g_boolean_var_605 = 0; _g_boolean_var_605; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "!caja_file_is_self_owned (file)"); return ((
0)); } } while (0)
;
2665 g_return_val_if_fail (CAJA_IS_DIRECTORY (new_directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_606
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_directory)); GType __t = (caja_directory_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_606 = 1; else _g_boolean_var_606 = 0; _g_boolean_var_606
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "CAJA_IS_DIRECTORY (new_directory)"
); return ((0)); } } while (0)
;
2666
2667 old_directory = file->details->directory;
2668 if (old_directory == new_directory) {
2669 if (name) {
2670 return update_name_internal (file, name, TRUE(!(0)));
2671 } else {
2672 return FALSE(0);
2673 }
2674 }
2675
2676 caja_file_ref (file);
2677
2678 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2679 * point to the old name know that the file has been moved.
2680 */
2681
2682 remove_from_link_hash_table (file);
2683
2684 monitors = caja_directory_remove_file_monitors (old_directory, file);
2685 caja_directory_remove_file (old_directory, file);
2686
2687 file->details->directory = caja_directory_ref (new_directory);
2688 caja_directory_unref (old_directory);
2689
2690 if (name) {
2691 update_name_internal (file, name, FALSE(0));
2692 }
2693
2694 caja_directory_add_file (new_directory, file);
2695 caja_directory_add_file_monitors (new_directory, file, monitors);
2696
2697 add_to_link_hash_table (file);
2698
2699 update_links_if_target (file);
2700
2701 caja_file_unref (file);
2702
2703 return TRUE(!(0));
2704}
2705
2706void
2707caja_file_set_directory (CajaFile *file,
2708 CajaDirectory *new_directory)
2709{
2710 caja_file_update_name_and_directory (file, NULL((void*)0), new_directory);
2711}
2712
2713static Knowledge
2714get_item_count (CajaFile *file,
2715 guint *count)
2716{
2717 gboolean known, unreadable;
2718
2719 known = caja_file_get_directory_item_count
2720 (file, count, &unreadable);
2721 if (!known) {
2722 return UNKNOWN;
2723 }
2724 if (unreadable) {
2725 return UNKNOWABLE;
2726 }
2727 return KNOWN;
2728}
2729
2730static Knowledge
2731get_size (CajaFile *file,
2732 goffset *size,
2733 gboolean size_on_disk)
2734{
2735 /* If we tried and failed, then treat it like there is no size
2736 * to know.
2737 */
2738 if (file->details->get_info_failed) {
2739 return UNKNOWABLE;
2740 }
2741
2742 /* If the info is NULL that means we haven't even tried yet,
2743 * so it's just unknown, not unknowable.
2744 */
2745 if (!file->details->got_file_info) {
2746 return UNKNOWN;
2747 }
2748
2749 /* If we got info with no size in it, it means there is no
2750 * such thing as a size as far as mate-vfs is concerned,
2751 * so "unknowable".
2752 */
2753 if (size_on_disk && file->details->size_on_disk == -1) {
2754 return UNKNOWABLE;
2755 }
2756
2757 if (!size_on_disk && file->details->size == -1) {
2758 return UNKNOWABLE;
2759 }
2760
2761 /* We have a size! */
2762 if (size_on_disk) {
2763 *size = file->details->size_on_disk;
2764 } else {
2765 *size = file->details->size;
2766 }
2767
2768 return KNOWN;
2769}
2770
2771static Knowledge
2772get_time (CajaFile *file,
2773 time_t *time_out,
2774 CajaDateType type)
2775{
2776 time_t time;
2777
2778 /* If we tried and failed, then treat it like there is no size
2779 * to know.
2780 */
2781 if (file->details->get_info_failed) {
2782 return UNKNOWABLE;
2783 }
2784
2785 /* If the info is NULL that means we haven't even tried yet,
2786 * so it's just unknown, not unknowable.
2787 */
2788 if (!file->details->got_file_info) {
2789 return UNKNOWN;
2790 }
2791
2792 time = 0;
2793 switch (type) {
2794 case CAJA_DATE_TYPE_MODIFIED:
2795 time = file->details->mtime;
2796 break;
2797 case CAJA_DATE_TYPE_ACCESSED:
2798 time = file->details->atime;
2799 break;
2800 case CAJA_DATE_TYPE_CREATED:
2801 time = file->details->btime;
2802 break;
2803 case CAJA_DATE_TYPE_TRASHED:
2804 time = file->details->trash_time;
2805 break;
2806 default:
2807 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file.c", 2807
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2808 break;
2809 }
2810
2811 *time_out = time;
2812
2813 /* If we got info with no modification time in it, it means
2814 * there is no such thing as a modification time as far as
2815 * mate-vfs is concerned, so "unknowable".
2816 */
2817 if (time == 0) {
2818 return UNKNOWABLE;
2819 }
2820 return KNOWN;
2821}
2822
2823static int
2824compare_directories_by_count (CajaFile *file_1, CajaFile *file_2)
2825{
2826 /* Sort order:
2827 * Directories with unknown # of items
2828 * Directories with "unknowable" # of items
2829 * Directories with 0 items
2830 * Directories with n items
2831 */
2832
2833 Knowledge count_known_1, count_known_2;
2834 guint count_1, count_2;
2835
2836 count_known_1 = get_item_count (file_1, &count_1);
2837 count_known_2 = get_item_count (file_2, &count_2);
2838
2839 if (count_known_1 > count_known_2) {
2840 return -1;
2841 }
2842 if (count_known_1 < count_known_2) {
2843 return +1;
2844 }
2845
2846 /* count_known_1 and count_known_2 are equal now. Check if count
2847 * details are UNKNOWABLE or UNKNOWN.
2848 */
2849 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2850 return 0;
2851 }
2852
2853 if (count_1 < count_2) {
2854 return -1;
2855 }
2856 if (count_1 > count_2) {
2857 return +1;
2858 }
2859
2860 return 0;
2861}
2862
2863static int
2864compare_files_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2865{
2866 /* Sort order:
2867 * Files with unknown size.
2868 * Files with "unknowable" size.
2869 * Files with smaller sizes.
2870 * Files with large sizes.
2871 */
2872
2873 Knowledge size_known_1, size_known_2;
2874 goffset size_1 = 0, size_2 = 0;
2875
2876 size_known_1 = get_size (file_1, &size_1, size_on_disk);
2877 size_known_2 = get_size (file_2, &size_2, size_on_disk);
2878
2879 if (size_known_1 > size_known_2) {
2880 return -1;
2881 }
2882 if (size_known_1 < size_known_2) {
2883 return +1;
2884 }
2885
2886 /* size_known_1 and size_known_2 are equal now. Check if size
2887 * details are UNKNOWABLE or UNKNOWN
2888 */
2889 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2890 return 0;
2891 }
2892
2893 if (size_1 < size_2) {
2894 return -1;
2895 }
2896 if (size_1 > size_2) {
2897 return +1;
2898 }
2899
2900 return 0;
2901}
2902
2903static int
2904compare_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2905{
2906 /* Sort order:
2907 * Directories with n items
2908 * Directories with 0 items
2909 * Directories with "unknowable" # of items
2910 * Directories with unknown # of items
2911 * Files with large sizes.
2912 * Files with smaller sizes.
2913 * Files with "unknowable" size.
2914 * Files with unknown size.
2915 */
2916
2917 gboolean is_directory_1, is_directory_2;
2918
2919 is_directory_1 = caja_file_is_directory (file_1);
2920 is_directory_2 = caja_file_is_directory (file_2);
2921
2922 if (is_directory_1 && !is_directory_2) {
2923 return -1;
2924 }
2925 if (is_directory_2 && !is_directory_1) {
2926 return +1;
2927 }
2928
2929 if (is_directory_1) {
2930 return compare_directories_by_count (file_1, file_2);
2931 } else {
2932 return compare_files_by_size (file_1, file_2, size_on_disk);
2933 }
2934}
2935
2936static int
2937compare_by_display_name (CajaFile *file_1, CajaFile *file_2)
2938{
2939 const char *name_1, *name_2;
2940 const char *key_1, *key_2;
2941 gboolean sort_last_1, sort_last_2;
2942 int compare;
2943
2944 name_1 = caja_file_peek_display_name (file_1);
2945 name_2 = caja_file_peek_display_name (file_2);
2946
2947 sort_last_1 = name_1[0] == SORT_LAST_CHAR1'.' || name_1[0] == SORT_LAST_CHAR2'#';
2948 sort_last_2 = name_2[0] == SORT_LAST_CHAR1'.' || name_2[0] == SORT_LAST_CHAR2'#';
2949
2950 if (sort_last_1 && !sort_last_2) {
2951 compare = +1;
2952 } else if (!sort_last_1 && sort_last_2) {
2953 compare = -1;
2954 } else {
2955 key_1 = caja_file_peek_display_name_collation_key (file_1);
2956 key_2 = caja_file_peek_display_name_collation_key (file_2);
2957 compare = strcmp (key_1, key_2);
2958 }
2959
2960 return compare;
2961}
2962
2963static int
2964compare_by_directory_name (CajaFile *file_1, CajaFile *file_2)
2965{
2966 char *directory_1, *directory_2;
2967 int compare;
2968
2969 if (file_1->details->directory == file_2->details->directory) {
2970 return 0;
2971 }
2972
2973 directory_1 = caja_file_get_parent_uri_for_display (file_1);
2974 directory_2 = caja_file_get_parent_uri_for_display (file_2);
2975
2976 compare = g_utf8_collate (directory_1, directory_2);
2977
2978 g_free (directory_1);
2979 g_free (directory_2);
2980
2981 return compare;
2982}
2983
2984static gboolean
2985file_has_note (CajaFile *file)
2986{
2987 char *note;
2988 gboolean res;
2989
2990 note = caja_file_get_metadata (file, CAJA_METADATA_KEY_ANNOTATION"annotation", NULL((void*)0));
2991 res = note != NULL((void*)0) && note[0] != 0;
2992 g_free (note);
2993
2994 return res;
2995}
2996
2997static GList *
2998prepend_automatic_keywords (CajaFile *file,
2999 GList *names)
3000{
3001 /* Prepend in reverse order. */
3002 CajaFile *parent;
3003
3004 parent = caja_file_get_parent (file);
3005
3006#ifdef TRASH_IS_FAST_ENOUGH
3007 if (caja_file_is_in_trash (file)) {
3008 names = g_list_prepend
3009 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash"));
3010 }
3011#endif
3012 if (file_has_note (file)) {
3013 names = g_list_prepend
3014 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_NOTE)g_strdup_inline ("note"));
3015 }
3016
3017 /* Trash files are assumed to be read-only,
3018 * so we want to ignore them here. */
3019 if (!caja_file_can_write (file) &&
3020 !caja_file_is_in_trash (file) &&
3021 (parent == NULL((void*)0) || caja_file_can_write (parent))) {
3022 names = g_list_prepend
3023 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite"));
3024 }
3025 if (!caja_file_can_read (file)) {
3026 names = g_list_prepend
3027 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_READ)g_strdup_inline ("noread"));
3028 }
3029 if (caja_file_is_symbolic_link (file)) {
3030 names = g_list_prepend
3031 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_SYMBOLIC_LINK)g_strdup_inline ("symbolic-link"));
3032 }
3033
3034 if (parent) {
3035 caja_file_unref (parent);
3036 }
3037
3038
3039 return names;
3040}
3041
3042static void
3043fill_emblem_cache_if_needed (CajaFile *file)
3044{
3045 GList *node, *keywords;
3046 char *scanner;
3047 size_t length;
3048
3049 if (file->details->compare_by_emblem_cache != NULL((void*)0)) {
3050 /* Got a cache already. */
3051 return;
3052 }
3053
3054 keywords = caja_file_get_keywords (file);
3055
3056 /* Add up the keyword string lengths */
3057 length = 1;
3058 for (node = keywords; node != NULL((void*)0); node = node->next) {
3059 length += strlen ((const char *) node->data) + 1;
3060 }
3061
3062 /* Now that we know how large the cache struct needs to be, allocate it. */
3063 file->details->compare_by_emblem_cache = g_malloc (sizeof(CajaFileSortByEmblemCache) + length);
3064
3065 /* Copy them into the cache. */
3066 scanner = file->details->compare_by_emblem_cache->emblem_keywords;
3067 for (node = keywords; node != NULL((void*)0); node = node->next) {
3068 length = strlen ((const char *) node->data) + 1;
3069 memcpy (scanner, (const char *) node->data, length);
3070 scanner += length;
3071 }
3072
3073 /* Zero-terminate so we can tell where the list ends. */
3074 *scanner = 0;
3075
3076 g_list_free_full (keywords, g_free);
3077}
3078
3079static int
3080compare_by_emblems (CajaFile *file_1, CajaFile *file_2)
3081{
3082 const char *keyword_cache_1, *keyword_cache_2;
3083 int compare_result;
3084
3085 fill_emblem_cache_if_needed (file_1);
3086 fill_emblem_cache_if_needed (file_2);
3087
3088 /* We ignore automatic emblems, and only sort by user-added keywords. */
3089 compare_result = 0;
3090 keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords;
3091 keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords;
3092 for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) {
3093 size_t length;
3094
3095 compare_result = g_utf8_collate (keyword_cache_1, keyword_cache_2);
3096 if (compare_result != 0) {
3097 return compare_result;
3098 }
3099
3100 /* Advance to the next keyword */
3101 length = strlen (keyword_cache_1);
3102 keyword_cache_1 += length + 1;
3103 keyword_cache_2 += length + 1;
3104 }
3105
3106
3107 /* One or both is now NULL. */
3108 if (*keyword_cache_1 != '\0') {
3109 g_assert (*keyword_cache_2 == '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_607
; if (*keyword_cache_2 == '\0') _g_boolean_var_607 = 1; else _g_boolean_var_607
= 0; _g_boolean_var_607; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3109, ((const char*) (__func__
)), "*keyword_cache_2 == '\\0'"); } while (0)
;
3110 return -1;
3111 } else if (*keyword_cache_2 != '\0') {
3112 return +1;
3113 }
3114
3115 return 0;
3116}
3117
3118static int
3119compare_by_type (CajaFile *file_1, CajaFile *file_2)
3120{
3121 gboolean is_directory_1;
3122 gboolean is_directory_2;
3123 char *type_string_1;
3124 char *type_string_2;
3125 int result;
3126
3127 /* Directories go first. Then, if mime types are identical,
3128 * don't bother getting strings (for speed). This assumes
3129 * that the string is dependent entirely on the mime type,
3130 * which is true now but might not be later.
3131 */
3132 is_directory_1 = caja_file_is_directory (file_1);
3133 is_directory_2 = caja_file_is_directory (file_2);
3134
3135 if (is_directory_1 && is_directory_2) {
3136 return 0;
3137 }
3138
3139 if (is_directory_1) {
3140 return -1;
3141 }
3142
3143 if (is_directory_2) {
3144 return +1;
3145 }
3146
3147 if (file_1->details->mime_type != NULL((void*)0) &&
3148 file_2->details->mime_type != NULL((void*)0) &&
3149 strcmp (file_1->details->mime_type,
3150 file_2->details->mime_type) == 0) {
3151 return 0;
3152 }
3153
3154 type_string_1 = caja_file_get_type_as_string (file_1);
3155 type_string_2 = caja_file_get_type_as_string (file_2);
3156
3157 result = g_utf8_collate (type_string_1, type_string_2);
3158
3159 g_free (type_string_1);
3160 g_free (type_string_2);
3161
3162 return result;
3163}
3164
3165static int
3166compare_by_time (CajaFile *file_1, CajaFile *file_2, CajaDateType type)
3167{
3168 /* Sort order:
3169 * Files with unknown times.
3170 * Files with "unknowable" times.
3171 * Files with older times.
3172 * Files with newer times.
3173 */
3174
3175 Knowledge time_known_1, time_known_2;
3176 time_t time_1, time_2;
3177
3178 time_1 = 0;
3179 time_2 = 0;
3180
3181 time_known_1 = get_time (file_1, &time_1, type);
3182 time_known_2 = get_time (file_2, &time_2, type);
3183
3184 if (time_known_1 > time_known_2) {
3185 return -1;
3186 }
3187 if (time_known_1 < time_known_2) {
3188 return +1;
3189 }
3190
3191 /* Now time_known_1 is equal to time_known_2. Check whether
3192 * we failed to get modification times for files
3193 */
3194 if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3195 return 0;
3196 }
3197
3198 if (time_1 < time_2) {
3199 return -1;
3200 }
3201 if (time_1 > time_2) {
3202 return +1;
3203 }
3204
3205 return 0;
3206}
3207
3208static int
3209compare_by_full_path (CajaFile *file_1, CajaFile *file_2)
3210{
3211 int compare;
3212
3213 compare = compare_by_directory_name (file_1, file_2);
3214 if (compare != 0) {
3215 return compare;
3216 }
3217 return compare_by_display_name (file_1, file_2);
3218}
3219
3220/* prev_extension_segment:
3221 * @basename The basename of a file
3222 * @rem_chars A pointer to the amount of remaining characters
3223 *
3224 * Finds the next segment delimiter to the left. A starting character of '.' is
3225 * set to '\0'.
3226 *
3227 * Return value: The start of the previous segment (right of the dot) or
3228 * basename if there are none remaining.
3229 */
3230static char *
3231prev_extension_segment (char *basename, int *rem_chars)
3232{
3233 if (*basename == '.') {
3234 *basename = 0;
3235 basename--;
3236 (*rem_chars)--;
3237 }
3238
3239 while (*rem_chars > 0 && *basename != '.') {
3240 (*rem_chars)--;
3241 basename--;
3242 }
3243
3244 return basename + 1;
3245}
3246
3247/* is_valid_extension_segment:
3248 * @segment Part of a modifiable zero-terminated string
3249 * @segment_index The index of the current segment
3250 *
3251 * Uses a heuristic to identify valid file extensions.
3252 *
3253 * Return value: Whether the segment is part of the file extension.
3254 */
3255static gboolean
3256is_valid_extension_segment (const char *segment, int segment_index)
3257{
3258 gboolean result;
3259 gboolean has_letters;
3260 int char_offset;
3261 switch (segment_index) {
3262 case 0:
3263 /* extremely long segments are probably not part of the extension */
3264 result = strlen (segment) < 20;
3265 break;
3266 default:
3267 has_letters = FALSE(0);
3268 char_offset = 0;
3269 while (TRUE(!(0))) {
3270 char c;
3271
3272 c = *(segment + char_offset);
3273 if (c == '\0') {
3274 result = has_letters;
3275 break;
3276 }
3277 /* allow digits if there are also letters */
3278 else if (isalpha (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha
)
) {
3279 has_letters = TRUE(!(0));
3280 }
3281 /* fail if it is neither digit nor letter */
3282 else if (!isdigit (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
) {
3283 result = FALSE(0);
3284 break;
3285 }
3286
3287 if (char_offset >= SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3) {
3288 result = FALSE(0);
3289 break;
3290 }
3291 char_offset++;
3292 }
3293 }
3294 return result;
3295}
3296
3297static int
3298compare_by_extension_segments (CajaFile *file_1, CajaFile *file_2)
3299{
3300 char *name_1, *name_2;
3301 char *segment_1, *segment_2;
3302 int compare;
3303 int rem_chars_1, rem_chars_2;
3304 gboolean done_1, done_2;
3305 gboolean is_directory_1, is_directory_2;
3306 int segment_index;
3307
3308
3309 /* Directories do not have an extension */
3310 is_directory_1 = caja_file_is_directory (file_1);
3311 is_directory_2 = caja_file_is_directory (file_2);
3312
3313 if (is_directory_1 && is_directory_2) {
3314 return 0;
3315 } else if (is_directory_1) {
3316 return -1;
3317 } else if (is_directory_2) {
3318 return 1;
3319 }
3320
3321 name_1 = caja_file_get_display_name (file_1);
3322 name_2 = caja_file_get_display_name (file_2);
3323 rem_chars_1 = strlen (name_1);
3324 rem_chars_2 = strlen (name_2);
3325
3326 /* Point to one after the zero character */
3327 segment_1 = name_1 + rem_chars_1 + 1;
3328 segment_2 = name_2 + rem_chars_2 + 1;
3329
3330 segment_index = 0;
3331 do {
3332 segment_1 = prev_extension_segment (segment_1 - 1, &rem_chars_1);
3333 segment_2 = prev_extension_segment (segment_2 - 1, &rem_chars_2);
3334
3335 done_1 = rem_chars_1 <= 0 || !is_valid_extension_segment (segment_1, segment_index);
3336 done_2 = rem_chars_2 <= 0 || !is_valid_extension_segment (segment_2, segment_index);
3337 if (done_1 && !done_2) {
3338 compare = -1;
3339 break;
3340 }
3341 else if (!done_1 && done_2) {
3342 compare = 1;
3343 break;
3344 }
3345 else if (done_1 && done_2) {
3346 compare = 0;
3347 break;
3348 }
3349
3350 segment_index++;
3351 if (segment_index > SORT_BY_EXTENSION_MAX_SEGMENTS3 - 1) {
3352 break;
3353 }
3354 compare = strcmp (segment_1, segment_2);
3355 } while (compare == 0);
3356
3357 g_free (name_1);
3358 g_free (name_2);
3359
3360 return compare;
3361}
3362
3363static gchar *
3364caja_file_get_extension_as_string (CajaFile *file)
3365{
3366 int rem_chars;
3367 char *segment;
3368
3369 if (!caja_file_is_directory (file)) {
43
Taking true branch
3370 char *name;
3371
3372 name = caja_file_get_display_name (file);
3373 rem_chars = strlen (name);
3374 segment = prev_extension_segment (name + rem_chars, &rem_chars);
3375
3376 if (rem_chars > 0 && is_valid_extension_segment (segment, 0)) {
44
Assuming 'rem_chars' is > 0
45
Assuming the condition is true
46
Taking true branch
3377 int segment_index;
3378 char *right_segment;
3379 char *result;
3380
3381 segment_index = 1;
3382 do {
3383 right_segment = segment;
3384 segment = prev_extension_segment (segment - 1, &rem_chars);
3385 if (rem_chars > 0 && is_valid_extension_segment (segment, segment_index)) {
47
Assuming 'rem_chars' is > 0
48
Assuming the condition is true
49
Taking true branch
3386 /* remove zero-termination of segment */
3387 *(right_segment - 1) = '.';
50
Access of 'char' element in the region at index -1
3388 }
3389 else {
3390 break;
3391 }
3392
3393 segment_index++;
3394 } while (segment_index < SORT_BY_EXTENSION_MAX_SEGMENTS3 + 1);
3395 result = g_strdup (right_segment)g_strdup_inline (right_segment);
3396 g_free (name);
3397 return result;
3398 }
3399 g_free (name);
3400 }
3401 return g_strdup ("")g_strdup_inline ("");
3402}
3403
3404static int
3405caja_file_compare_for_sort_internal (CajaFile *file_1,
3406 CajaFile *file_2,
3407 gboolean directories_first,
3408 gboolean reversed)
3409{
3410 gboolean is_directory_1, is_directory_2;
3411
3412 if (directories_first) {
3413 is_directory_1 = caja_file_is_directory (file_1);
3414 is_directory_2 = caja_file_is_directory (file_2);
3415
3416 if (is_directory_1 && !is_directory_2) {
3417 return -1;
3418 }
3419
3420 if (is_directory_2 && !is_directory_1) {
3421 return +1;
3422 }
3423 }
3424
3425 if (file_1->details->sort_order < file_2->details->sort_order) {
3426 return reversed ? 1 : -1;
3427 } else if (file_1->details->sort_order > file_2->details->sort_order) {
3428 return reversed ? -1 : 1;
3429 }
3430
3431 return 0;
3432}
3433
3434/**
3435 * caja_file_compare_for_sort:
3436 * @file_1: A file object
3437 * @file_2: Another file object
3438 * @sort_type: Sort criterion
3439 * @directories_first: Put all directories before any non-directories
3440 * @reversed: Reverse the order of the items, except that
3441 * the directories_first flag is still respected.
3442 *
3443 * Return value: int < 0 if @file_1 should come before file_2 in a
3444 * sorted list; int > 0 if @file_2 should come before file_1 in a
3445 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3446 * that each named sort type may actually break ties several ways, with the name
3447 * of the sort criterion being the primary but not only differentiator.
3448 **/
3449int
3450caja_file_compare_for_sort (CajaFile *file_1,
3451 CajaFile *file_2,
3452 CajaFileSortType sort_type,
3453 gboolean directories_first,
3454 gboolean reversed)
3455{
3456 int result;
3457
3458 if (file_1 == file_2) {
3459 return 0;
3460 }
3461
3462 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3463
3464 if (result == 0) {
3465 switch (sort_type) {
3466 case CAJA_FILE_SORT_BY_DISPLAY_NAME:
3467 result = compare_by_display_name (file_1, file_2);
3468 if (result == 0) {
3469 result = compare_by_directory_name (file_1, file_2);
3470 }
3471 break;
3472 case CAJA_FILE_SORT_BY_DIRECTORY:
3473 result = compare_by_full_path (file_1, file_2);
3474 break;
3475 case CAJA_FILE_SORT_BY_SIZE:
3476 /* Compare directory sizes ourselves, then if necessary
3477 * use MateVFS to compare file sizes.
3478 */
3479 result = compare_by_size (file_1, file_2, FALSE(0));
3480 if (result == 0) {
3481 result = compare_by_full_path (file_1, file_2);
3482 }
3483 break;
3484 case CAJA_FILE_SORT_BY_SIZE_ON_DISK:
3485 /* Compare directory sizes ourselves, then if necessary
3486 * use MateVFS to compare file sizes.
3487 */
3488 result = compare_by_size (file_1, file_2, TRUE(!(0)));
3489 if (result == 0) {
3490 result = compare_by_full_path (file_1, file_2);
3491 }
3492 break;
3493 case CAJA_FILE_SORT_BY_TYPE:
3494 /* MateVFS doesn't know about our special text for certain
3495 * mime types, so we handle the mime-type sorting ourselves.
3496 */
3497 result = compare_by_type (file_1, file_2);
3498 if (result == 0) {
3499 result = compare_by_full_path (file_1, file_2);
3500 }
3501 break;
3502 case CAJA_FILE_SORT_BY_MTIME:
3503 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_MODIFIED);
3504 if (result == 0) {
3505 result = compare_by_full_path (file_1, file_2);
3506 }
3507 break;
3508 case CAJA_FILE_SORT_BY_BTIME:
3509 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_CREATED);
3510 if (result == 0) {
3511 result = compare_by_full_path (file_1, file_2);
3512 }
3513 break;
3514 case CAJA_FILE_SORT_BY_ATIME:
3515 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_ACCESSED);
3516 if (result == 0) {
3517 result = compare_by_full_path (file_1, file_2);
3518 }
3519 break;
3520 case CAJA_FILE_SORT_BY_TRASHED_TIME:
3521 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_TRASHED);
3522 if (result == 0) {
3523 result = compare_by_full_path (file_1, file_2);
3524 }
3525 break;
3526 case CAJA_FILE_SORT_BY_EMBLEMS:
3527 /* MateVFS doesn't know squat about our emblems, so
3528 * we handle comparing them here, before falling back
3529 * to tie-breakers.
3530 */
3531 result = compare_by_emblems (file_1, file_2);
3532 if (result == 0) {
3533 result = compare_by_full_path (file_1, file_2);
3534 }
3535 break;
3536 case CAJA_FILE_SORT_BY_EXTENSION:
3537 result = compare_by_extension_segments (file_1, file_2);
3538 if (result == 0) {
3539 result = compare_by_full_path (file_1, file_2);
3540 }
3541 break;
3542 default:
3543 g_return_val_if_reached (0)do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "caja-file.c", 3543, ((const char*) (__func__))); return (0
); } while (0)
;
3544 }
3545
3546 if (reversed) {
3547 result = -result;
3548 }
3549 }
3550
3551 return result;
3552}
3553
3554int
3555caja_file_compare_for_sort_by_attribute_q (CajaFile *file_1,
3556 CajaFile *file_2,
3557 GQuark attribute,
3558 gboolean directories_first,
3559 gboolean reversed)
3560{
3561 int result;
3562
3563 if (file_1 == file_2) {
3564 return 0;
3565 }
3566
3567 /* Convert certain attributes into CajaFileSortTypes and use
3568 * caja_file_compare_for_sort()
3569 */
3570 if (attribute == 0 || attribute == attribute_name_q) {
3571 return caja_file_compare_for_sort (file_1, file_2,
3572 CAJA_FILE_SORT_BY_DISPLAY_NAME,
3573 directories_first,
3574 reversed);
3575 } else if (attribute == attribute_size_q) {
3576 return caja_file_compare_for_sort (file_1, file_2,
3577 CAJA_FILE_SORT_BY_SIZE,
3578 directories_first,
3579 reversed);
3580 } else if (attribute == attribute_size_on_disk_q) {
3581 return caja_file_compare_for_sort (file_1, file_2,
3582 CAJA_FILE_SORT_BY_SIZE_ON_DISK,
3583 directories_first,
3584 reversed);
3585 } else if (attribute == attribute_type_q) {
3586 return caja_file_compare_for_sort (file_1, file_2,
3587 CAJA_FILE_SORT_BY_TYPE,
3588 directories_first,
3589 reversed);
3590 } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q) {
3591 return caja_file_compare_for_sort (file_1, file_2,
3592 CAJA_FILE_SORT_BY_MTIME,
3593 directories_first,
3594 reversed);
3595 } else if (attribute == attribute_creation_date_q || attribute == attribute_date_created_q) {
3596 return caja_file_compare_for_sort (file_1, file_2,
3597 CAJA_FILE_SORT_BY_BTIME,
3598 directories_first,
3599 reversed);
3600 } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q) {
3601 return caja_file_compare_for_sort (file_1, file_2,
3602 CAJA_FILE_SORT_BY_ATIME,
3603 directories_first,
3604 reversed);
3605 } else if (attribute == attribute_trashed_on_q) {
3606 return caja_file_compare_for_sort (file_1, file_2,
3607 CAJA_FILE_SORT_BY_TRASHED_TIME,
3608 directories_first,
3609 reversed);
3610 } else if (attribute == attribute_emblems_q) {
3611 return caja_file_compare_for_sort (file_1, file_2,
3612 CAJA_FILE_SORT_BY_EMBLEMS,
3613 directories_first,
3614 reversed);
3615 } else if (attribute == attribute_extension_q) {
3616 return caja_file_compare_for_sort (file_1, file_2,
3617 CAJA_FILE_SORT_BY_EXTENSION,
3618 directories_first,
3619 reversed);
3620 }
3621
3622 /* it is a normal attribute, compare by strings */
3623
3624 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3625
3626 if (result == 0) {
3627 char *value_1;
3628 char *value_2;
3629
3630 value_1 = caja_file_get_string_attribute_q (file_1,
3631 attribute);
3632 value_2 = caja_file_get_string_attribute_q (file_2,
3633 attribute);
3634
3635 if (value_1 != NULL((void*)0) && value_2 != NULL((void*)0)) {
3636 result = strcmp (value_1, value_2);
3637 }
3638
3639 g_free (value_1);
3640 g_free (value_2);
3641
3642 if (reversed) {
3643 result = -result;
3644 }
3645 }
3646
3647 return result;
3648}
3649
3650int
3651caja_file_compare_for_sort_by_attribute (CajaFile *file_1,
3652 CajaFile *file_2,
3653 const char *attribute,
3654 gboolean directories_first,
3655 gboolean reversed)
3656{
3657 return caja_file_compare_for_sort_by_attribute_q (file_1, file_2,
3658 g_quark_from_string (attribute),
3659 directories_first,
3660 reversed);
3661}
3662
3663
3664/**
3665 * caja_file_compare_name:
3666 * @file: A file object
3667 * @pattern: A string we are comparing it with
3668 *
3669 * Return value: result of a comparison of the file name and the given pattern,
3670 * using the same sorting order as sort by name.
3671 **/
3672int
3673caja_file_compare_display_name (CajaFile *file,
3674 const char *pattern)
3675{
3676 const char *name;
3677 int result;
3678
3679 g_return_val_if_fail (pattern != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_608
; if (pattern != ((void*)0)) _g_boolean_var_608 = 1; else _g_boolean_var_608
= 0; _g_boolean_var_608; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "pattern != NULL"
); return (-1); } } while (0)
;
3680
3681 name = caja_file_peek_display_name (file);
3682 result = g_utf8_collate (name, pattern);
3683 return result;
3684}
3685
3686
3687gboolean
3688caja_file_is_hidden_file (CajaFile *file)
3689{
3690 return file->details->is_hidden;
3691}
3692
3693static gboolean
3694caja_file_is_backup_file (CajaFile *file)
3695{
3696 return file->details->is_backup;
3697}
3698
3699/**
3700 * caja_file_should_show:
3701 * @file: the file to check.
3702 * @show_hidden: whether we want to show hidden files or not.
3703 * @show_backup: whether we want to show backup files or not.
3704 *
3705 * Determines if a #CajaFile should be shown. Note that when browsing
3706 * a trash directory, this function will always return %TRUE.
3707 *
3708 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3709 */
3710gboolean
3711caja_file_should_show (CajaFile *file,
3712 gboolean show_hidden,
3713 gboolean show_foreign,
3714 gboolean show_backup)
3715{
3716 /* Never hide any files in trash. */
3717 if (caja_file_is_in_trash (file)) {
3718 return TRUE(!(0));
3719 } else {
3720 return (show_hidden || !caja_file_is_hidden_file (file)) &&
3721 (show_backup || !caja_file_is_backup_file (file)) &&
3722 (show_foreign || !(caja_file_is_in_desktop (file) && caja_file_is_foreign_link (file)));
3723 }
3724}
3725
3726gboolean
3727caja_file_is_home (CajaFile *file)
3728{
3729 GFile *dir;
3730
3731 dir = file->details->directory->details->location;
3732 if (dir == NULL((void*)0)) {
3733 return FALSE(0);
3734 }
3735
3736 return caja_is_home_directory_file (dir, file->details->name);
3737}
3738
3739gboolean
3740caja_file_is_in_desktop (CajaFile *file)
3741{
3742 if (file->details->directory->details->location) {
3743 return caja_is_desktop_directory (file->details->directory->details->location);
3744 }
3745 return FALSE(0);
3746
3747}
3748
3749static gboolean
3750filter_hidden_partition_callback (gpointer data,
3751 gpointer callback_data)
3752{
3753 CajaFile *file;
3754 FilterOptions options;
3755
3756 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
3757 options = GPOINTER_TO_INT (callback_data)((gint) (glong) (callback_data));
3758
3759 return caja_file_should_show (file,
3760 options & SHOW_HIDDEN,
3761 TRUE(!(0)),
3762 options & SHOW_BACKUP);
3763}
3764
3765GList *
3766caja_file_list_filter_hidden (GList *files,
3767 gboolean show_hidden)
3768{
3769 GList *filtered_files;
3770 GList *removed_files;
3771
3772 /* FIXME bugzilla.gnome.org 40653:
3773 * Eventually this should become a generic filtering thingy.
3774 */
3775
3776 filtered_files = caja_file_list_copy (files);
3777 filtered_files = eel_g_list_partition (filtered_files,
3778 filter_hidden_partition_callback,
3779 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0))((gpointer) (glong) ((show_hidden ? SHOW_HIDDEN : 0))),
3780 &removed_files);
3781 caja_file_list_free (removed_files);
3782
3783 return filtered_files;
3784}
3785
3786char *
3787caja_file_get_metadata (CajaFile *file,
3788 const char *key,
3789 const char *default_metadata)
3790{
3791 guint id;
3792 char *value;
3793
3794 g_return_val_if_fail (key != NULL, g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_609
; if (key != ((void*)0)) _g_boolean_var_609 = 1; else _g_boolean_var_609
= 0; _g_boolean_var_609; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(g_strdup_inline (default_metadata)); } } while (0)
;
3795 g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_610
; if (key[0] != '\0') _g_boolean_var_610 = 1; else _g_boolean_var_610
= 0; _g_boolean_var_610; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (g_strdup_inline (default_metadata)); } } while (0)
;
3796
3797 if (file == NULL((void*)0) ||
3798 file->details->metadata == NULL((void*)0)) {
3799 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3800 }
3801
3802 g_return_val_if_fail (CAJA_IS_FILE (file), g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_611
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_611
= 1; else _g_boolean_var_611 = 0; _g_boolean_var_611; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (g_strdup_inline
(default_metadata)); } } while (0)
;
3803
3804 id = caja_metadata_get_id (key);
3805 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3806
3807 if (value) {
3808 return g_strdup (value)g_strdup_inline (value);
3809 }
3810 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3811}
3812
3813GList *
3814caja_file_get_metadata_list (CajaFile *file,
3815 const char *key)
3816{
3817 guint id;
3818 char **value;
3819
3820 g_return_val_if_fail (key != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_612
; if (key != ((void*)0)) _g_boolean_var_612 = 1; else _g_boolean_var_612
= 0; _g_boolean_var_612; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(((void*)0)); } } while (0)
;
3821 g_return_val_if_fail (key[0] != '\0', NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_613
; if (key[0] != '\0') _g_boolean_var_613 = 1; else _g_boolean_var_613
= 0; _g_boolean_var_613; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (((void*)0)); } } while (0)
;
3822
3823 if (file == NULL((void*)0) ||
3824 file->details->metadata == NULL((void*)0)) {
3825 return NULL((void*)0);
3826 }
3827
3828 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_614
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_614
= 1; else _g_boolean_var_614 = 0; _g_boolean_var_614; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
3829
3830 id = caja_metadata_get_id (key);
3831 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
3832
3833 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3834
3835 if (value) {
3836 GList *res;
3837 int i;
3838
3839 res = NULL((void*)0);
3840 for (i = 0; value[i] != NULL((void*)0); i++) {
3841 res = g_list_prepend (res, g_strdup (value[i])g_strdup_inline (value[i]));
3842 }
3843 return g_list_reverse (res);
3844 }
3845
3846 return NULL((void*)0);
3847}
3848
3849void
3850caja_file_set_metadata (CajaFile *file,
3851 const char *key,
3852 const char *default_metadata,
3853 const char *metadata)
3854{
3855 const char *val;
3856
3857 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_615
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_615
= 1; else _g_boolean_var_615 = 0; _g_boolean_var_615; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3858 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_616
; if (key != ((void*)0)) _g_boolean_var_616 = 1; else _g_boolean_var_616
= 0; _g_boolean_var_616; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3859 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_617
; if (key[0] != '\0') _g_boolean_var_617 = 1; else _g_boolean_var_617
= 0; _g_boolean_var_617; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3860
3861 val = metadata;
3862 if (val == NULL((void*)0)) {
3863 val = default_metadata;
3864 }
3865
3866 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3867 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3868 set_metadata, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
;
3869}
3870
3871void
3872caja_file_set_metadata_list (CajaFile *file,
3873 const char *key,
3874 GList *list)
3875{
3876 char **val;
3877 int len, i;
3878 GList *l;
3879
3880 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_618
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_618
= 1; else _g_boolean_var_618 = 0; _g_boolean_var_618; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3881 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_619
; if (key != ((void*)0)) _g_boolean_var_619 = 1; else _g_boolean_var_619
= 0; _g_boolean_var_619; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
3882 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_620
; if (key[0] != '\0') _g_boolean_var_620 = 1; else _g_boolean_var_620
= 0; _g_boolean_var_620; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
3883
3884 len = g_list_length (list);
3885 val = g_new (char *, len + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
3886 for (l = list, i = 0; l != NULL((void*)0); l = l->next, i++) {
3887 val[i] = l->data;
3888 }
3889 val[i] = NULL((void*)0);
3890
3891 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3892 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3893 set_metadata_as_list, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
;
3894
3895 g_free (val);
3896}
3897
3898
3899gboolean
3900caja_file_get_boolean_metadata (CajaFile *file,
3901 const char *key,
3902 gboolean default_metadata)
3903{
3904 char *result_as_string;
3905 gboolean result;
3906
3907 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_621
; if (key != ((void*)0)) _g_boolean_var_621 = 1; else _g_boolean_var_621
= 0; _g_boolean_var_621; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3908 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_622
; if (key[0] != '\0') _g_boolean_var_622 = 1; else _g_boolean_var_622
= 0; _g_boolean_var_622; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3909
3910 if (file == NULL((void*)0)) {
3911 return default_metadata;
3912 }
3913
3914 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_623
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_623
= 1; else _g_boolean_var_623 = 0; _g_boolean_var_623; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3915
3916 result_as_string = caja_file_get_metadata
3917 (file, key, default_metadata ? "true" : "false");
3918 g_assert (result_as_string != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_624
; if (result_as_string != ((void*)0)) _g_boolean_var_624 = 1;
else _g_boolean_var_624 = 0; _g_boolean_var_624; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file.c", 3918,
((const char*) (__func__)), "result_as_string != NULL"); } while
(0)
;
3919
3920 if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3921 result = TRUE(!(0));
3922 } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3923 result = FALSE(0);
3924 } else {
3925 g_error ("boolean metadata with value other than true or false");
3926 result = default_metadata;
3927 }
3928
3929 g_free (result_as_string);
3930 return result;
3931}
3932
3933int
3934caja_file_get_integer_metadata (CajaFile *file,
3935 const char *key,
3936 int default_metadata)
3937{
3938 char *result_as_string;
3939 char default_as_string[32];
3940 int result;
3941 char c;
3942
3943 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_625
; if (key != ((void*)0)) _g_boolean_var_625 = 1; else _g_boolean_var_625
= 0; _g_boolean_var_625; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3944 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_626
; if (key[0] != '\0') _g_boolean_var_626 = 1; else _g_boolean_var_626
= 0; _g_boolean_var_626; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3945
3946 if (file == NULL((void*)0)) {
3947 return default_metadata;
3948 }
3949 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_627
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_627
= 1; else _g_boolean_var_627 = 0; _g_boolean_var_627; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3950
3951 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3952 result_as_string = caja_file_get_metadata
3953 (file, key, default_as_string);
3954
3955 /* Normally we can't get a a NULL, but we check for it here to
3956 * handle the oddball case of a non-existent directory.
3957 */
3958 if (result_as_string == NULL((void*)0)) {
3959 result = default_metadata;
3960 } else {
3961 if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3962 result = default_metadata;
3963 }
3964 g_free (result_as_string);
3965 }
3966
3967 return result;
3968}
3969
3970static gboolean
3971get_time_from_time_string (const char *time_string,
3972 time_t *time)
3973{
3974 long scanned_time;
3975 char c;
3976
3977 g_assert (time != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_628
; if (time != ((void*)0)) _g_boolean_var_628 = 1; else _g_boolean_var_628
= 0; _g_boolean_var_628; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3977, ((const char*) (__func__
)), "time != NULL"); } while (0)
;
3978
3979 /* Only accept string if it has one integer with nothing
3980 * afterwards.
3981 */
3982 if (time_string == NULL((void*)0) ||
3983 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3984 return FALSE(0);
3985 }
3986 *time = (time_t) scanned_time;
3987 return TRUE(!(0));
3988}
3989
3990time_t
3991caja_file_get_time_metadata (CajaFile *file,
3992 const char *key)
3993{
3994 time_t time;
3995 char *time_string;
3996
3997 time_string = caja_file_get_metadata (file, key, NULL((void*)0));
3998 if (!get_time_from_time_string (time_string, &time)) {
3999 time = UNDEFINED_TIME((time_t) (-1));
4000 }
4001 g_free (time_string);
4002
4003 return time;
4004}
4005
4006void
4007caja_file_set_time_metadata (CajaFile *file,
4008 const char *key,
4009 time_t time)
4010{
4011 char time_str[21];
4012 char *metadata;
4013
4014 if (time != UNDEFINED_TIME((time_t) (-1))) {
4015 /* 2^64 turns out to be 20 characters */
4016 g_snprintf (time_str, 20, "%ld", (long int)time);
4017 time_str[20] = '\0';
4018 metadata = time_str;
4019 } else {
4020 metadata = NULL((void*)0);
4021 }
4022
4023 caja_file_set_metadata (file, key, NULL((void*)0), metadata);
4024}
4025
4026
4027void
4028caja_file_set_boolean_metadata (CajaFile *file,
4029 const char *key,
4030 gboolean default_metadata,
4031 gboolean metadata)
4032{
4033 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_629
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_629
= 1; else _g_boolean_var_629 = 0; _g_boolean_var_629; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4034 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_630
; if (key != ((void*)0)) _g_boolean_var_630 = 1; else _g_boolean_var_630
= 0; _g_boolean_var_630; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4035 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_631
; if (key[0] != '\0') _g_boolean_var_631 = 1; else _g_boolean_var_631
= 0; _g_boolean_var_631; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4036
4037 caja_file_set_metadata (file, key,
4038 default_metadata ? "true" : "false",
4039 metadata ? "true" : "false");
4040}
4041
4042void
4043caja_file_set_integer_metadata (CajaFile *file,
4044 const char *key,
4045 int default_metadata,
4046 int metadata)
4047{
4048 char value_as_string[32];
4049 char default_as_string[32];
4050
4051 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_632
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_632
= 1; else _g_boolean_var_632 = 0; _g_boolean_var_632; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4052 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_633
; if (key != ((void*)0)) _g_boolean_var_633 = 1; else _g_boolean_var_633
= 0; _g_boolean_var_633; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4053 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_634
; if (key[0] != '\0') _g_boolean_var_634 = 1; else _g_boolean_var_634
= 0; _g_boolean_var_634; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4054
4055 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4056 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4057
4058 caja_file_set_metadata (file, key,
4059 default_as_string, value_as_string);
4060}
4061
4062static const char *
4063caja_file_peek_display_name_collation_key (CajaFile *file)
4064{
4065 const char *res;
4066
4067 res = file->details->display_name_collation_key;
4068 if (res == NULL((void*)0))
4069 res = "";
4070
4071 return res;
4072}
4073
4074static const char *
4075caja_file_peek_display_name (CajaFile *file)
4076{
4077 /*
4078 stefano-k: Imported 15_nautilus_file_peek_crash.patch from debian nautilus
4079 Date: Thu, 27 Jan 2011 10:22:10 +0000
4080 Subject: Prevent a crash in nautilus_file_peek_display_name() on invalid NautilusFile
4081 This is more a workaround only, expect assert failures at other
4082 places when something bad happens. There's a race condition somewhere,
4083 this patch only prevents immediate crash.
4084 Patch by Marcus Husar <marcus.husar@rose.uni-heidelberg.de>
4085 https://bugzilla.gnome.org/show_bug.cgi?id=602500
4086 */
4087 if (file == NULL((void*)0) || caja_file_is_gone (file))
4088 return "";
4089
4090 /* Default to display name based on filename if its not set yet */
4091
4092 if (file->details->display_name == NULL((void*)0)) {
4093 const char *name;
4094
4095 name = file->details->name;
4096 if (g_utf8_validate (name, -1, NULL((void*)0))) {
4097 caja_file_set_display_name (file,
4098 name,
4099 NULL((void*)0),
4100 FALSE(0));
4101 } else {
4102 char *escaped_name;
4103
4104 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
4105 caja_file_set_display_name (file,
4106 escaped_name,
4107 NULL((void*)0),
4108 FALSE(0));
4109 g_free (escaped_name);
4110 }
4111 }
4112
4113 return file->details->display_name;
4114}
4115
4116char *
4117caja_file_get_display_name (CajaFile *file)
4118{
4119 return g_strdup (caja_file_peek_display_name (file))g_strdup_inline (caja_file_peek_display_name (file));
4120}
4121
4122char *
4123caja_file_get_edit_name (CajaFile *file)
4124{
4125 const char *res;
4126
4127 res = file->details->edit_name;
4128 if (res == NULL((void*)0))
4129 res = "";
4130
4131 return g_strdup (res)g_strdup_inline (res);
4132}
4133
4134char *
4135caja_file_get_name (CajaFile *file)
4136{
4137 return g_strdup (file->details->name)g_strdup_inline (file->details->name);
4138}
4139
4140/**
4141 * caja_file_get_description:
4142 * @file: a #CajaFile.
4143 *
4144 * Gets the standard::description key from @file, if
4145 * it has been cached.
4146 *
4147 * Returns: a string containing the value of the standard::description
4148 * key, or %NULL.
4149 */
4150char *
4151caja_file_get_description (CajaFile *file)
4152{
4153 return g_strdup (file->details->description)g_strdup_inline (file->details->description);
4154}
4155
4156void
4157caja_file_monitor_add (CajaFile *file,
4158 gconstpointer client,
4159 CajaFileAttributes attributes)
4160{
4161 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_635
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_635
= 1; else _g_boolean_var_635 = 0; _g_boolean_var_635; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4162 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_636
; if (client != ((void*)0)) _g_boolean_var_636 = 1; else _g_boolean_var_636
= 0; _g_boolean_var_636; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4163
4164 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4165 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4166 monitor_add, (file, client, attributes))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
;
4167}
4168
4169void
4170caja_file_monitor_remove (CajaFile *file,
4171 gconstpointer client)
4172{
4173 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_637
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_637
= 1; else _g_boolean_var_637 = 0; _g_boolean_var_637; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4174 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_638
; if (client != ((void*)0)) _g_boolean_var_638 = 1; else _g_boolean_var_638
= 0; _g_boolean_var_638; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4175
4176 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4177 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4178 monitor_remove, (file, client))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
;
4179}
4180
4181gboolean
4182caja_file_is_launcher (CajaFile *file)
4183{
4184 return file->details->is_launcher;
4185}
4186
4187gboolean
4188caja_file_is_foreign_link (CajaFile *file)
4189{
4190 return file->details->is_foreign_link;
4191}
4192
4193gboolean
4194caja_file_is_trusted_link (CajaFile *file)
4195{
4196 return file->details->is_trusted_link;
4197}
4198
4199gboolean
4200caja_file_has_activation_uri (CajaFile *file)
4201{
4202 return file->details->activation_uri != NULL((void*)0);
4203}
4204
4205
4206/* Return the uri associated with the passed-in file, which may not be
4207 * the actual uri if the file is an desktop file or a caja
4208 * xml link file.
4209 */
4210char *
4211caja_file_get_activation_uri (CajaFile *file)
4212{
4213 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_639
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_639
= 1; else _g_boolean_var_639 = 0; _g_boolean_var_639; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4214
4215 if (file->details->activation_uri != NULL((void*)0)) {
4216 return g_strdup (file->details->activation_uri)g_strdup_inline (file->details->activation_uri);
4217 }
4218
4219 return caja_file_get_uri (file);
4220}
4221
4222GFile *
4223caja_file_get_activation_location (CajaFile *file)
4224{
4225 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_640
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_640
= 1; else _g_boolean_var_640 = 0; _g_boolean_var_640; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4226
4227 if (file->details->activation_uri != NULL((void*)0)) {
4228 return g_file_new_for_uri (file->details->activation_uri);
4229 }
4230
4231 return caja_file_get_location (file);
4232}
4233
4234
4235char *
4236caja_file_get_drop_target_uri (CajaFile *file)
4237{
4238 char *uri, *target_uri;
4239 GFile *location;
4240
4241 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_641
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_641
= 1; else _g_boolean_var_641 = 0; _g_boolean_var_641; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4242
4243 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
4244 CajaDesktopLink *link;
4245
4246 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
4247
4248 if (link != NULL((void*)0)) {
4249 location = caja_desktop_link_get_activation_location (link);
4250 g_object_unref (link);
4251 if (location != NULL((void*)0)) {
4252 uri = g_file_get_uri (location);
4253 g_object_unref (location);
4254 return uri;
4255 }
4256 }
4257 }
4258
4259 uri = caja_file_get_uri (file);
4260
4261 /* Check for Caja link */
4262 if (caja_file_is_caja_link (file)) {
4263 location = caja_file_get_location (file);
4264 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
4265 if (g_file_is_native (location)) {
4266 target_uri = caja_link_local_get_link_uri (uri);
4267 if (target_uri != NULL((void*)0)) {
4268 g_free (uri);
4269 uri = target_uri;
4270 }
4271 }
4272 g_object_unref (location);
4273 }
4274
4275 return uri;
4276}
4277
4278static gboolean
4279is_uri_relative (const char *uri)
4280{
4281 char *scheme;
4282 gboolean ret;
4283
4284 scheme = g_uri_parse_scheme (uri);
4285 ret = (scheme == NULL((void*)0));
4286 g_free (scheme);
4287 return ret;
4288}
4289
4290static char *
4291get_custom_icon_metadata_uri (CajaFile *file)
4292{
4293 char *custom_icon_uri;
4294 char *uri;
4295
4296 uri = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
4297 if (uri != NULL((void*)0) &&
4298 caja_file_is_directory (file) &&
4299 is_uri_relative (uri)) {
4300 char *dir_uri;
4301
4302 dir_uri = caja_file_get_uri (file);
4303 custom_icon_uri = g_build_filename (dir_uri, uri, NULL((void*)0));
4304 g_free (dir_uri);
4305 g_free (uri);
4306 } else {
4307 custom_icon_uri = uri;
4308 }
4309 return custom_icon_uri;
4310}
4311
4312static GIcon *
4313get_custom_icon (CajaFile *file)
4314{
4315 char *custom_icon_uri;
4316 GFile *icon_file;
4317 GIcon *icon;
4318
4319 if (file == NULL((void*)0)) {
4320 return NULL((void*)0);
4321 }
4322
4323 icon = NULL((void*)0);
4324
4325 /* Metadata takes precedence */
4326 custom_icon_uri = get_custom_icon_metadata_uri (file);
4327
4328 if (custom_icon_uri) {
4329 icon_file = g_file_new_for_uri (custom_icon_uri);
4330 icon = g_file_icon_new (icon_file);
4331 g_object_unref (icon_file);
4332 g_free (custom_icon_uri);
4333 }
4334
4335 if (icon == NULL((void*)0) && file->details->got_link_info && file->details->custom_icon != NULL((void*)0)) {
4336 if (g_path_is_absolute (file->details->custom_icon)) {
4337 icon_file = g_file_new_for_path (file->details->custom_icon);
4338 icon = g_file_icon_new (icon_file);
4339 g_object_unref (icon_file);
4340 } else {
4341 icon = g_themed_icon_new (file->details->custom_icon);
4342 }
4343 }
4344
4345 return icon;
4346}
4347
4348
4349static guint64 cached_thumbnail_limit;
4350int cached_thumbnail_size;
4351static int show_image_thumbs;
4352
4353GFilesystemPreviewType
4354caja_file_get_filesystem_use_preview (CajaFile *file)
4355{
4356 GFilesystemPreviewType use_preview;
4357 CajaFile *parent;
4358
4359 parent = caja_file_get_parent (file);
4360 if (parent != NULL((void*)0)) {
4361 use_preview = parent->details->filesystem_use_preview;
4362 g_object_unref (parent);
4363 } else {
4364 use_preview = 0;
4365 }
4366
4367 return use_preview;
4368}
4369
4370gboolean
4371caja_file_should_show_thumbnail (CajaFile *file)
4372{
4373 const char *mime_type;
4374 GFilesystemPreviewType use_preview;
4375
4376 use_preview = caja_file_get_filesystem_use_preview (file);
4377
4378 mime_type = file->details->mime_type;
4379 if (mime_type == NULL((void*)0)) {
4380 mime_type = "application/octet-stream";
4381 }
4382
4383 /* If the thumbnail has already been created, don't care about the size
4384 * of the original file.
4385 */
4386 if (caja_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4387 file->details->thumbnail_path == NULL((void*)0) &&
4388 caja_file_get_size (file) > cached_thumbnail_limit) {
4389 return FALSE(0);
4390 }
4391
4392 if (show_image_thumbs == CAJA_SPEED_TRADEOFF_ALWAYS) {
4393 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4394 return FALSE(0);
4395 } else {
4396 return TRUE(!(0));
4397 }
4398 } else if (show_image_thumbs == CAJA_SPEED_TRADEOFF_NEVER) {
4399 return FALSE(0);
4400 } else {
4401 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4402 /* file system says to never thumbnail anything */
4403 return FALSE(0);
4404 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4405 /* file system says we should treat file as if it's local */
4406 return TRUE(!(0));
4407 } else {
4408 /* only local files */
4409 return caja_file_is_local (file);
4410 }
4411 }
4412
4413 return FALSE(0);
4414}
4415
4416static void
4417prepend_icon_name (const char *name,
4418 GThemedIcon *icon)
4419{
4420 g_themed_icon_prepend_name(icon, name);
4421}
4422
4423GIcon *
4424caja_file_get_gicon (CajaFile *file,
4425 CajaFileIconFlags flags)
4426{
4427 const char * const * names;
4428 GIcon *icon, *mount_icon = NULL((void*)0), *emblemed_icon;
4429 gboolean is_folder = FALSE(0), is_preview = FALSE(0), is_inode_directory = FALSE(0);
4430
4431 if (file == NULL((void*)0)) {
4432 return NULL((void*)0);
4433 }
4434
4435 icon = get_custom_icon (file);
4436 if (icon != NULL((void*)0)) {
4437 return icon;
4438 }
4439
4440 if (file->details->icon) {
4441 icon = NULL((void*)0);
4442
4443 /* fetch the mount icon here, we'll use it later */
4444 if (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4445 flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4446 GMount *mount;
4447
4448 mount = caja_file_get_mount (file);
4449
4450 if (mount != NULL((void*)0)) {
4451 mount_icon = g_mount_get_icon (mount);
4452 g_object_unref (mount);
4453 }
4454 }
4455
4456 if (((flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4457 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4458 (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4459 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4460 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4461 ((flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4462 caja_file_has_open_window (file))) &&
4463 G_IS_THEMED_ICON (file->details->icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file->details->icon)); GType __t = ((g_themed_icon_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; }))))
) {
4464 GPtrArray *prepend_array;
4465 int i;
4466
4467 names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon)((((GThemedIcon*) (void *) ((file->details->icon))))));
4468 prepend_array = g_ptr_array_new ();
4469
4470 for (i = 0; names[i] != NULL((void*)0); i++) {
4471 const char *name;
4472
4473 name = names[i];
4474
4475 if (strcmp (name, "folder") == 0) {
4476 is_folder = TRUE(!(0));
4477 }
4478 if (strcmp (name, "inode-directory") == 0) {
4479 is_inode_directory = TRUE(!(0));
4480 }
4481 if (strcmp (name, "text-x-generic") == 0 &&
4482 (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4483 is_preview = TRUE(!(0));
4484 }
4485 }
4486
4487 /* Here, we add icons in reverse order of precedence,
4488 * because they are later prepended */
4489 if (is_preview) {
4490 g_ptr_array_add (prepend_array, "text-x-preview");
4491 }
4492
4493 /* "folder" should override "inode-directory", not the other way around */
4494 if (is_inode_directory) {
4495 g_ptr_array_add (prepend_array, "folder");
4496 }
4497 if (is_folder && (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4498 g_ptr_array_add (prepend_array, "folder-open");
4499 }
4500 if (is_folder &&
4501 (flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4502 caja_file_has_open_window (file)) {
4503 g_ptr_array_add (prepend_array, "folder-visiting");
4504 }
4505 if (is_folder &&
4506 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4507 g_ptr_array_add (prepend_array, "folder-drag-accept");
4508 }
4509
4510 if (prepend_array->len) {
4511 /* When constructing GThemed Icon, pointers from the array
4512 * are reused, but not the array itself, so the cast is safe */
4513 icon = g_themed_icon_new_from_names ((char**) names, -1);
4514 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4515 }
4516
4517 g_ptr_array_free (prepend_array, TRUE(!(0)));
4518 }
4519
4520 if (icon == NULL((void*)0)) {
4521 icon = g_object_ref (file->details->icon)((__typeof__ (file->details->icon)) (g_object_ref) (file
->details->icon))
;
4522 }
4523
4524 if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4525 mount_icon != NULL((void*)0)) {
4526 g_object_unref (icon);
4527 icon = mount_icon;
4528 } else if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4529 mount_icon != NULL((void*)0) && !g_icon_equal (mount_icon, icon)) {
4530 GEmblem *emblem;
4531
4532 emblem = g_emblem_new (mount_icon);
4533 emblemed_icon = g_emblemed_icon_new (icon, emblem);
4534
4535 g_object_unref (emblem);
4536 g_object_unref (icon);
4537 g_object_unref (mount_icon);
4538
4539 icon = emblemed_icon;
4540 } else if (mount_icon != NULL((void*)0)) {
4541 g_object_unref (mount_icon);
4542 }
4543
4544 return icon;
4545 }
4546
4547 return g_themed_icon_new ("text-x-generic");
4548}
4549
4550static GIcon *
4551get_default_file_icon (CajaFileIconFlags flags)
4552{
4553 static GIcon *fallback_icon = NULL((void*)0);
4554 static GIcon *fallback_icon_preview = NULL((void*)0);
4555 if (fallback_icon == NULL((void*)0)) {
4556 fallback_icon = g_themed_icon_new ("text-x-generic");
4557 fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4558 g_themed_icon_append_name (G_THEMED_ICON (fallback_icon_preview)((((GThemedIcon*) (void *) ((fallback_icon_preview))))), "text-x-generic");
4559 }
4560 if (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4561 return fallback_icon_preview;
4562 } else {
4563 return fallback_icon;
4564 }
4565}
4566
4567CajaIconInfo *
4568caja_file_get_icon (CajaFile *file,
4569 int size,
4570 int scale,
4571 CajaFileIconFlags flags)
4572{
4573 CajaIconInfo *icon;
4574 GIcon *gicon;
4575 GdkPixbuf *scaled_pixbuf;
4576
4577 if (file == NULL((void*)0)) {
4578 return NULL((void*)0);
4579 }
4580
4581 gicon = get_custom_icon (file);
4582 if (gicon) {
4583 GdkPixbuf *pixbuf;
4584
4585 icon = caja_icon_info_lookup (gicon, size, scale);
4586 g_object_unref (gicon);
4587
4588 pixbuf = caja_icon_info_get_pixbuf (icon);
4589 if (pixbuf != NULL((void*)0)) {
4590 if (!file->details->is_launcher && !gdk_pixbuf_get_has_alpha (pixbuf)) {
4591 caja_ui_frame_image (&pixbuf);
4592 }
4593 g_object_unref (icon);
4594
4595 icon = caja_icon_info_new_for_pixbuf (pixbuf, scale);
4596 g_object_unref (pixbuf);
4597 }
4598
4599 return icon;
4600 }
4601
4602 if (flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4603 caja_file_should_show_thumbnail (file)) {
4604 int modified_size;
4605
4606 if (flags & CAJA_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4607 modified_size = size * scale;
4608 } else {
4609 modified_size = size * scale * cached_thumbnail_size / CAJA_ICON_SIZE_STANDARD48;
4610 }
4611
4612 if (file->details->thumbnail) {
4613 int w, h, s;
4614 double thumb_scale;
4615 GdkPixbuf *raw_pixbuf;
4616
4617 raw_pixbuf = g_object_ref (file->details->thumbnail)((__typeof__ (file->details->thumbnail)) (g_object_ref)
(file->details->thumbnail))
;
4618
4619 w = gdk_pixbuf_get_width (raw_pixbuf);
4620 h = gdk_pixbuf_get_height (raw_pixbuf);
4621
4622 s = MAX (w, h)(((w) > (h)) ? (w) : (h));
4623 /* Don't scale up small thumbnails in the standard view */
4624 if (s <= cached_thumbnail_size) {
4625 thumb_scale = (double)size / CAJA_ICON_SIZE_STANDARD48;
4626 }
4627 else {
4628 thumb_scale = (double)modified_size / s;
4629 }
4630 /* Make sure that icons don't get smaller than CAJA_ICON_SIZE_SMALLEST */
4631 if (s*thumb_scale <= CAJA_ICON_SIZE_SMALLEST16) {
4632 thumb_scale = (double) CAJA_ICON_SIZE_SMALLEST16 / s;
4633 }
4634
4635 scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4636 MAX (w * thumb_scale, 1)(((w * thumb_scale) > (1)) ? (w * thumb_scale) : (1)),
4637 MAX (h * thumb_scale, 1)(((h * thumb_scale) > (1)) ? (h * thumb_scale) : (1)),
4638 GDK_INTERP_BILINEAR);
4639
4640 /* Render frames only for thumbnails of non-image files
4641 and for images with no alpha channel. */
4642 gboolean is_image = file->details->mime_type &&
4643 (strncmp (file->details->mime_type, "image/", 6) == 0);
4644 if (!is_image || !gdk_pixbuf_get_has_alpha (raw_pixbuf)) {
4645 caja_ui_frame_image (&scaled_pixbuf);
4646 }
4647
4648 g_object_unref (raw_pixbuf);
4649
4650 /* Don't scale up if more than 25%, then read the original
4651 image instead. We don't want to compare to exactly 100%,
4652 since the zoom level 150% gives thumbnails at 144, which is
4653 ok to scale up from 128. */
4654 if (modified_size > 128 * 1.25 * scale &&
4655 !file->details->thumbnail_wants_original &&
4656 caja_can_thumbnail_internally (file)) {
4657 /* Invalidate if we resize upward */
4658 file->details->thumbnail_wants_original = TRUE(!(0));
4659 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_THUMBNAIL);
4660 }
4661
4662 icon = caja_icon_info_new_for_pixbuf (scaled_pixbuf, scale);
4663 g_object_unref (scaled_pixbuf);
4664 return icon;
4665 } else if (file->details->thumbnail_path == NULL((void*)0) &&
4666 file->details->can_read &&
4667 !file->details->is_thumbnailing &&
4668 !file->details->thumbnailing_failed) {
4669 if (caja_can_thumbnail (file)) {
4670 caja_create_thumbnail (file);
4671 }
4672 }
4673 }
4674
4675 if (file->details->is_thumbnailing &&
4676 flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS)
4677 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING"image-loading");
4678 else
4679 gicon = caja_file_get_gicon (file, flags);
4680
4681 if (gicon) {
4682 icon = caja_icon_info_lookup (gicon, size, scale);
4683 g_object_unref (gicon);
4684 return icon;
4685 } else {
4686 return caja_icon_info_lookup (get_default_file_icon (flags), size, scale);
4687 }
4688}
4689
4690cairo_surface_t *
4691caja_file_get_icon_surface (CajaFile *file,
4692 int size,
4693 gboolean force_size,
4694 int scale,
4695 CajaFileIconFlags flags)
4696{
4697 CajaIconInfo *info;
4698 cairo_surface_t *surface;
4699
4700 info = caja_file_get_icon (file, size, scale, flags);
4701 if (force_size) {
4702 surface = caja_icon_info_get_surface_at_size (info, size);
4703 } else {
4704 surface = caja_icon_info_get_surface (info);
4705 }
4706 g_object_unref (info);
4707
4708 return surface;
4709}
4710
4711char *
4712caja_file_get_custom_icon (CajaFile *file)
4713{
4714 char *custom_icon;
4715
4716 if (file == NULL((void*)0)) {
4717 return NULL((void*)0);
4718 }
4719
4720 /* Metadata takes precedence */
4721 custom_icon = get_custom_icon_metadata_uri (file);
4722
4723 if (custom_icon == NULL((void*)0) && file->details->got_link_info) {
4724 custom_icon = g_strdup (file->details->custom_icon)g_strdup_inline (file->details->custom_icon);
4725 }
4726
4727 return custom_icon;
4728}
4729
4730
4731gboolean
4732caja_file_get_date (CajaFile *file,
4733 CajaDateType date_type,
4734 time_t *date)
4735{
4736 if (date != NULL((void*)0)) {
4737 *date = 0;
4738 }
4739
4740 g_return_val_if_fail (date_type == CAJA_DATE_TYPE_CHANGEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_642
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_642 = 1; else _g_boolean_var_642 = 0; _g_boolean_var_642
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4741 || date_type == CAJA_DATE_TYPE_ACCESSEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_642
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_642 = 1; else _g_boolean_var_642 = 0; _g_boolean_var_642
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4742 || date_type == CAJA_DATE_TYPE_MODIFIEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_642
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_642 = 1; else _g_boolean_var_642 = 0; _g_boolean_var_642
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4743 || date_type == CAJA_DATE_TYPE_CREATEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_642
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_642 = 1; else _g_boolean_var_642 = 0; _g_boolean_var_642
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4744 || date_type == CAJA_DATE_TYPE_TRASHEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_642
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_642 = 1; else _g_boolean_var_642 = 0; _g_boolean_var_642
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4745 || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_642
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_642 = 1; else _g_boolean_var_642 = 0; _g_boolean_var_642
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
;
4746
4747 if (file == NULL((void*)0)) {
4748 return FALSE(0);
4749 }
4750
4751 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_643
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_643
= 1; else _g_boolean_var_643 = 0; _g_boolean_var_643; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
4752
4753 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4754 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4755 get_date, (file, date_type, date))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
;
4756}
4757
4758static char *
4759caja_file_get_where_string (CajaFile *file)
4760{
4761 if (file == NULL((void*)0)) {
4762 return NULL((void*)0);
4763 }
4764
4765 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_644
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_644
= 1; else _g_boolean_var_644 = 0; _g_boolean_var_644; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4766
4767 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4768 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4769 get_where_string, (file))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
;
4770}
4771
4772static const char *TODAY_TIME_FORMATS [] = {
4773 /* Today, use special word.
4774 * strftime patterns preceeded with the widest
4775 * possible resulting string for that pattern.
4776 *
4777 * Note to localizers: You can look at man strftime
4778 * for details on the format, but you should only use
4779 * the specifiers from the C standard, not extensions.
4780 * These include "%" followed by one of
4781 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
4782 * in the Caja version of strftime that can be
4783 * used (and match GNU extensions). Putting a "-"
4784 * between the "%" and any numeric directive will turn
4785 * off zero padding, and putting a "_" there will use
4786 * space padding instead of zero padding.
4787 */
4788 N_("today at 00:00:00 PM")("today at 00:00:00 PM"),
4789 N_("today at %-I:%M:%S %p")("today at %-I:%M:%S %p"),
4790
4791 N_("today at 00:00 PM")("today at 00:00 PM"),
4792 N_("today at %-I:%M %p")("today at %-I:%M %p"),
4793
4794 N_("today, 00:00 PM")("today, 00:00 PM"),
4795 N_("today, %-I:%M %p")("today, %-I:%M %p"),
4796
4797 N_("today")("today"),
4798 N_("today")("today"),
4799
4800 NULL((void*)0)
4801};
4802
4803static const char *YESTERDAY_TIME_FORMATS [] = {
4804 /* Yesterday, use special word.
4805 * Note to localizers: Same issues as "today" string.
4806 */
4807 N_("yesterday at 00:00:00 PM")("yesterday at 00:00:00 PM"),
4808 N_("yesterday at %-I:%M:%S %p")("yesterday at %-I:%M:%S %p"),
4809
4810 N_("yesterday at 00:00 PM")("yesterday at 00:00 PM"),
4811 N_("yesterday at %-I:%M %p")("yesterday at %-I:%M %p"),
4812
4813 N_("yesterday, 00:00 PM")("yesterday, 00:00 PM"),
4814 N_("yesterday, %-I:%M %p")("yesterday, %-I:%M %p"),
4815
4816 N_("yesterday")("yesterday"),
4817 N_("yesterday")("yesterday"),
4818
4819 NULL((void*)0)
4820};
4821
4822static const char *CURRENT_WEEK_TIME_FORMATS [] = {
4823 /* Current week, include day of week.
4824 * Note to localizers: Same issues as "today" string.
4825 * The width measurement templates correspond to
4826 * the day/month name with the most letters.
4827 */
4828 N_("Wednesday, September 00 0000 at 00:00:00 PM")("Wednesday, September 00 0000 at 00:00:00 PM"),
4829 N_("%A, %B %-d %Y at %-I:%M:%S %p")("%A, %B %-d %Y at %-I:%M:%S %p"),
4830
4831 N_("Mon, Oct 00 0000 at 00:00:00 PM")("Mon, Oct 00 0000 at 00:00:00 PM"),
4832 N_("%a, %b %-d %Y at %-I:%M:%S %p")("%a, %b %-d %Y at %-I:%M:%S %p"),
4833
4834 N_("Mon, Oct 00 0000 at 00:00 PM")("Mon, Oct 00 0000 at 00:00 PM"),
4835 N_("%a, %b %-d %Y at %-I:%M %p")("%a, %b %-d %Y at %-I:%M %p"),
4836
4837 N_("Oct 00 0000 at 00:00 PM")("Oct 00 0000 at 00:00 PM"),
4838 N_("%b %-d %Y at %-I:%M %p")("%b %-d %Y at %-I:%M %p"),
4839
4840 N_("Oct 00 0000, 00:00 PM")("Oct 00 0000, 00:00 PM"),
4841 N_("%b %-d %Y, %-I:%M %p")("%b %-d %Y, %-I:%M %p"),
4842
4843 N_("00/00/00, 00:00 PM")("00/00/00, 00:00 PM"),
4844 N_("%m/%-d/%y, %-I:%M %p")("%m/%-d/%y, %-I:%M %p"),
4845
4846 N_("00/00/00")("00/00/00"),
4847 N_("%m/%d/%y")("%m/%d/%y"),
4848
4849 NULL((void*)0)
4850};
4851
4852static char *
4853caja_file_fit_date_as_string (CajaFile *file,
4854 CajaDateType date_type,
4855 int width,
4856 CajaWidthMeasureCallback measure_callback,
4857 CajaTruncateCallback truncate_callback,
4858 void *measure_context)
4859{
4860 time_t file_time_raw;
4861 const char **formats;
4862 const char *format;
4863 char *date_string;
4864 gchar *result = NULL((void*)0);
4865 int i;
4866 GDateTime *date_time, *today, *end_of_today;
4867 GTimeSpan file_date_age;
4868
4869 if (!caja_file_get_date (file, date_type, &file_time_raw)) {
4870 return NULL((void*)0);
4871 }
4872
4873 date_time = g_date_time_new_from_unix_local (file_time_raw);
4874
4875 if (date_format_pref == CAJA_DATE_FORMAT_LOCALE) {
4876 result = g_date_time_format (date_time, "%c");
4877 goto out;
4878 } else if (date_format_pref == CAJA_DATE_FORMAT_ISO) {
4879 result = g_date_time_format (date_time, "%Y-%m-%d %H:%M:%S");
4880 goto out;
4881 }
4882
4883 today = g_date_time_new_now_local ();
4884 end_of_today = g_date_time_add_full (today, 0, 0, 1,
4885 -1 * g_date_time_get_hour (today),
4886 -1 * g_date_time_get_minute (today),
4887 -1.0 * g_date_time_get_seconds (today));
4888 g_date_time_unref (today);
4889
4890 file_date_age = g_date_time_difference (end_of_today, date_time);
4891 g_date_time_unref (end_of_today);
4892
4893 /* Format varies depending on how old the date is. This minimizes
4894 * the length (and thus clutter & complication) of typical dates
4895 * while providing sufficient detail for recent dates to make
4896 * them maximally understandable at a glance. Keep all format
4897 * strings separate rather than combining bits & pieces for
4898 * internationalization's sake.
4899 */
4900
4901 if (file_date_age <= 0 || file_date_age > 2 * G_TIME_SPAN_DAY((86400000000L))) {
4902 formats = CURRENT_WEEK_TIME_FORMATS;
4903 } else if (file_date_age > G_TIME_SPAN_DAY((86400000000L))) {
4904 formats = YESTERDAY_TIME_FORMATS;
4905 } else {
4906 formats = TODAY_TIME_FORMATS;
4907 }
4908
4909 /* Find the date format that just fits the required width. Instead of measuring
4910 * the resulting string width directly, measure the width of a template that represents
4911 * the widest possible version of a date in a given format. This is done by using M, m
4912 * and 0 for the variable letters/digits respectively.
4913 */
4914 format = NULL((void*)0);
4915
4916 for (i = 0; ; i += 2) {
4917 const char *width_template;
4918
4919 width_template = (formats [i] ? _(formats [i])dcgettext (((void*)0), formats [i], 5) : NULL((void*)0));
4920 if (width_template == NULL((void*)0)) {
4921 /* no more formats left */
4922 g_assert (format != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_645
; if (format != ((void*)0)) _g_boolean_var_645 = 1; else _g_boolean_var_645
= 0; _g_boolean_var_645; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 4922, ((const char*) (__func__
)), "format != NULL"); } while (0)
;
4923
4924 /* Can't fit even the shortest format -- return an ellipsized form in the
4925 * shortest format
4926 */
4927
4928 date_string = g_date_time_format (date_time, format);
4929
4930 if (truncate_callback == NULL((void*)0)) {
4931 result = date_string;
4932 break;
4933 }
4934
4935 result = (* truncate_callback) (date_string, width, measure_context);
4936 g_free (date_string);
4937 break;
4938 }
4939
4940 format = _(formats [i + 1])dcgettext (((void*)0), formats [i + 1], 5);
4941
4942 if (measure_callback == NULL((void*)0)) {
4943 /* don't care about fitting the width */
4944 break;
4945 }
4946
4947 if ((* measure_callback) (width_template, measure_context) <= width) {
4948 /* The template fits, this is the format we can fit. */
4949 break;
4950 }
4951 }
4952
4953 if (result == NULL((void*)0)) {
4954 result = g_date_time_format (date_time, format);
4955 }
4956
4957out:
4958 g_date_time_unref (date_time);
4959 return result;
4960}
4961
4962/**
4963 * caja_file_fit_modified_date_as_string:
4964 *
4965 * Get a user-displayable string representing a file modification date,
4966 * truncated to @width using the measuring and truncating callbacks.
4967 * @file: CajaFile representing the file in question.
4968 * @width: The desired resulting string width.
4969 * @measure_callback: The callback used to measure the string width.
4970 * @truncate_callback: The callback used to truncate the string to a desired width.
4971 * @measure_context: Data neede when measuring and truncating.
4972 *
4973 * Returns: Newly allocated string ready to display to the user.
4974 *
4975 **/
4976char *
4977caja_file_fit_modified_date_as_string (CajaFile *file,
4978 int width,
4979 CajaWidthMeasureCallback measure_callback,
4980 CajaTruncateCallback truncate_callback,
4981 void *measure_context)
4982{
4983 return caja_file_fit_date_as_string (file, CAJA_DATE_TYPE_MODIFIED,
4984 width, measure_callback, truncate_callback, measure_context);
4985}
4986
4987static char *
4988caja_file_get_trash_original_file_parent_as_string (CajaFile *file)
4989{
4990 if (file->details->trash_orig_path != NULL((void*)0)) {
4991 CajaFile *orig_file, *parent;
4992 GFile *location;
4993 char *filename;
4994
4995 orig_file = caja_file_get_trash_original_file (file);
4996 parent = caja_file_get_parent (orig_file);
4997 location = caja_file_get_location (parent);
4998
4999 filename = g_file_get_parse_name (location);
5000
5001 g_object_unref (location);
5002 caja_file_unref (parent);
5003 caja_file_unref (orig_file);
5004
5005 return filename;
5006 }
5007
5008 return NULL((void*)0);
5009}
5010
5011/**
5012 * caja_file_get_date_as_string:
5013 *
5014 * Get a user-displayable string representing a file modification date.
5015 * The caller is responsible for g_free-ing this string.
5016 * @file: CajaFile representing the file in question.
5017 *
5018 * Returns: Newly allocated string ready to display to the user.
5019 *
5020 **/
5021static char *
5022caja_file_get_date_as_string (CajaFile *file, CajaDateType date_type)
5023{
5024 return caja_file_fit_date_as_string (file, date_type,
5025 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5026}
5027
5028static CajaSpeedTradeoffValue show_directory_item_count;
5029static CajaSpeedTradeoffValue show_text_in_icons;
5030
5031static void
5032show_text_in_icons_changed_callback (gpointer callback_data)
5033{
5034 show_text_in_icons = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS"show-icon-text");
5035}
5036
5037static void
5038show_directory_item_count_changed_callback (gpointer callback_data)
5039{
5040 show_directory_item_count = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS"show-directory-item-counts");
5041}
5042
5043static gboolean
5044get_speed_tradeoff_preference_for_file (CajaFile *file, CajaSpeedTradeoffValue value)
5045{
5046 GFilesystemPreviewType use_preview;
5047
5048 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_646
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_646
= 1; else _g_boolean_var_646 = 0; _g_boolean_var_646; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5049
5050 use_preview = caja_file_get_filesystem_use_preview (file);
5051
5052 if (value == CAJA_SPEED_TRADEOFF_ALWAYS) {
5053 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5054 return FALSE(0);
5055 } else {
5056 return TRUE(!(0));
5057 }
5058 }
5059
5060 if (value == CAJA_SPEED_TRADEOFF_NEVER) {
5061 return FALSE(0);
5062 }
5063
5064 g_assert (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_647
; if (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY) _g_boolean_var_647
= 1; else _g_boolean_var_647 = 0; _g_boolean_var_647; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5064, ((const char*) (__func__)), "value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY"
); } while (0)
;
5065
5066 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5067 /* file system says to never preview anything */
5068 return FALSE(0);
5069 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
5070 /* file system says we should treat file as if it's local */
5071 return TRUE(!(0));
5072 } else {
5073 /* only local files */
5074 return caja_file_is_local (file);
5075 }
5076}
5077
5078gboolean
5079caja_file_should_show_directory_item_count (CajaFile *file)
5080{
5081 static gboolean show_directory_item_count_callback_added = FALSE(0);
5082
5083 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_648
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_648
= 1; else _g_boolean_var_648 = 0; _g_boolean_var_648; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5084
5085 if (file->details->mime_type &&
5086 strcmp (file->details->mime_type, "x-directory/smb-share") == 0) {
5087 return FALSE(0);
5088 }
5089
5090 /* Add the callback once for the life of our process */
5091 if (!show_directory_item_count_callback_added) {
5092 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5093 "changed::" CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5094 G_CALLBACK(show_directory_item_count_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5095 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5096 show_directory_item_count_callback_added = TRUE(!(0));
5097
5098 /* Peek for the first time */
5099 show_directory_item_count_changed_callback (NULL((void*)0));
5100 }
5101
5102 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5103}
5104
5105gboolean
5106caja_file_should_show_type (CajaFile *file)
5107{
5108 char *uri;
5109 gboolean ret;
5110
5111 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_649
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_649
= 1; else _g_boolean_var_649 = 0; _g_boolean_var_649; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5112
5113 uri = caja_file_get_uri (file);
5114 ret = ((strcmp (uri, "computer:///") != 0) &&
5115 (strcmp (uri, "network:///") != 0) &&
5116 (strcmp (uri, "smb:///") != 0));
5117 g_free (uri);
5118
5119 return ret;
5120}
5121
5122gboolean
5123caja_file_should_get_top_left_text (CajaFile *file)
5124{
5125 static gboolean show_text_in_icons_callback_added = FALSE(0);
5126
5127 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_650
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_650
= 1; else _g_boolean_var_650 = 0; _g_boolean_var_650; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5128
5129 /* Add the callback once for the life of our process */
5130 if (!show_text_in_icons_callback_added) {
5131 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5132 "changed::" CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5133 G_CALLBACK (show_text_in_icons_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5134 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5135 show_text_in_icons_callback_added = TRUE(!(0));
5136
5137 /* Peek for the first time */
5138 show_text_in_icons_changed_callback (NULL((void*)0));
5139 }
5140
5141 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_ALWAYS) {
5142 return TRUE(!(0));
5143 }
5144
5145 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_NEVER) {
5146 return FALSE(0);
5147 }
5148
5149 return get_speed_tradeoff_preference_for_file (file, show_text_in_icons);
5150}
5151
5152/**
5153 * caja_file_get_directory_item_count
5154 *
5155 * Get the number of items in a directory.
5156 * @file: CajaFile representing a directory.
5157 * @count: Place to put count.
5158 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5159 * the item count from being read on this directory. Otherwise set to FALSE.
5160 *
5161 * Returns: TRUE if count is available.
5162 *
5163 **/
5164gboolean
5165caja_file_get_directory_item_count (CajaFile *file,
5166 guint *count,
5167 gboolean *count_unreadable)
5168{
5169 if (count != NULL((void*)0)) {
5170 *count = 0;
5171 }
5172 if (count_unreadable != NULL((void*)0)) {
5173 *count_unreadable = FALSE(0);
5174 }
5175
5176 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_651
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_651
= 1; else _g_boolean_var_651 = 0; _g_boolean_var_651; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5177
5178 if (!caja_file_is_directory (file)) {
5179 return FALSE(0);
5180 }
5181
5182 if (!caja_file_should_show_directory_item_count (file)) {
5183 return FALSE(0);
5184 }
5185
5186 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5187 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5188 get_item_count, (file, count, count_unreadable))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
;
5189}
5190
5191/**
5192 * caja_file_get_deep_counts
5193 *
5194 * Get the statistics about items inside a directory.
5195 * @file: CajaFile representing a directory or file.
5196 * @directory_count: Place to put count of directories inside.
5197 * @files_count: Place to put count of files inside.
5198 * @unreadable_directory_count: Number of directories encountered
5199 * that were unreadable.
5200 * @total_size: Total size of all files and directories visited.
5201 * @total_size_on_disk: Total size on disk of all files and directories visited.
5202 * @force: Whether the deep counts should even be collected if
5203 * caja_file_should_show_directory_item_count returns FALSE
5204 * for this file.
5205 *
5206 * Returns: Status to indicate whether sizes are available.
5207 *
5208 **/
5209CajaRequestStatus
5210caja_file_get_deep_counts (CajaFile *file,
5211 guint *directory_count,
5212 guint *file_count,
5213 guint *unreadable_directory_count,
5214 goffset *total_size,
5215 goffset *total_size_on_disk,
5216 gboolean force)
5217{
5218 if (directory_count != NULL((void*)0)) {
5219 *directory_count = 0;
5220 }
5221 if (file_count != NULL((void*)0)) {
5222 *file_count = 0;
5223 }
5224 if (unreadable_directory_count != NULL((void*)0)) {
5225 *unreadable_directory_count = 0;
5226 }
5227 if (total_size != NULL((void*)0)) {
5228 *total_size = 0;
5229 }
5230 if (total_size_on_disk != NULL((void*)0)) {
5231 *total_size_on_disk = 0;
5232 }
5233
5234 g_return_val_if_fail (CAJA_IS_FILE (file), CAJA_REQUEST_DONE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_652
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_652
= 1; else _g_boolean_var_652 = 0; _g_boolean_var_652; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (CAJA_REQUEST_DONE
); } } while (0)
;
5235
5236 if (!force && !caja_file_should_show_directory_item_count (file)) {
5237 /* Set field so an existing value isn't treated as up-to-date
5238 * when preference changes later.
5239 */
5240 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5241 return file->details->deep_counts_status;
5242 }
5243
5244 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5245 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5246 get_deep_counts, (file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5247 directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5248 file_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5249 unreadable_directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5250 total_size,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5251 total_size_on_disk))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
;
5252}
5253
5254void
5255caja_file_recompute_deep_counts (CajaFile *file)
5256{
5257 if (file->details->deep_counts_status != CAJA_REQUEST_IN_PROGRESS) {
5258 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5259 if (file->details->directory != NULL((void*)0)) {
5260 caja_directory_add_file_to_work_queue (file->details->directory, file);
5261 caja_directory_async_state_changed (file->details->directory);
5262 }
5263 }
5264}
5265
5266gboolean
5267caja_file_can_get_size (CajaFile *file)
5268{
5269 return file->details->size == -1;
5270}
5271
5272
5273/**
5274 * caja_file_get_size
5275 *
5276 * Get the file size.
5277 * @file: CajaFile representing the file in question.
5278 *
5279 * Returns: Size in bytes.
5280 *
5281 **/
5282goffset
5283caja_file_get_size (CajaFile *file)
5284{
5285 /* Before we have info on the file, we don't know the size. */
5286 if (file->details->size == -1)
5287 return 0;
5288 return file->details->size;
5289}
5290
5291/**
5292 * caja_file_get_size_on_disk
5293 *
5294 * Get the file size on disk (how many bytes is using on the filesystem).
5295 * e.g.: usually files with 1 byte will use a whole inode so it will return the
5296 * size of 1 inode. If the file is sparse the size on disk will be equal or less
5297 * than the size of the file.
5298 * @file: CajaFile representing the file in question.
5299 *
5300 * Returns: Size in bytes.
5301 *
5302 **/
5303goffset
5304caja_file_get_size_on_disk (CajaFile *file)
5305{
5306 /* Before we have info on the file, we don't know the size. */
5307 if (file->details->size_on_disk == -1)
5308 return 0;
5309 return file->details->size_on_disk;
5310}
5311
5312time_t
5313caja_file_get_mtime (CajaFile *file)
5314{
5315 return file->details->mtime;
5316}
5317
5318
5319static void
5320set_attributes_get_info_callback (GObject *source_object,
5321 GAsyncResult *res,
5322 gpointer callback_data)
5323{
5324 CajaFileOperation *op;
5325 GFileInfo *new_info;
5326 GError *error;
5327
5328 op = callback_data;
5329
5330 error = NULL((void*)0);
5331 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
5332 if (new_info != NULL((void*)0)) {
5333 if (caja_file_update_info (op->file, new_info)) {
5334 caja_file_changed (op->file);
5335 }
5336 g_object_unref (new_info);
5337 }
5338 caja_file_operation_complete (op, NULL((void*)0), error);
5339 if (error) {
5340 g_error_free (error);
5341 }
5342}
5343
5344
5345static void
5346set_attributes_callback (GObject *source_object,
5347 GAsyncResult *result,
5348 gpointer callback_data)
5349{
5350 CajaFileOperation *op;
5351 GError *error;
5352 gboolean res;
5353
5354 op = callback_data;
5355
5356 error = NULL((void*)0);
5357 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5358 result,
5359 NULL((void*)0),
5360 &error);
5361
5362 if (res) {
5363 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5364 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
5365 0,
5366 G_PRIORITY_DEFAULT0,
5367 op->cancellable,
5368 set_attributes_get_info_callback, op);
5369 } else {
5370 caja_file_operation_complete (op, NULL((void*)0), error);
5371 g_error_free (error);
5372 }
5373}
5374
5375void
5376caja_file_set_attributes (CajaFile *file,
5377 GFileInfo *attributes,
5378 CajaFileOperationCallback callback,
5379 gpointer callback_data)
5380{
5381 CajaFileOperation *op;
5382 GFile *location;
5383
5384 op = caja_file_operation_new (file, callback, callback_data);
5385
5386 location = caja_file_get_location (file);
5387 g_file_set_attributes_async (location,
5388 attributes,
5389 0,
5390 G_PRIORITY_DEFAULT0,
5391 op->cancellable,
5392 set_attributes_callback,
5393 op);
5394 g_object_unref (location);
5395}
5396
5397
5398/**
5399 * caja_file_can_get_permissions:
5400 *
5401 * Check whether the permissions for a file are determinable.
5402 * This might not be the case for files on non-UNIX file systems.
5403 *
5404 * @file: The file in question.
5405 *
5406 * Return value: TRUE if the permissions are valid.
5407 */
5408gboolean
5409caja_file_can_get_permissions (CajaFile *file)
5410{
5411 return file->details->has_permissions;
5412}
5413
5414/**
5415 * caja_file_can_set_permissions:
5416 *
5417 * Check whether the current user is allowed to change
5418 * the permissions of a file.
5419 *
5420 * @file: The file in question.
5421 *
5422 * Return value: TRUE if the current user can change the
5423 * permissions of @file, FALSE otherwise. It's always possible
5424 * that when you actually try to do it, you will fail.
5425 */
5426gboolean
5427caja_file_can_set_permissions (CajaFile *file)
5428{
5429 uid_t user_id;
5430
5431 if (file->details->uid != -1 &&
5432 caja_file_is_local (file)) {
5433 /* Check the user. */
5434 user_id = geteuid();
5435
5436 /* Owner is allowed to set permissions. */
5437 if (user_id == (uid_t) file->details->uid) {
5438 return TRUE(!(0));
5439 }
5440
5441 /* Root is also allowed to set permissions. */
5442 if (user_id == 0) {
5443 return TRUE(!(0));
5444 }
5445
5446 /* Nobody else is allowed. */
5447 return FALSE(0);
5448 }
5449
5450 /* pretend to have full chmod rights when no info is available, relevant when
5451 * the FS can't provide ownership info, for instance for FTP */
5452 return TRUE(!(0));
5453}
5454
5455guint
5456caja_file_get_permissions (CajaFile *file)
5457{
5458 g_return_val_if_fail (caja_file_can_get_permissions (file), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_653
; if (caja_file_can_get_permissions (file)) _g_boolean_var_653
= 1; else _g_boolean_var_653 = 0; _g_boolean_var_653; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "caja_file_can_get_permissions (file)");
return (0); } } while (0)
;
5459
5460 return file->details->permissions;
5461}
5462
5463/**
5464 * caja_file_set_permissions:
5465 *
5466 * Change a file's permissions. This should only be called if
5467 * caja_file_can_set_permissions returned TRUE.
5468 *
5469 * @file: CajaFile representing the file in question.
5470 * @new_permissions: New permissions value. This is the whole
5471 * set of permissions, not a delta.
5472 **/
5473void
5474caja_file_set_permissions (CajaFile *file,
5475 guint32 new_permissions,
5476 CajaFileOperationCallback callback,
5477 gpointer callback_data)
5478{
5479 GFileInfo *info;
5480
5481 if (!caja_file_can_set_permissions (file)) {
5482 GError *error;
5483
5484 /* Claim that something changed even if the permission change failed.
5485 * This makes it easier for some clients who see the "reverting"
5486 * to the old permissions as "changing back".
5487 */
5488 caja_file_changed (file);
5489 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5490 _("Not allowed to set permissions")dcgettext (((void*)0), "Not allowed to set permissions", 5));
5491 (* callback) (file, NULL((void*)0), error, callback_data);
5492 g_error_free (error);
5493 return;
5494 }
5495
5496 /* Test the permissions-haven't-changed case explicitly
5497 * because we don't want to send the file-changed signal if
5498 * nothing changed.
5499 */
5500 if (new_permissions == file->details->permissions) {
5501 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5502 return;
5503 }
5504
5505 // Start UNDO-REDO
5506 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5507 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_SETPERMISSIONS, 1);
5508 caja_undostack_manager_data_set_file_permissions(undo_redo_data, caja_file_get_uri(file), file->details->permissions, new_permissions);
5509 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5510 undo_redo_data);
5511 }
5512 // End UNDO-REDO
5513
5514 info = g_file_info_new ();
5515 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode", new_permissions);
5516 caja_file_set_attributes (file, info, callback, callback_data);
5517 g_object_unref (info);
5518}
5519
5520/**
5521 * caja_file_can_get_selinux_context:
5522 *
5523 * Check whether the selinux context for a file are determinable.
5524 * This might not be the case for files on non-UNIX file systems,
5525 * files without a context or systems that don't support selinux.
5526 *
5527 * @file: The file in question.
5528 *
5529 * Return value: TRUE if the permissions are valid.
5530 */
5531gboolean
5532caja_file_can_get_selinux_context (CajaFile *file)
5533{
5534 return file->details->selinux_context != NULL((void*)0);
5535}
5536
5537
5538/**
5539 * caja_file_get_selinux_context:
5540 *
5541 * Get a user-displayable string representing a file's selinux
5542 * context
5543 * @file: CajaFile representing the file in question.
5544 *
5545 * Returns: Newly allocated string ready to display to the user.
5546 *
5547 **/
5548char *
5549caja_file_get_selinux_context (CajaFile *file)
5550{
5551 char *translated;
5552 char *raw;
5553
5554 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_654
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_654
= 1; else _g_boolean_var_654 = 0; _g_boolean_var_654; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
5555
5556 if (!caja_file_can_get_selinux_context (file)) {
5557 return NULL((void*)0);
5558 }
5559
5560 raw = file->details->selinux_context;
5561
5562#ifdef HAVE_SELINUX1
5563 if (selinux_raw_to_trans_context (raw, &translated) == 0) {
5564 char *tmp;
5565 tmp = g_strdup (translated)g_strdup_inline (translated);
5566 freecon (translated);
5567 translated = tmp;
5568 }
5569 else
5570#endif
5571 {
5572 translated = g_strdup (raw)g_strdup_inline (raw);
5573 }
5574
5575 return translated;
5576}
5577
5578static char *
5579get_real_name (const char *name, const char *gecos)
5580{
5581 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
5582
5583 if (gecos == NULL((void*)0)) {
5584 return NULL((void*)0);
5585 }
5586
5587 locale_string = eel_str_strip_substring_and_after (gecos, ",");
5588 if (!g_utf8_validate (locale_string, -1, NULL((void*)0))) {
5589 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5590 g_free (locale_string);
5591 } else {
5592 part_before_comma = locale_string;
5593 }
5594
5595 if (!g_utf8_validate (name, -1, NULL((void*)0))) {
5596 locale_string = g_locale_to_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5597 } else {
5598 locale_string = g_strdup (name)g_strdup_inline (name);
5599 }
5600
5601 capitalized_login_name = eel_str_capitalize (locale_string);
5602 g_free (locale_string);
5603
5604 if (capitalized_login_name == NULL((void*)0)) {
5605 real_name = part_before_comma;
5606 } else {
5607 real_name = eel_str_replace_substring
5608 (part_before_comma, "&", capitalized_login_name);
5609 g_free (part_before_comma);
5610 }
5611
5612
5613 if (eel_str_is_empty (real_name)
5614 || eel_strcmp (name, real_name) == 0
5615 || eel_strcmp (capitalized_login_name, real_name) == 0) {
5616 g_free (real_name);
5617 real_name = NULL((void*)0);
5618 }
5619
5620 g_free (capitalized_login_name);
5621
5622 return real_name;
5623}
5624
5625static gboolean
5626get_group_id_from_group_name (const char *group_name, uid_t *gid)
5627{
5628 struct group *group;
5629
5630 g_assert (gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_655
; if (gid != ((void*)0)) _g_boolean_var_655 = 1; else _g_boolean_var_655
= 0; _g_boolean_var_655; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5630, ((const char*) (__func__
)), "gid != NULL"); } while (0)
;
5631
5632 group = getgrnam (group_name);
5633
5634 if (group == NULL((void*)0)) {
5635 return FALSE(0);
5636 }
5637
5638 *gid = group->gr_gid;
5639
5640 return TRUE(!(0));
5641}
5642
5643static gboolean
5644get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid)
5645{
5646 struct passwd *password_info;
5647
5648 g_assert (uid != NULL || gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_656
; if (uid != ((void*)0) || gid != ((void*)0)) _g_boolean_var_656
= 1; else _g_boolean_var_656 = 0; _g_boolean_var_656; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5648, ((const char*) (__func__)), "uid != NULL || gid != NULL"
); } while (0)
;
5649
5650 password_info = getpwnam (user_name);
5651
5652 if (password_info == NULL((void*)0)) {
5653 return FALSE(0);
5654 }
5655
5656 if (uid != NULL((void*)0)) {
5657 *uid = password_info->pw_uid;
5658 }
5659
5660 if (gid != NULL((void*)0)) {
5661 *gid = password_info->pw_gid;
5662 }
5663
5664 return TRUE(!(0));
5665}
5666
5667static gboolean
5668get_user_id_from_user_name (const char *user_name, uid_t *id)
5669{
5670 return get_ids_from_user_name (user_name, id, NULL((void*)0));
5671}
5672
5673static gboolean
5674get_id_from_digit_string (const char *digit_string, uid_t *id)
5675{
5676 long scanned_id;
5677 char c;
5678
5679 g_assert (id != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_657
; if (id != ((void*)0)) _g_boolean_var_657 = 1; else _g_boolean_var_657
= 0; _g_boolean_var_657; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5679, ((const char*) (__func__
)), "id != NULL"); } while (0)
;
5680
5681 /* Only accept string if it has one integer with nothing
5682 * afterwards.
5683 */
5684 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) {
5685 return FALSE(0);
5686 }
5687 *id = scanned_id;
5688 return TRUE(!(0));
5689}
5690
5691/**
5692 * caja_file_can_get_owner:
5693 *
5694 * Check whether the owner a file is determinable.
5695 * This might not be the case for files on non-UNIX file systems.
5696 *
5697 * @file: The file in question.
5698 *
5699 * Return value: TRUE if the owner is valid.
5700 */
5701gboolean
5702caja_file_can_get_owner (CajaFile *file)
5703{
5704 /* Before we have info on a file, the owner is unknown. */
5705 return file->details->uid != -1;
5706}
5707
5708/**
5709 * caja_file_get_owner_name:
5710 *
5711 * Get the user name of the file's owner. If the owner has no
5712 * name, returns the userid as a string. The caller is responsible
5713 * for g_free-ing this string.
5714 *
5715 * @file: The file in question.
5716 *
5717 * Return value: A newly-allocated string.
5718 */
5719char *
5720caja_file_get_owner_name (CajaFile *file)
5721{
5722 return caja_file_get_owner_as_string (file, FALSE(0));
5723}
5724
5725/**
5726 * caja_file_can_set_owner:
5727 *
5728 * Check whether the current user is allowed to change
5729 * the owner of a file.
5730 *
5731 * @file: The file in question.
5732 *
5733 * Return value: TRUE if the current user can change the
5734 * owner of @file, FALSE otherwise. It's always possible
5735 * that when you actually try to do it, you will fail.
5736 */
5737gboolean
5738caja_file_can_set_owner (CajaFile *file)
5739{
5740 /* Not allowed to set the owner if we can't
5741 * even read it. This can happen on non-UNIX file
5742 * systems.
5743 */
5744 if (!caja_file_can_get_owner (file)) {
5745 return FALSE(0);
5746 }
5747
5748 /* Only root is also allowed to set the owner. */
5749 return geteuid() == 0;
5750}
5751
5752/**
5753 * caja_file_set_owner:
5754 *
5755 * Set the owner of a file. This will only have any effect if
5756 * caja_file_can_set_owner returns TRUE.
5757 *
5758 * @file: The file in question.
5759 * @user_name_or_id: The user name to set the owner to.
5760 * If the string does not match any user name, and the
5761 * string is an integer, the owner will be set to the
5762 * userid represented by that integer.
5763 * @callback: Function called when asynch owner change succeeds or fails.
5764 * @callback_data: Parameter passed back with callback function.
5765 */
5766void
5767caja_file_set_owner (CajaFile *file,
5768 const char *user_name_or_id,
5769 CajaFileOperationCallback callback,
5770 gpointer callback_data)
5771{
5772 GError *error;
5773 GFileInfo *info;
5774 uid_t new_id;
5775
5776 if (!caja_file_can_set_owner (file)) {
5777 /* Claim that something changed even if the permission
5778 * change failed. This makes it easier for some
5779 * clients who see the "reverting" to the old owner as
5780 * "changing back".
5781 */
5782 caja_file_changed (file);
5783 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5784 _("Not allowed to set owner")dcgettext (((void*)0), "Not allowed to set owner", 5));
5785 (* callback) (file, NULL((void*)0), error, callback_data);
5786 g_error_free (error);
5787 return;
5788 }
5789
5790 /* If no match treating user_name_or_id as name, try treating
5791 * it as id.
5792 */
5793 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
5794 && !get_id_from_digit_string (user_name_or_id, &new_id)) {
5795 /* Claim that something changed even if the permission
5796 * change failed. This makes it easier for some
5797 * clients who see the "reverting" to the old owner as
5798 * "changing back".
5799 */
5800 caja_file_changed (file);
5801 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
5802 _("Specified owner '%s' doesn't exist")dcgettext (((void*)0), "Specified owner '%s' doesn't exist", 5
)
, user_name_or_id);
5803 (* callback) (file, NULL((void*)0), error, callback_data);
5804 g_error_free (error);
5805 return;
5806 }
5807
5808 /* Test the owner-hasn't-changed case explicitly because we
5809 * don't want to send the file-changed signal if nothing
5810 * changed.
5811 */
5812 if (new_id == (uid_t) file->details->uid) {
5813 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5814 return;
5815 }
5816
5817 // Start UNDO-REDO
5818 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5819 char* current_owner = caja_file_get_owner_as_string (file, FALSE(0));
5820 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEOWNER, 1);
5821 caja_undostack_manager_data_set_owner_change_information(undo_redo_data, caja_file_get_uri(file), current_owner, user_name_or_id);
5822 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5823 undo_redo_data);
5824 g_free(current_owner);
5825 }
5826 // End UNDO-REDO
5827
5828 info = g_file_info_new ();
5829 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid", new_id);
5830 caja_file_set_attributes (file, info, callback, callback_data);
5831 g_object_unref (info);
5832}
5833
5834/**
5835 * caja_get_user_names:
5836 *
5837 * Get a list of user names. For users with a different associated
5838 * "real name", the real name follows the standard user name, separated
5839 * by a carriage return. The caller is responsible for freeing this list
5840 * and its contents.
5841 */
5842GList *
5843caja_get_user_names (void)
5844{
5845 GList *list;
5846 char *name;
5847 struct passwd *user;
5848
5849 list = NULL((void*)0);
5850
5851 setpwent ();
5852
5853 while ((user = getpwent ()) != NULL((void*)0)) {
5854 char *real_name;
5855
5856 real_name = get_real_name (user->pw_name, user->pw_gecos);
5857 if (real_name != NULL((void*)0)) {
5858 name = g_strconcat (user->pw_name, "\n", real_name, NULL((void*)0));
5859 } else {
5860 name = g_strdup (user->pw_name)g_strdup_inline (user->pw_name);
5861 }
5862 g_free (real_name);
5863 list = g_list_prepend (list, name);
5864 }
5865
5866 endpwent ();
5867
5868 return eel_g_str_list_alphabetize (list);
5869}
5870
5871/**
5872 * caja_file_can_get_group:
5873 *
5874 * Check whether the group a file is determinable.
5875 * This might not be the case for files on non-UNIX file systems.
5876 *
5877 * @file: The file in question.
5878 *
5879 * Return value: TRUE if the group is valid.
5880 */
5881gboolean
5882caja_file_can_get_group (CajaFile *file)
5883{
5884 /* Before we have info on a file, the group is unknown. */
5885 return file->details->gid != -1;
5886}
5887
5888/**
5889 * caja_file_get_group_name:
5890 *
5891 * Get the name of the file's group. If the group has no
5892 * name, returns the groupid as a string. The caller is responsible
5893 * for g_free-ing this string.
5894 *
5895 * @file: The file in question.
5896 *
5897 * Return value: A newly-allocated string.
5898 **/
5899char *
5900caja_file_get_group_name (CajaFile *file)
5901{
5902 return g_strdup (file->details->group)g_strdup_inline (file->details->group);
5903}
5904
5905/**
5906 * caja_file_can_set_group:
5907 *
5908 * Check whether the current user is allowed to change
5909 * the group of a file.
5910 *
5911 * @file: The file in question.
5912 *
5913 * Return value: TRUE if the current user can change the
5914 * group of @file, FALSE otherwise. It's always possible
5915 * that when you actually try to do it, you will fail.
5916 */
5917gboolean
5918caja_file_can_set_group (CajaFile *file)
5919{
5920 uid_t user_id;
5921
5922 /* Not allowed to set the permissions if we can't
5923 * even read them. This can happen on non-UNIX file
5924 * systems.
5925 */
5926 if (!caja_file_can_get_group (file)) {
5927 return FALSE(0);
5928 }
5929
5930 /* Check the user. */
5931 user_id = geteuid();
5932
5933 /* Owner is allowed to set group (with restrictions). */
5934 if (user_id == (uid_t) file->details->uid) {
5935 return TRUE(!(0));
5936 }
5937
5938 /* Root is also allowed to set group. */
5939 if (user_id == 0) {
5940 return TRUE(!(0));
5941 }
5942
5943 /* Nobody else is allowed. */
5944 return FALSE(0);
5945}
5946
5947/* Get a list of group names, filtered to only the ones
5948 * that contain the given username. If the username is
5949 * NULL, returns a list of all group names.
5950 */
5951static GList *
5952caja_get_group_names_for_user (void)
5953{
5954 GList *list;
5955 int count, i;
5956 gid_t gid_list[NGROUPS_MAX65536 + 1];
5957 struct group *group = NULL((void*)0);
5958
5959
5960 list = NULL((void*)0);
5961
5962 count = getgroups (NGROUPS_MAX65536 + 1, gid_list);
5963 for (i = 0; i < count; i++) {
5964 group = getgrgid (gid_list[i]);
5965 if (group == NULL((void*)0))
5966 break;
5967
5968 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5969 }
5970
5971 return eel_g_str_list_alphabetize (list);
5972}
5973
5974/**
5975 * caja_get_group_names:
5976 *
5977 * Get a list of all group names.
5978 */
5979GList *
5980caja_get_all_group_names (void)
5981{
5982 GList *list;
5983 struct group *group;
5984
5985 list = NULL((void*)0);
5986
5987 setgrent ();
5988
5989 while ((group = getgrent ()) != NULL((void*)0))
5990 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5991
5992 endgrent ();
5993
5994 return eel_g_str_list_alphabetize (list);
5995}
5996
5997/**
5998 * caja_file_get_settable_group_names:
5999 *
6000 * Get a list of all group names that the current user
6001 * can set the group of a specific file to.
6002 *
6003 * @file: The CajaFile in question.
6004 */
6005GList *
6006caja_file_get_settable_group_names (CajaFile *file)
6007{
6008 uid_t user_id;
6009 GList *result;
6010
6011 if (!caja_file_can_set_group (file)) {
6012 return NULL((void*)0);
6013 }
6014
6015 /* Check the user. */
6016 user_id = geteuid();
6017
6018 if (user_id == 0) {
6019 /* Root is allowed to set group to anything. */
6020 result = caja_get_all_group_names ();
6021 } else if (user_id == (uid_t) file->details->uid) {
6022 /* Owner is allowed to set group to any that owner is member of. */
6023 result = caja_get_group_names_for_user ();
6024 } else {
6025 g_warning ("unhandled case in caja_get_settable_group_names");
6026 result = NULL((void*)0);
6027 }
6028
6029 return result;
6030}
6031
6032/**
6033 * caja_file_set_group:
6034 *
6035 * Set the group of a file. This will only have any effect if
6036 * caja_file_can_set_group returns TRUE.
6037 *
6038 * @file: The file in question.
6039 * @group_name_or_id: The group name to set the owner to.
6040 * If the string does not match any group name, and the
6041 * string is an integer, the group will be set to the
6042 * group id represented by that integer.
6043 * @callback: Function called when asynch group change succeeds or fails.
6044 * @callback_data: Parameter passed back with callback function.
6045 */
6046void
6047caja_file_set_group (CajaFile *file,
6048 const char *group_name_or_id,
6049 CajaFileOperationCallback callback,
6050 gpointer callback_data)
6051{
6052 GError *error;
6053 GFileInfo *info;
6054 uid_t new_id;
6055
6056 if (!caja_file_can_set_group (file)) {
6057 /* Claim that something changed even if the group
6058 * change failed. This makes it easier for some
6059 * clients who see the "reverting" to the old group as
6060 * "changing back".
6061 */
6062 caja_file_changed (file);
6063 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
6064 _("Not allowed to set group")dcgettext (((void*)0), "Not allowed to set group", 5));
6065 (* callback) (file, NULL((void*)0), error, callback_data);
6066 g_error_free (error);
6067 return;
6068 }
6069
6070 /* If no match treating group_name_or_id as name, try treating
6071 * it as id.
6072 */
6073 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6074 && !get_id_from_digit_string (group_name_or_id, &new_id)) {
6075 /* Claim that something changed even if the group
6076 * change failed. This makes it easier for some
6077 * clients who see the "reverting" to the old group as
6078 * "changing back".
6079 */
6080 caja_file_changed (file);
6081 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
6082 _("Specified group '%s' doesn't exist")dcgettext (((void*)0), "Specified group '%s' doesn't exist", 5
)
, group_name_or_id);
6083 (* callback) (file, NULL((void*)0), error, callback_data);
6084 g_error_free (error);
6085 return;
6086 }
6087
6088 if (new_id == (gid_t) file->details->gid) {
6089 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
6090 return;
6091 }
6092
6093 // Start UNDO-REDO
6094 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6095 char* current_group = caja_file_get_group_name (file);
6096 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEGROUP, 1);
6097 caja_undostack_manager_data_set_group_change_information(undo_redo_data, caja_file_get_uri(file), current_group, group_name_or_id);
6098 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
6099 undo_redo_data);
6100 g_free(current_group);
6101 }
6102 // End UNDO-REDO
6103
6104 info = g_file_info_new ();
6105 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid", new_id);
6106 caja_file_set_attributes (file, info, callback, callback_data);
6107 g_object_unref (info);
6108}
6109
6110/**
6111 * caja_file_get_octal_permissions_as_string:
6112 *
6113 * Get a user-displayable string representing a file's permissions
6114 * as an octal number. The caller
6115 * is responsible for g_free-ing this string.
6116 * @file: CajaFile representing the file in question.
6117 *
6118 * Returns: Newly allocated string ready to display to the user.
6119 *
6120 **/
6121static char *
6122caja_file_get_octal_permissions_as_string (CajaFile *file)
6123{
6124 guint32 permissions;
6125
6126 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_658
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_658
= 1; else _g_boolean_var_658 = 0; _g_boolean_var_658; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6126, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6127
6128 if (!caja_file_can_get_permissions (file)) {
6129 return NULL((void*)0);
6130 }
6131
6132 permissions = file->details->permissions;
6133 return g_strdup_printf ("%03o", permissions);
6134}
6135
6136/**
6137 * caja_file_get_permissions_as_string:
6138 *
6139 * Get a user-displayable string representing a file's permissions. The caller
6140 * is responsible for g_free-ing this string.
6141 * @file: CajaFile representing the file in question.
6142 *
6143 * Returns: Newly allocated string ready to display to the user.
6144 *
6145 **/
6146static char *
6147caja_file_get_permissions_as_string (CajaFile *file)
6148{
6149 guint32 permissions;
6150 gboolean is_directory;
6151 gboolean is_link;
6152 gboolean suid, sgid, sticky;
6153
6154 if (!caja_file_can_get_permissions (file)) {
6155 return NULL((void*)0);
6156 }
6157
6158 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_659
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_659
= 1; else _g_boolean_var_659 = 0; _g_boolean_var_659; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6158, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6159
6160 permissions = file->details->permissions;
6161 is_directory = caja_file_is_directory (file);
6162 is_link = caja_file_is_symbolic_link (file);
6163
6164 /* We use ls conventions for displaying these three obscure flags */
6165 suid = permissions & S_ISUID04000;
6166 sgid = permissions & S_ISGID02000;
6167 sticky = permissions & S_ISVTX01000;
6168
6169 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6170 is_link ? 'l' : is_directory ? 'd' : '-',
6171 permissions & S_IRUSR0400 ? 'r' : '-',
6172 permissions & S_IWUSR0200 ? 'w' : '-',
6173 permissions & S_IXUSR0100
6174 ? (suid ? 's' : 'x')
6175 : (suid ? 'S' : '-'),
6176 permissions & S_IRGRP(0400 >> 3) ? 'r' : '-',
6177 permissions & S_IWGRP(0200 >> 3) ? 'w' : '-',
6178 permissions & S_IXGRP(0100 >> 3)
6179 ? (sgid ? 's' : 'x')
6180 : (sgid ? 'S' : '-'),
6181 permissions & S_IROTH((0400 >> 3) >> 3) ? 'r' : '-',
6182 permissions & S_IWOTH((0200 >> 3) >> 3) ? 'w' : '-',
6183 permissions & S_IXOTH((0100 >> 3) >> 3)
6184 ? (sticky ? 't' : 'x')
6185 : (sticky ? 'T' : '-'));
6186}
6187
6188/**
6189 * caja_file_get_owner_as_string:
6190 *
6191 * Get a user-displayable string representing a file's owner. The caller
6192 * is responsible for g_free-ing this string.
6193 * @file: CajaFile representing the file in question.
6194 * @include_real_name: Whether or not to append the real name (if any)
6195 * for this user after the user name.
6196 *
6197 * Returns: Newly allocated string ready to display to the user.
6198 *
6199 **/
6200static char *
6201caja_file_get_owner_as_string (CajaFile *file, gboolean include_real_name)
6202{
6203 char *user_name;
6204
6205 /* Before we have info on a file, the owner is unknown. */
6206 if (file->details->owner == NULL((void*)0) &&
6207 file->details->owner_real == NULL((void*)0)) {
6208 return NULL((void*)0);
6209 }
6210
6211 if (file->details->owner_real == NULL((void*)0)) {
6212 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6213 } else if (file->details->owner == NULL((void*)0)) {
6214 user_name = g_strdup (file->details->owner_real)g_strdup_inline (file->details->owner_real);
6215 } else if (include_real_name &&
6216 strcmp (file->details->owner, file->details->owner_real) != 0) {
6217 user_name = g_strdup_printf ("%s - %s",
6218 file->details->owner,
6219 file->details->owner_real);
6220 } else {
6221 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6222 }
6223
6224 return user_name;
6225}
6226
6227static char *
6228format_item_count_for_display (guint item_count,
6229 gboolean includes_directories,
6230 gboolean includes_files)
6231{
6232 g_assert (includes_directories || includes_files)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_660
; if (includes_directories || includes_files) _g_boolean_var_660
= 1; else _g_boolean_var_660 = 0; _g_boolean_var_660; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6232, ((const char*) (__func__)), "includes_directories || includes_files"
); } while (0)
;
6233
6234 return g_strdup_printf (includes_directories
6235 ? (includes_files
6236 ? ngettext ("%'u item", "%'u items", item_count)dcngettext (((void*)0), "%'u item", "%'u items", item_count, 5
)
6237 : ngettext ("%'u folder", "%'u folders", item_count)dcngettext (((void*)0), "%'u folder", "%'u folders", item_count
, 5)
)
6238 : ngettext ("%'u file", "%'u files", item_count)dcngettext (((void*)0), "%'u file", "%'u files", item_count, 5
)
, item_count);
6239}
6240
6241/**
6242 * caja_file_get_size_as_string:
6243 *
6244 * Get a user-displayable string representing a file size. The caller
6245 * is responsible for g_free-ing this string. The string is an item
6246 * count for directories.
6247 * @file: CajaFile representing the file in question.
6248 * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
6249 *
6250 * Returns: Newly allocated string ready to display to the user.
6251 *
6252 **/
6253static char *
6254caja_file_get_size_as_string (CajaFile *file,
6255 gboolean size_on_disk)
6256{
6257 guint item_count;
6258 gboolean count_unreadable;
6259 goffset size;
6260
6261 if (file == NULL((void*)0)) {
6262 return NULL((void*)0);
6263 }
6264
6265 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_661
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_661
= 1; else _g_boolean_var_661 = 0; _g_boolean_var_661; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6265, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6266
6267 if (caja_file_is_directory (file)) {
6268 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6269 return NULL((void*)0);
6270 }
6271 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6272 }
6273
6274 if (size_on_disk) {
6275 size = file->details->size_on_disk;
6276 } else {
6277 size = file->details->size;
6278 }
6279
6280 if (size == -1) {
6281 return NULL((void*)0);
6282 }
6283
6284 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6285 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6286 else
6287 return g_format_size (size);
6288}
6289
6290/**
6291 * caja_file_get_size_as_string_with_real_size:
6292 *
6293 * Get a user-displayable string representing a file size. The caller
6294 * is responsible for g_free-ing this string. The string is an item
6295 * count for directories.
6296 * This function adds the real size in the string.
6297 * @file: CajaFile representing the file in question.
6298 *
6299 * Returns: Newly allocated string ready to display to the user.
6300 *
6301 **/
6302static char *
6303caja_file_get_size_as_string_with_real_size (CajaFile *file,
6304 gboolean size_on_disk)
6305{
6306 guint item_count;
6307 gboolean count_unreadable;
6308 goffset size;
6309 char * formatted;
6310 char * formatted_plus_real;
6311 char * real_size;
6312
6313 if (file == NULL((void*)0)) {
6314 return NULL((void*)0);
6315 }
6316
6317 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_662
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_662
= 1; else _g_boolean_var_662 = 0; _g_boolean_var_662; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6317, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6318
6319 if (caja_file_is_directory (file)) {
6320 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6321 return NULL((void*)0);
6322 }
6323 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6324 }
6325
6326 if (size_on_disk) {
6327 size = file->details->size_on_disk;
6328 } else {
6329 size = file->details->size;
6330 }
6331
6332 if (size == -1) {
6333 return NULL((void*)0);
6334 }
6335
6336 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6337 formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6338 else
6339 formatted = g_format_size(size);
6340
6341 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
6342 real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT)dcgettext (((void*)0), "%""lu", 5), (guint64) size);
6343 formatted_plus_real = g_strdup_printf (_("%s (%s bytes)")dcgettext (((void*)0), "%s (%s bytes)", 5), formatted, real_size);
6344 g_free (real_size);
6345 g_free (formatted);
6346 return formatted_plus_real;
6347}
6348
6349static char *
6350caja_file_get_deep_count_as_string_internal (CajaFile *file,
6351 gboolean report_size,
6352 gboolean report_size_on_disk,
6353 gboolean report_directory_count,
6354 gboolean report_file_count)
6355{
6356 CajaRequestStatus status;
6357 guint directory_count;
6358 guint file_count;
6359 guint unreadable_count;
6360 guint total_count;
6361 goffset total_size;
6362 goffset total_size_on_disk;
6363
6364 /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
6365 g_assert (!(report_size && report_size_on_disk))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_663
; if (!(report_size && report_size_on_disk)) _g_boolean_var_663
= 1; else _g_boolean_var_663 = 0; _g_boolean_var_663; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6365, ((const char*) (__func__)), "!(report_size && report_size_on_disk)"
); } while (0)
;
6366 g_assert (!(report_size && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_664
; if (!(report_size && (report_directory_count || report_file_count
))) _g_boolean_var_664 = 1; else _g_boolean_var_664 = 0; _g_boolean_var_664
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6366, ((const char*) (__func__)), "!(report_size && (report_directory_count || report_file_count))"
); } while (0)
;
6367 g_assert (!(report_size_on_disk && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_665
; if (!(report_size_on_disk && (report_directory_count
|| report_file_count))) _g_boolean_var_665 = 1; else _g_boolean_var_665
= 0; _g_boolean_var_665; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6367, ((const char*) (__func__
)), "!(report_size_on_disk && (report_directory_count || report_file_count))"
); } while (0)
;
6368
6369 /* Must ask for something */
6370 g_assert (report_size || report_size_on_disk || report_directory_count || report_file_count)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_666
; if (report_size || report_size_on_disk || report_directory_count
|| report_file_count) _g_boolean_var_666 = 1; else _g_boolean_var_666
= 0; _g_boolean_var_666; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6370, ((const char*) (__func__
)), "report_size || report_size_on_disk || report_directory_count || report_file_count"
); } while (0)
;
6371
6372 if (file == NULL((void*)0)) {
6373 return NULL((void*)0);
6374 }
6375
6376 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_667
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_667
= 1; else _g_boolean_var_667 = 0; _g_boolean_var_667; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6376, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6377 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_668
; if (caja_file_is_directory (file)) _g_boolean_var_668 = 1; else
_g_boolean_var_668 = 0; _g_boolean_var_668; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6377, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
6378
6379 status = caja_file_get_deep_counts (file,
6380 &directory_count,
6381 &file_count,
6382 &unreadable_count,
6383 &total_size,
6384 &total_size_on_disk,
6385 FALSE(0));
6386
6387 /* Check whether any info is available. */
6388 if (status == CAJA_REQUEST_NOT_STARTED) {
6389 return NULL((void*)0);
6390 }
6391
6392 total_count = file_count + directory_count;
6393
6394 if (total_count == 0) {
6395 switch (status) {
6396 case CAJA_REQUEST_IN_PROGRESS:
6397 /* Don't return confident "zero" until we're finished looking,
6398 * because of next case.
6399 */
6400 return NULL((void*)0);
6401 case CAJA_REQUEST_DONE:
6402 /* Don't return "zero" if we there were contents but we couldn't read them. */
6403 if (unreadable_count != 0) {
6404 return NULL((void*)0);
6405 }
6406 default: break;
6407 }
6408 }
6409
6410 /* Note that we don't distinguish the "everything was readable" case
6411 * from the "some things but not everything was readable" case here.
6412 * Callers can distinguish them using caja_file_get_deep_counts
6413 * directly if desired.
6414 */
6415 if (report_size)
6416 {
6417 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6418 return g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
6419 else
6420 return g_format_size(total_size);
6421 }
6422
6423 if (report_size_on_disk)
6424 {
6425 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6426 return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
6427 else
6428 return g_format_size (total_size_on_disk);
6429 }
6430
6431 return format_item_count_for_display (report_directory_count
6432 ? (report_file_count ? total_count : directory_count)
6433 : file_count,
6434 report_directory_count, report_file_count);
6435}
6436
6437/**
6438 * caja_file_get_deep_size_as_string:
6439 *
6440 * Get a user-displayable string representing the size of all contained
6441 * items (only makes sense for directories). The caller
6442 * is responsible for g_free-ing this string.
6443 * @file: CajaFile representing the file in question.
6444 * @size_on_disk: if TRUE will return the size on disk, else return size of file.
6445 *
6446 * Returns: Newly allocated string ready to display to the user.
6447 *
6448 **/
6449static char *
6450caja_file_get_deep_size_as_string (CajaFile *file, gboolean size_on_disk)
6451{
6452 if (size_on_disk) {
6453 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), TRUE(!(0)), FALSE(0), FALSE(0));
6454 } else {
6455 return caja_file_get_deep_count_as_string_internal (file, TRUE(!(0)), FALSE(0), FALSE(0), FALSE(0));
6456 }
6457}
6458
6459/**
6460 * caja_file_get_deep_total_count_as_string:
6461 *
6462 * Get a user-displayable string representing the count of all contained
6463 * items (only makes sense for directories). The caller
6464 * is responsible for g_free-ing this string.
6465 * @file: CajaFile representing the file in question.
6466 *
6467 * Returns: Newly allocated string ready to display to the user.
6468 *
6469 **/
6470static char *
6471caja_file_get_deep_total_count_as_string (CajaFile *file)
6472{
6473 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), TRUE(!(0)));
6474}
6475
6476/**
6477 * caja_file_get_deep_file_count_as_string:
6478 *
6479 * Get a user-displayable string representing the count of all contained
6480 * items, not including directories. It only makes sense to call this
6481 * function on a directory. The caller
6482 * is responsible for g_free-ing this string.
6483 * @file: CajaFile representing the file in question.
6484 *
6485 * Returns: Newly allocated string ready to display to the user.
6486 *
6487 **/
6488static char *
6489caja_file_get_deep_file_count_as_string (CajaFile *file)
6490{
6491 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), FALSE(0), TRUE(!(0)));
6492}
6493
6494/**
6495 * caja_file_get_deep_directory_count_as_string:
6496 *
6497 * Get a user-displayable string representing the count of all contained
6498 * directories. It only makes sense to call this
6499 * function on a directory. The caller
6500 * is responsible for g_free-ing this string.
6501 * @file: CajaFile representing the file in question.
6502 *
6503 * Returns: Newly allocated string ready to display to the user.
6504 *
6505 **/
6506static char *
6507caja_file_get_deep_directory_count_as_string (CajaFile *file)
6508{
6509 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), FALSE(0));
6510}
6511
6512/**
6513 * caja_file_get_string_attribute:
6514 *
6515 * Get a user-displayable string from a named attribute. Use g_free to
6516 * free this string. If the value is unknown, returns NULL. You can call
6517 * caja_file_get_string_attribute_with_default if you want a non-NULL
6518 * default.
6519 *
6520 * @file: CajaFile representing the file in question.
6521 * @attribute_name: The name of the desired attribute. The currently supported
6522 * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
6523 * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
6524 * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
6525 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
6526 *
6527 * Returns: Newly allocated string ready to display to the user, or NULL
6528 * if the value is unknown or @attribute_name is not supported.
6529 *
6530 **/
6531char *
6532caja_file_get_string_attribute_q (CajaFile *file, GQuark attribute_q)
6533{
6534 char *extension_attribute;
6535
6536 if (attribute_q == attribute_name_q) {
2
Assuming 'attribute_q' is not equal to 'attribute_name_q'
3
Taking false branch
6537 return caja_file_get_display_name (file);
6538 }
6539 if (attribute_q == attribute_type_q) {
4
Assuming 'attribute_q' is not equal to 'attribute_type_q'
5
Taking false branch
6540 return caja_file_get_type_as_string (file);
6541 }
6542 if (attribute_q == attribute_mime_type_q) {
6
Assuming 'attribute_q' is not equal to 'attribute_mime_type_q'
7
Taking false branch
6543 return caja_file_get_mime_type (file);
6544 }
6545 if (attribute_q == attribute_size_q) {
8
Assuming 'attribute_q' is not equal to 'attribute_size_q'
9
Taking false branch
6546 return caja_file_get_size_as_string (file, FALSE(0));
6547 }
6548 if (attribute_q == attribute_size_on_disk_q) {
10
Assuming 'attribute_q' is not equal to 'attribute_size_on_disk_q'
11
Taking false branch
6549 return caja_file_get_size_as_string (file, TRUE(!(0)));
6550 }
6551 if (attribute_q == attribute_size_detail_q) {
12
Assuming 'attribute_q' is not equal to 'attribute_size_detail_q'
13
Taking false branch
6552 return caja_file_get_size_as_string_with_real_size (file, FALSE(0));
6553 }
6554 if (attribute_q == attribute_size_on_disk_detail_q) {
14
Assuming 'attribute_q' is not equal to 'attribute_size_on_disk_detail_q'
15
Taking false branch
6555 return caja_file_get_size_as_string_with_real_size (file, TRUE(!(0)));
6556 }
6557 if (attribute_q == attribute_deep_size_q) {
16
Assuming 'attribute_q' is not equal to 'attribute_deep_size_q'
17
Taking false branch
6558 return caja_file_get_deep_size_as_string (file, FALSE(0));
6559 }
6560 if (attribute_q == attribute_deep_size_on_disk_q) {
18
Assuming 'attribute_q' is not equal to 'attribute_deep_size_on_disk_q'
19
Taking false branch
6561 return caja_file_get_deep_size_as_string (file, TRUE(!(0)));
6562 }
6563 if (attribute_q == attribute_deep_file_count_q) {
20
Assuming 'attribute_q' is not equal to 'attribute_deep_file_count_q'
21
Taking false branch
6564 return caja_file_get_deep_file_count_as_string (file);
6565 }
6566 if (attribute_q == attribute_deep_directory_count_q) {
22
Assuming 'attribute_q' is not equal to 'attribute_deep_directory_count_q'
23
Taking false branch
6567 return caja_file_get_deep_directory_count_as_string (file);
6568 }
6569 if (attribute_q == attribute_deep_total_count_q) {
24
Assuming 'attribute_q' is not equal to 'attribute_deep_total_count_q'
25
Taking false branch
6570 return caja_file_get_deep_total_count_as_string (file);
6571 }
6572 if (attribute_q == attribute_trash_orig_path_q) {
26
Assuming 'attribute_q' is not equal to 'attribute_trash_orig_path_q'
27
Taking false branch
6573 return caja_file_get_trash_original_file_parent_as_string (file);
6574 }
6575 if (attribute_q == attribute_date_modified_q) {
28
Assuming 'attribute_q' is not equal to 'attribute_date_modified_q'
29
Taking false branch
6576 return caja_file_get_date_as_string (file,
6577 CAJA_DATE_TYPE_MODIFIED);
6578 }
6579 if (attribute_q == attribute_date_changed_q) {
30
Assuming 'attribute_q' is not equal to 'attribute_date_changed_q'
31
Taking false branch
6580 return caja_file_get_date_as_string (file,
6581 CAJA_DATE_TYPE_CHANGED);
6582 }
6583 if (attribute_q == attribute_date_accessed_q) {
32
Assuming 'attribute_q' is not equal to 'attribute_date_accessed_q'
33
Taking false branch
6584 return caja_file_get_date_as_string (file,
6585 CAJA_DATE_TYPE_ACCESSED);
6586 }
6587 if (attribute_q == attribute_date_created_q) {
34
Assuming 'attribute_q' is not equal to 'attribute_date_created_q'
35
Taking false branch
6588 return caja_file_get_date_as_string (file,
6589 CAJA_DATE_TYPE_CREATED);
6590 }
6591 if (attribute_q == attribute_trashed_on_q) {
36
Assuming 'attribute_q' is not equal to 'attribute_trashed_on_q'
37
Taking false branch
6592 return caja_file_get_date_as_string (file,
6593 CAJA_DATE_TYPE_TRASHED);
6594 }
6595 if (attribute_q == attribute_date_permissions_q) {
38
Assuming 'attribute_q' is not equal to 'attribute_date_permissions_q'
39
Taking false branch
6596 return caja_file_get_date_as_string (file,
6597 CAJA_DATE_TYPE_PERMISSIONS_CHANGED);
6598 }
6599 if (attribute_q == attribute_extension_q) {
40
Assuming 'attribute_q' is equal to 'attribute_extension_q'
41
Taking true branch
6600 return caja_file_get_extension_as_string (file);
42
Calling 'caja_file_get_extension_as_string'
6601 }
6602 if (attribute_q == attribute_permissions_q) {
6603 return caja_file_get_permissions_as_string (file);
6604 }
6605 if (attribute_q == attribute_selinux_context_q) {
6606 return caja_file_get_selinux_context (file);
6607 }
6608 if (attribute_q == attribute_octal_permissions_q) {
6609 return caja_file_get_octal_permissions_as_string (file);
6610 }
6611 if (attribute_q == attribute_owner_q) {
6612 return caja_file_get_owner_as_string (file, TRUE(!(0)));
6613 }
6614 if (attribute_q == attribute_group_q) {
6615 return caja_file_get_group_name (file);
6616 }
6617 if (attribute_q == attribute_uri_q) {
6618 return caja_file_get_uri (file);
6619 }
6620 if (attribute_q == attribute_where_q) {
6621 return caja_file_get_where_string (file);
6622 }
6623 if (attribute_q == attribute_link_target_q) {
6624 return caja_file_get_symbolic_link_target_path (file);
6625 }
6626 if (attribute_q == attribute_volume_q) {
6627 return caja_file_get_volume_name (file);
6628 }
6629 if (attribute_q == attribute_free_space_q) {
6630 return caja_file_get_volume_free_space (file);
6631 }
6632
6633 extension_attribute = NULL((void*)0);
6634
6635 if (file->details->pending_extension_attributes) {
6636 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
6637 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6638 }
6639
6640 if (extension_attribute == NULL((void*)0) && file->details->extension_attributes) {
6641 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
6642 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6643 }
6644
6645 return g_strdup (extension_attribute)g_strdup_inline (extension_attribute);
6646}
6647
6648char *
6649caja_file_get_string_attribute (CajaFile *file, const char *attribute_name)
6650{
6651 return caja_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
1
Calling 'caja_file_get_string_attribute_q'
6652}
6653
6654
6655/**
6656 * caja_file_get_string_attribute_with_default:
6657 *
6658 * Get a user-displayable string from a named attribute. Use g_free to
6659 * free this string. If the value is unknown, returns a string representing
6660 * the unknown value, which varies with attribute. You can call
6661 * caja_file_get_string_attribute if you want NULL instead of a default
6662 * result.
6663 *
6664 * @file: CajaFile representing the file in question.
6665 * @attribute_name: The name of the desired attribute. See the description of
6666 * caja_file_get_string for the set of available attributes.
6667 *
6668 * Returns: Newly allocated string ready to display to the user, or a string
6669 * such as "unknown" if the value is unknown or @attribute_name is not supported.
6670 *
6671 **/
6672char *
6673caja_file_get_string_attribute_with_default_q (CajaFile *file, GQuark attribute_q)
6674{
6675 char *result;
6676 guint item_count;
6677 gboolean count_unreadable;
6678 CajaRequestStatus status;
6679
6680 result = caja_file_get_string_attribute_q (file, attribute_q);
6681 if (result != NULL((void*)0)) {
6682 return result;
6683 }
6684
6685 /* Supply default values for the ones we know about. */
6686 /* FIXME bugzilla.gnome.org 40646:
6687 * Use hash table and switch statement or function pointers for speed?
6688 */
6689 if (attribute_q == attribute_size_q) {
6690 if (!caja_file_should_show_directory_item_count (file)) {
6691 return g_strdup ("--")g_strdup_inline ("--");
6692 }
6693 count_unreadable = FALSE(0);
6694 if (caja_file_is_directory (file)) {
6695 caja_file_get_directory_item_count (file, &item_count, &count_unreadable);
6696 }
6697 return g_strdup (count_unreadable ? _("? items") : "...")g_strdup_inline (count_unreadable ? dcgettext (((void*)0), "? items"
, 5) : "...")
;
6698 }
6699 if (attribute_q == attribute_deep_size_q) {
6700 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6701 if (status == CAJA_REQUEST_DONE) {
6702 /* This means no contents at all were readable */
6703 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6704 }
6705 return g_strdup ("...")g_strdup_inline ("...");
6706 }
6707 if (attribute_q == attribute_deep_size_on_disk_q) {
6708 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6709 if (status == CAJA_REQUEST_DONE) {
6710 /* This means no contents at all were readable */
6711 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6712 }
6713 return g_strdup ("...")g_strdup_inline ("...");
6714 }
6715 if (attribute_q == attribute_deep_file_count_q
6716 || attribute_q == attribute_deep_directory_count_q
6717 || attribute_q == attribute_deep_total_count_q) {
6718 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6719 if (status == CAJA_REQUEST_DONE) {
6720 /* This means no contents at all were readable */
6721 return g_strdup (_("? items"))g_strdup_inline (dcgettext (((void*)0), "? items", 5));
6722 }
6723 return g_strdup ("...")g_strdup_inline ("...");
6724 }
6725 if (attribute_q == attribute_type_q) {
6726 return g_strdup (_("unknown type"))g_strdup_inline (dcgettext (((void*)0), "unknown type", 5));
6727 }
6728 if (attribute_q == attribute_mime_type_q) {
6729 return g_strdup (_("unknown MIME type"))g_strdup_inline (dcgettext (((void*)0), "unknown MIME type", 5
))
;
6730 }
6731 if (attribute_q == attribute_trashed_on_q) {
6732 /* If n/a */
6733 return g_strdup ("")g_strdup_inline ("");
6734 }
6735 if (attribute_q == attribute_trash_orig_path_q) {
6736 /* If n/a */
6737 return g_strdup ("")g_strdup_inline ("");
6738 }
6739
6740 /* Fallback, use for both unknown attributes and attributes
6741 * for which we have no more appropriate default.
6742 */
6743 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
6744}
6745
6746char *
6747caja_file_get_string_attribute_with_default (CajaFile *file, const char *attribute_name)
6748{
6749 return caja_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
6750}
6751
6752gboolean
6753caja_file_is_date_sort_attribute_q (GQuark attribute_q)
6754{
6755 if (attribute_q == attribute_modification_date_q ||
6756 attribute_q == attribute_date_modified_q ||
6757 attribute_q == attribute_creation_date_q ||
6758 attribute_q == attribute_date_created_q ||
6759 attribute_q == attribute_accessed_date_q ||
6760 attribute_q == attribute_date_accessed_q ||
6761 attribute_q == attribute_date_changed_q ||
6762 attribute_q == attribute_trashed_on_q ||
6763 attribute_q == attribute_date_permissions_q) {
6764 return TRUE(!(0));
6765 }
6766
6767 return FALSE(0);
6768}
6769
6770/**
6771 * get_description:
6772 *
6773 * Get a user-displayable string representing a file type. The caller
6774 * is responsible for g_free-ing this string.
6775 * @file: CajaFile representing the file in question.
6776 *
6777 * Returns: Newly allocated string ready to display to the user.
6778 *
6779 **/
6780static char *
6781get_description (CajaFile *file)
6782{
6783 const char *mime_type;
6784 char *description;
6785
6786 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_669
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_669
= 1; else _g_boolean_var_669 = 0; _g_boolean_var_669; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6786, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6787
6788 mime_type = file->details->mime_type;
6789 if (eel_str_is_empty (mime_type)) {
6790 return NULL((void*)0);
6791 }
6792
6793 if (g_content_type_is_unknown (mime_type) &&
6794 caja_file_is_executable (file)) {
6795 return g_strdup (_("program"))g_strdup_inline (dcgettext (((void*)0), "program", 5));
6796 }
6797
6798 description = g_content_type_get_description (mime_type);
6799 if (!eel_str_is_empty (description)) {
6800 return description;
6801 }
6802
6803 return g_strdup (mime_type)g_strdup_inline (mime_type);
6804}
6805
6806/* Takes ownership of string */
6807static char *
6808update_description_for_link (CajaFile *file, char *string)
6809{
6810 if (caja_file_is_symbolic_link (file)) {
6811 char *res;
6812
6813 g_assert (!caja_file_is_broken_symbolic_link (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_670
; if (!caja_file_is_broken_symbolic_link (file)) _g_boolean_var_670
= 1; else _g_boolean_var_670 = 0; _g_boolean_var_670; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6813, ((const char*) (__func__)), "!caja_file_is_broken_symbolic_link (file)"
); } while (0)
;
6814 if (string == NULL((void*)0)) {
6815 return g_strdup (_("link"))g_strdup_inline (dcgettext (((void*)0), "link", 5));
6816 }
6817 /* Note to localizers: convert file type string for file
6818 * (e.g. "folder", "plain text") to file type for symbolic link
6819 * to that kind of file (e.g. "link to folder").
6820 */
6821 res = g_strdup_printf (_("Link to %s")dcgettext (((void*)0), "Link to %s", 5), string);
6822 g_free (string);
6823 return res;
6824 }
6825
6826 return string;
6827}
6828
6829static char *
6830caja_file_get_type_as_string (CajaFile *file)
6831{
6832 if (file == NULL((void*)0)) {
6833 return NULL((void*)0);
6834 }
6835
6836 if (caja_file_is_broken_symbolic_link (file)) {
6837 return g_strdup (_("link (broken)"))g_strdup_inline (dcgettext (((void*)0), "link (broken)", 5));
6838 }
6839
6840 return update_description_for_link (file, get_description (file));
6841}
6842
6843/**
6844 * caja_file_get_file_type
6845 *
6846 * Return this file's type.
6847 * @file: CajaFile representing the file in question.
6848 *
6849 * Returns: The type.
6850 *
6851 **/
6852GFileType
6853caja_file_get_file_type (CajaFile *file)
6854{
6855 if (file == NULL((void*)0)) {
6856 return G_FILE_TYPE_UNKNOWN;
6857 }
6858
6859 return file->details->type;
6860}
6861
6862/**
6863 * caja_file_get_mime_type
6864 *
6865 * Return this file's default mime type.
6866 * @file: CajaFile representing the file in question.
6867 *
6868 * Returns: The mime type.
6869 *
6870 **/
6871char *
6872caja_file_get_mime_type (CajaFile *file)
6873{
6874 if (file != NULL((void*)0)) {
6875 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_671
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_671
= 1; else _g_boolean_var_671 = 0; _g_boolean_var_671; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6876 if (file->details->mime_type != NULL((void*)0)) {
6877 return g_strdup (file->details->mime_type)g_strdup_inline (file->details->mime_type);
6878 }
6879 }
6880 return g_strdup ("application/octet-stream")g_strdup_inline ("application/octet-stream");
6881}
6882
6883/**
6884 * caja_file_is_mime_type
6885 *
6886 * Check whether a file is of a particular MIME type, or inherited
6887 * from it.
6888 * @file: CajaFile representing the file in question.
6889 * @mime_type: The MIME-type string to test (e.g. "text/plain")
6890 *
6891 * Return value: TRUE if @mime_type exactly matches the
6892 * file's MIME type.
6893 *
6894 **/
6895gboolean
6896caja_file_is_mime_type (CajaFile *file, const char *mime_type)
6897{
6898 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_672
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_672
= 1; else _g_boolean_var_672 = 0; _g_boolean_var_672; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
6899 g_return_val_if_fail (mime_type != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_673
; if (mime_type != ((void*)0)) _g_boolean_var_673 = 1; else _g_boolean_var_673
= 0; _g_boolean_var_673; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "mime_type != NULL"
); return ((0)); } } while (0)
;
6900
6901 if (file->details->mime_type == NULL((void*)0)) {
6902 return FALSE(0);
6903 }
6904 return g_content_type_is_a (file->details->mime_type,
6905 mime_type);
6906}
6907
6908gboolean
6909caja_file_is_launchable (CajaFile *file)
6910{
6911 gboolean type_can_be_executable;
6912
6913 type_can_be_executable = FALSE(0);
6914 if (file->details->mime_type != NULL((void*)0)) {
6915 type_can_be_executable =
6916 g_content_type_can_be_executable (file->details->mime_type);
6917 }
6918
6919 return type_can_be_executable &&
6920 caja_file_can_get_permissions (file) &&
6921 caja_file_can_execute (file) &&
6922 caja_file_is_executable (file) &&
6923 !caja_file_is_directory (file);
6924}
6925
6926
6927/**
6928 * caja_file_get_emblem_icons
6929 *
6930 * Return the list of names of emblems that this file should display,
6931 * in canonical order.
6932 * @file: CajaFile representing the file in question.
6933 *
6934 * Returns: A list of emblem names.
6935 *
6936 **/
6937GList *
6938caja_file_get_emblem_icons (CajaFile *file,
6939 char **exclude)
6940{
6941 GList *keywords, *l;
6942 GList *icons;
6943 char *icon_names[2];
6944 char *keyword;
6945 int i;
6946 GIcon *icon;
6947
6948 if (file == NULL((void*)0)) {
6949 return NULL((void*)0);
6950 }
6951
6952 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_674
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_674
= 1; else _g_boolean_var_674 = 0; _g_boolean_var_674; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6953
6954 keywords = caja_file_get_keywords (file);
6955 keywords = prepend_automatic_keywords (file, keywords);
6956
6957 icons = NULL((void*)0);
6958 for (l = keywords; l != NULL((void*)0); l = l->next) {
6959 keyword = l->data;
6960
6961#ifdef TRASH_IS_FAST_ENOUGH
6962 if (strcmp (keyword, CAJA_FILE_EMBLEM_NAME_TRASH"trash") == 0) {
6963 char *uri;
6964 gboolean file_is_trash;
6965 /* Leave out the trash emblem for the trash itself, since
6966 * putting a trash emblem on a trash icon is gilding the
6967 * lily.
6968 */
6969 uri = caja_file_get_uri (file);
6970 file_is_trash = strcmp (uri, EEL_TRASH_URI"trash:") == 0;
6971 g_free (uri);
6972 if (file_is_trash) {
6973 continue;
6974 }
6975 }
6976#endif
6977 if (exclude) {
6978 for (i = 0; exclude[i] != NULL((void*)0); i++) {
6979 if (strcmp (exclude[i], keyword) == 0) {
6980 continue;
6981 }
6982 }
6983 }
6984
6985
6986 icon_names[0] = g_strconcat ("emblem-", keyword, NULL((void*)0));
6987 icon_names[1] = keyword;
6988 icon = g_themed_icon_new_from_names (icon_names, 2);
6989 g_free (icon_names[0]);
6990
6991 icons = g_list_prepend (icons, icon);
6992 }
6993
6994 g_list_free_full (keywords, g_free);
6995
6996 return icons;
6997}
6998
6999GList *
7000caja_file_get_emblem_pixbufs (CajaFile *file,
7001 int size,
7002 gboolean force_size,
7003 char **exclude)
7004{
7005 GList *icons, *l;
7006 GList *pixbufs;
7007 GdkPixbuf *pixbuf;
7008 GIcon *icon = NULL((void*)0);
7009 CajaIconInfo *icon_info = NULL((void*)0);
7010
7011 icons = caja_file_get_emblem_icons (file, exclude);
7012 pixbufs = NULL((void*)0);
7013
7014 for (l = icons; l != NULL((void*)0); l = l->next) {
7015 icon = l->data;
7016
7017 icon_info = caja_icon_info_lookup (icon, size, 1);
7018 if (force_size) {
7019 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (icon_info, size);
7020 } else {
7021 pixbuf = caja_icon_info_get_pixbuf_nodefault (icon_info);
7022 }
7023
7024 if (pixbuf) {
7025 pixbufs = g_list_prepend (pixbufs, pixbuf);
7026 }
7027
7028
7029 g_object_unref (icon_info);
7030 g_object_unref (icon);
7031 }
7032 g_list_free (icons);
7033
7034 return g_list_reverse (pixbufs);
7035
7036
7037}
7038
7039static GList *
7040sort_keyword_list_and_remove_duplicates (GList *keywords)
7041{
7042 GList *p;
7043
7044 if (keywords != NULL((void*)0)) {
7045 GList *duplicate_link = NULL((void*)0);
7046
7047 keywords = eel_g_str_list_alphabetize (keywords);
7048
7049 p = keywords;
7050 while (p->next != NULL((void*)0)) {
7051 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) {
7052 duplicate_link = p->next;
7053 keywords = g_list_remove_link (keywords, duplicate_link);
7054 g_list_free_full (duplicate_link, g_free);
7055 } else {
7056 p = p->next;
7057 }
7058 }
7059 }
7060
7061 return keywords;
7062}
7063
7064/**
7065 * caja_file_get_keywords
7066 *
7067 * Return this file's keywords.
7068 * @file: CajaFile representing the file in question.
7069 *
7070 * Returns: A list of keywords.
7071 *
7072 **/
7073GList *
7074caja_file_get_keywords (CajaFile *file)
7075{
7076 GList *keywords;
7077
7078 if (file == NULL((void*)0)) {
7079 return NULL((void*)0);
7080 }
7081
7082 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_675
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_675
= 1; else _g_boolean_var_675 = 0; _g_boolean_var_675; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7083
7084 /* Put all the keywords into a list. */
7085 keywords = caja_file_get_metadata_list
7086 (file, CAJA_METADATA_KEY_EMBLEMS"emblems");
7087
7088 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7089 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7090
7091 return sort_keyword_list_and_remove_duplicates (keywords);
7092}
7093
7094/**
7095 * caja_file_set_keywords
7096 *
7097 * Change this file's keywords.
7098 * @file: CajaFile representing the file in question.
7099 * @keywords: New set of keywords (a GList of strings).
7100 *
7101 **/
7102void
7103caja_file_set_keywords (CajaFile *file, GList *keywords)
7104{
7105 GList *canonical_keywords;
7106
7107 /* Invalidate the emblem compare cache */
7108 g_free (file->details->compare_by_emblem_cache);
7109 file->details->compare_by_emblem_cache = NULL((void*)0);
7110
7111 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_676
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_676
= 1; else _g_boolean_var_676 = 0; _g_boolean_var_676; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7112
7113 canonical_keywords = sort_keyword_list_and_remove_duplicates
7114 (g_list_copy (keywords));
7115 caja_file_set_metadata_list
7116 (file, CAJA_METADATA_KEY_EMBLEMS"emblems", canonical_keywords);
7117 g_list_free (canonical_keywords);
7118}
7119
7120/**
7121 * caja_file_is_symbolic_link
7122 *
7123 * Check if this file is a symbolic link.
7124 * @file: CajaFile representing the file in question.
7125 *
7126 * Returns: True if the file is a symbolic link.
7127 *
7128 **/
7129gboolean
7130caja_file_is_symbolic_link (CajaFile *file)
7131{
7132 return file->details->is_symlink;
7133}
7134
7135gboolean
7136caja_file_is_mountpoint (CajaFile *file)
7137{
7138 return file->details->is_mountpoint;
7139}
7140
7141GMount *
7142caja_file_get_mount (CajaFile *file)
7143{
7144 if (file->details->mount) {
7145 return g_object_ref (file->details->mount)((__typeof__ (file->details->mount)) (g_object_ref) (file
->details->mount))
;
7146 }
7147 return NULL((void*)0);
7148}
7149
7150static void
7151file_mount_unmounted (GMount *mount,
7152 gpointer data)
7153{
7154 CajaFile *file;
7155
7156 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
7157
7158 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_MOUNT);
7159}
7160
7161void
7162caja_file_set_mount (CajaFile *file,
7163 GMount *mount)
7164{
7165 if (file->details->mount) {
7166 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
7167 g_object_unref (file->details->mount);
7168 file->details->mount = NULL((void*)0);
7169 }
7170
7171 if (mount) {
7172 file->details->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
7173 g_signal_connect (mount, "unmounted",g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
7174 G_CALLBACK (file_mount_unmounted), file)g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
;
7175 }
7176}
7177
7178/**
7179 * caja_file_is_broken_symbolic_link
7180 *
7181 * Check if this file is a symbolic link with a missing target.
7182 * @file: CajaFile representing the file in question.
7183 *
7184 * Returns: True if the file is a symbolic link with a missing target.
7185 *
7186 **/
7187gboolean
7188caja_file_is_broken_symbolic_link (CajaFile *file)
7189{
7190 if (file == NULL((void*)0)) {
7191 return FALSE(0);
7192 }
7193
7194 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_677
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_677
= 1; else _g_boolean_var_677 = 0; _g_boolean_var_677; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7195
7196 /* Non-broken symbolic links return the target's type for get_file_type. */
7197 return caja_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7198}
7199
7200static void
7201get_fs_free_cb (GObject *source_object,
7202 GAsyncResult *res,
7203 gpointer user_data)
7204{
7205 CajaDirectory *directory;
7206 guint64 free_space;
7207 GFileInfo *info;
7208
7209 directory = CAJA_DIRECTORY (user_data)((((CajaDirectory*) (void *) ((user_data)))));
7210
7211 free_space = (guint64)-1;
7212 info = g_file_query_filesystem_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
7213 res, NULL((void*)0));
7214 if (info) {
7215 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
7216 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
7217 }
7218 g_object_unref (info);
7219 }
7220
7221 if (directory->details->free_space != free_space) {
7222 CajaFile *file;
7223
7224 directory->details->free_space = free_space;
7225 file = caja_directory_get_existing_corresponding_file (directory);
7226 if (file) {
7227 caja_file_emit_changed (file);
7228 caja_file_unref (file);
7229 }
7230 }
7231 caja_directory_unref (directory);
7232}
7233
7234/**
7235 * caja_file_get_volume_free_space
7236 * Get a nicely formatted char with free space on the file's volume
7237 * @file: CajaFile representing the file in question.
7238 *
7239 * Returns: newly-allocated copy of file size in a formatted string
7240 */
7241char *
7242caja_file_get_volume_free_space (CajaFile *file)
7243{
7244 CajaDirectory *directory;
7245 char *res;
7246 time_t now;
7247
7248 directory = caja_directory_get_for_file (file);
7249
7250 now = time (NULL((void*)0));
7251 /* Update first time and then every 2 seconds */
7252 if (directory->details->free_space_read == 0 ||
7253 (now - directory->details->free_space_read) > 2) {
7254 GFile *location;
7255
7256 directory->details->free_space_read = now;
7257 location = caja_file_get_location (file);
7258 g_file_query_filesystem_info_async (location,
7259 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free",
7260 0, NULL((void*)0),
7261 get_fs_free_cb,
7262 directory); /* Inherits ref */
7263 g_object_unref (location);
7264 } else {
7265 caja_directory_unref (directory);
7266 }
7267
7268
7269 res = NULL((void*)0);
7270
7271 if (directory->details->free_space != (guint64) -1)
7272 {
7273 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
7274 res = g_format_size_full (directory->details->free_space, G_FORMAT_SIZE_IEC_UNITS);
7275 else
7276 res = g_format_size(directory->details->free_space);
7277 }
7278
7279 return res;
7280}
7281
7282/**
7283 * caja_file_get_volume_name
7284 * Get the path of the volume the file resides on
7285 * @file: CajaFile representing the file in question.
7286 *
7287 * Returns: newly-allocated copy of the volume name of the target file,
7288 * if the volume name isn't set, it returns the mount path of the volume
7289 */
7290char *
7291caja_file_get_volume_name (CajaFile *file)
7292{
7293 GFile *location;
7294 char *res;
7295 GMount *mount;
7296
7297 res = NULL((void*)0);
7298
7299 location = caja_file_get_location (file);
7300 mount = g_file_find_enclosing_mount (location, NULL((void*)0), NULL((void*)0));
7301 if (mount) {
7302 res = g_strdup (g_mount_get_name (mount))g_strdup_inline (g_mount_get_name (mount));
7303 g_object_unref (mount);
7304 }
7305 g_object_unref (location);
7306
7307 return res;
7308}
7309
7310/**
7311 * caja_file_get_symbolic_link_target_path
7312 *
7313 * Get the file path of the target of a symbolic link. It is an error
7314 * to call this function on a file that isn't a symbolic link.
7315 * @file: CajaFile representing the symbolic link in question.
7316 *
7317 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7318 */
7319char *
7320caja_file_get_symbolic_link_target_path (CajaFile *file)
7321{
7322 if (!caja_file_is_symbolic_link (file)) {
7323 g_warning ("File has symlink target, but is not marked as symlink");
7324 }
7325
7326 return g_strdup (file->details->symlink_name)g_strdup_inline (file->details->symlink_name);
7327}
7328
7329/**
7330 * caja_file_get_symbolic_link_target_uri
7331 *
7332 * Get the uri of the target of a symbolic link. It is an error
7333 * to call this function on a file that isn't a symbolic link.
7334 * @file: CajaFile representing the symbolic link in question.
7335 *
7336 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7337 */
7338char *
7339caja_file_get_symbolic_link_target_uri (CajaFile *file)
7340{
7341 if (!caja_file_is_symbolic_link (file)) {
7342 g_warning ("File has symlink target, but is not marked as symlink");
7343 }
7344
7345 if (file->details->symlink_name == NULL((void*)0)) {
7346 return NULL((void*)0);
7347 } else {
7348 GFile *location, *parent, *target;
7349 char *target_uri;
7350
7351 target = NULL((void*)0);
7352
7353 location = caja_file_get_location (file);
7354 parent = g_file_get_parent (location);
7355 g_object_unref (location);
7356 if (parent) {
7357 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7358 g_object_unref (parent);
7359 }
7360
7361 target_uri = NULL((void*)0);
7362 if (target) {
7363 target_uri = g_file_get_uri (target);
7364 g_object_unref (target);
7365 }
7366 return target_uri;
7367 }
7368}
7369
7370/**
7371 * caja_file_is_caja_link
7372 *
7373 * Check if this file is a "caja link", meaning a historical
7374 * caja xml link file or a desktop file.
7375 * @file: CajaFile representing the file in question.
7376 *
7377 * Returns: True if the file is a caja link.
7378 *
7379 **/
7380gboolean
7381caja_file_is_caja_link (CajaFile *file)
7382{
7383 if (file->details->mime_type == NULL((void*)0))
7384 {
7385 return FALSE(0);
7386 }
7387 return g_content_type_equals (file->details->mime_type,
7388 "application/x-desktop");
7389}
7390
7391/**
7392 * caja_file_is_directory
7393 *
7394 * Check if this file is a directory.
7395 * @file: CajaFile representing the file in question.
7396 *
7397 * Returns: TRUE if @file is a directory.
7398 *
7399 **/
7400gboolean
7401caja_file_is_directory (CajaFile *file)
7402{
7403 return caja_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
7404}
7405
7406/**
7407 * caja_file_is_user_special_directory
7408 *
7409 * Check if this file is a special platform directory.
7410 * @file: CajaFile representing the file in question.
7411 * @special_directory: GUserDirectory representing the type to test for
7412 *
7413 * Returns: TRUE if @file is a special directory of the given kind.
7414 */
7415gboolean
7416caja_file_is_user_special_directory (CajaFile *file,
7417 GUserDirectory special_directory)
7418{
7419 gboolean is_special_dir;
7420 const gchar *special_dir;
7421
7422 special_dir = g_get_user_special_dir (special_directory);
7423 is_special_dir = FALSE(0);
7424
7425 if (special_dir) {
7426 GFile *loc;
7427 GFile *special_gfile;
7428
7429 loc = caja_file_get_location (file);
7430 special_gfile = g_file_new_for_path (special_dir);
7431 is_special_dir = g_file_equal (loc, special_gfile);
7432 g_object_unref (special_gfile);
7433 g_object_unref (loc);
7434 }
7435
7436 return is_special_dir;
7437}
7438
7439gboolean
7440caja_file_is_archive (CajaFile *file)
7441{
7442 char *mime_type;
7443 int i;
7444 static const char * archive_mime_types[] = { "application/x-gtar",
7445 "application/x-zip",
7446 "application/x-zip-compressed",
7447 "application/zip",
7448 "application/x-zip",
7449 "application/x-tar",
7450 "application/x-7z-compressed",
7451 "application/x-rar",
7452 "application/x-rar-compressed",
7453 "application/x-jar",
7454 "application/x-java-archive",
7455 "application/x-war",
7456 "application/x-ear",
7457 "application/x-arj",
7458 "application/x-gzip",
7459 "application/x-bzip-compressed-tar",
7460 "application/x-compressed-tar" };
7461
7462 g_return_val_if_fail (file != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_678
; if (file != ((void*)0)) _g_boolean_var_678 = 1; else _g_boolean_var_678
= 0; _g_boolean_var_678; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file != NULL"); return
((0)); } } while (0)
;
7463
7464 mime_type = caja_file_get_mime_type (file);
7465 for (i = 0; i < G_N_ELEMENTS (archive_mime_types)(sizeof (archive_mime_types) / sizeof ((archive_mime_types)[0
]))
; i++) {
7466 if (!strcmp (mime_type, archive_mime_types[i])) {
7467 g_free (mime_type);
7468 return TRUE(!(0));
7469 }
7470 }
7471 g_free (mime_type);
7472
7473 return FALSE(0);
7474}
7475
7476
7477/**
7478 * caja_file_is_in_trash
7479 *
7480 * Check if this file is a file in trash.
7481 * @file: CajaFile representing the file in question.
7482 *
7483 * Returns: TRUE if @file is in a trash.
7484 *
7485 **/
7486gboolean
7487caja_file_is_in_trash (CajaFile *file)
7488{
7489 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_679
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_679
= 1; else _g_boolean_var_679 = 0; _g_boolean_var_679; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7489, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7490
7491 return caja_directory_is_in_trash (file->details->directory);
7492}
7493
7494GError *
7495caja_file_get_file_info_error (CajaFile *file)
7496{
7497 if (!file->details->get_info_failed) {
7498 return NULL((void*)0);
7499 }
7500
7501 return file->details->get_info_error;
7502}
7503
7504/**
7505 * caja_file_contains_text
7506 *
7507 * Check if this file contains text.
7508 * This is private and is used to decide whether or not to read the top left text.
7509 * @file: CajaFile representing the file in question.
7510 *
7511 * Returns: TRUE if @file has a text MIME type.
7512 *
7513 **/
7514gboolean
7515caja_file_contains_text (CajaFile *file)
7516{
7517 if (file == NULL((void*)0)) {
7518 return FALSE(0);
7519 }
7520
7521 /* All text files inherit from text/plain */
7522 return caja_file_is_mime_type (file, "text/plain");
7523}
7524
7525/**
7526 * caja_file_is_binary
7527 *
7528 * Check if this file is a binary file.
7529 * This is private and is used to decide whether or not to show the diff
7530 * button in the file conflict dialog.
7531 * @file: CajaFile representing the file in question.
7532 *
7533 * Returns: TRUE if @file is a binary file.
7534 *
7535 **/
7536gboolean
7537caja_file_is_binary (CajaFile *file)
7538{
7539 if (!caja_file_can_read(file))
7540 {
7541 return FALSE(0);
7542 }
7543
7544 gboolean is_binary = FALSE(0);
7545 int i = 0;
7546 FILE *fp;
7547
7548 /* Check the first 4096 bytes of the files. If these contains a 0,
7549 * we can assume the file is binary.
7550 * This idea is taken from python code of meld.
7551 */
7552
7553 fp = g_fopenfopen (g_file_get_path (caja_file_get_location (file)), "r");
7554 if (fp == NULL((void*)0))
7555 {
7556 return FALSE(0);
7557 }
7558
7559 while (!feof (fp)) {
7560 int c;
7561
7562 if (i > 4096) {
7563 break;
7564 }
7565 c = fgetc(fp);
7566 if (c == 0) {
7567 is_binary = TRUE(!(0));
7568 break;
7569 }
7570 i++;
7571 }
7572 fclose(fp);
7573
7574 return is_binary;
7575}
7576
7577/**
7578 * caja_file_is_executable
7579 *
7580 * Check if this file is executable at all.
7581 * @file: CajaFile representing the file in question.
7582 *
7583 * Returns: TRUE if any of the execute bits are set. FALSE if
7584 * not, or if the permissions are unknown.
7585 *
7586 **/
7587gboolean
7588caja_file_is_executable (CajaFile *file)
7589{
7590 if (!file->details->has_permissions) {
7591 /* File's permissions field is not valid.
7592 * Can't access specific permissions, so return FALSE.
7593 */
7594 return FALSE(0);
7595 }
7596
7597 return file->details->can_execute;
7598}
7599
7600/**
7601 * caja_file_peek_top_left_text
7602 *
7603 * Peek at the text from the top left of the file.
7604 * @file: CajaFile representing the file in question.
7605 *
7606 * Returns: NULL if there is no text readable, otherwise, the text.
7607 * This string is owned by the file object and should not
7608 * be kept around or freed.
7609 *
7610 **/
7611char *
7612caja_file_peek_top_left_text (CajaFile *file,
7613 gboolean need_large_text,
7614 gboolean *needs_loading)
7615{
7616 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_680
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_680
= 1; else _g_boolean_var_680 = 0; _g_boolean_var_680; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7617
7618 if (!caja_file_should_get_top_left_text (file)) {
7619 if (needs_loading) {
7620 *needs_loading = FALSE(0);
7621 }
7622 return NULL((void*)0);
7623 }
7624
7625 if (needs_loading) {
7626 *needs_loading = !file->details->top_left_text_is_up_to_date;
7627 if (need_large_text) {
7628 *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text;
7629 }
7630 }
7631
7632 /* Show " ..." in the file until we read the contents in. */
7633 if (!file->details->got_top_left_text) {
7634
7635 if (caja_file_contains_text (file)) {
7636 return " ...";
7637 }
7638 return NULL((void*)0);
7639 }
7640
7641 /* Show what we read in. */
7642 return file->details->top_left_text;
7643}
7644
7645/**
7646 * caja_file_get_top_left_text
7647 *
7648 * Get the text from the top left of the file.
7649 * @file: CajaFile representing the file in question.
7650 *
7651 * Returns: NULL if there is no text readable, otherwise, the text.
7652 *
7653 **/
7654char *
7655caja_file_get_top_left_text (CajaFile *file)
7656{
7657 return g_strdup (caja_file_peek_top_left_text (file, FALSE, NULL))g_strdup_inline (caja_file_peek_top_left_text (file, (0), ((void
*)0)))
;
7658}
7659
7660char *
7661caja_file_get_filesystem_id (CajaFile *file)
7662{
7663 return g_strdup (file->details->filesystem_id)g_strdup_inline (file->details->filesystem_id);
7664}
7665
7666CajaFile *
7667caja_file_get_trash_original_file (CajaFile *file)
7668{
7669 CajaFile *original_file;
7670
7671 original_file = NULL((void*)0);
7672
7673 if (file->details->trash_orig_path != NULL((void*)0)) {
7674 GFile *location;
7675
7676 location = g_file_new_for_path (file->details->trash_orig_path);
7677 original_file = caja_file_get (location);
7678 g_object_unref (location);
7679 }
7680
7681 return original_file;
7682
7683}
7684
7685void
7686caja_file_mark_gone (CajaFile *file)
7687{
7688 CajaDirectory *directory;
7689
7690 if (file->details->is_gone)
7691 return;
7692
7693 file->details->is_gone = TRUE(!(0));
7694
7695 update_links_if_target (file);
7696
7697 /* Drop it from the symlink hash ! */
7698 remove_from_link_hash_table (file);
7699
7700 /* Let the directory know it's gone. */
7701 directory = file->details->directory;
7702 if (!caja_file_is_self_owned (file)) {
7703 caja_directory_remove_file (directory, file);
7704 }
7705
7706 caja_file_clear_info (file);
7707
7708 /* FIXME bugzilla.gnome.org 42429:
7709 * Maybe we can get rid of the name too eventually, but
7710 * for now that would probably require too many if statements
7711 * everywhere anyone deals with the name. Maybe we can give it
7712 * a hard-coded "<deleted>" name or something.
7713 */
7714}
7715
7716/**
7717 * caja_file_changed
7718 *
7719 * Notify the user that this file has changed.
7720 * @file: CajaFile representing the file in question.
7721 **/
7722void
7723caja_file_changed (CajaFile *file)
7724{
7725 GList fake_list;
7726
7727 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_681
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_681
= 1; else _g_boolean_var_681 = 0; _g_boolean_var_681; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7728
7729 if (caja_file_is_self_owned (file)) {
7730 caja_file_emit_changed (file);
7731 } else {
7732 fake_list.data = file;
7733 fake_list.next = NULL((void*)0);
7734 fake_list.prev = NULL((void*)0);
7735 caja_directory_emit_change_signals
7736 (file->details->directory, &fake_list);
7737 }
7738}
7739
7740/**
7741 * caja_file_updated_deep_count_in_progress
7742 *
7743 * Notify clients that a newer deep count is available for
7744 * the directory in question.
7745 */
7746void
7747caja_file_updated_deep_count_in_progress (CajaFile *file) {
7748 GList *link_files, *node;
7749
7750 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_682
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_682
= 1; else _g_boolean_var_682 = 0; _g_boolean_var_682; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7750, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7751 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_683
; if (caja_file_is_directory (file)) _g_boolean_var_683 = 1; else
_g_boolean_var_683 = 0; _g_boolean_var_683; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 7751, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
7752
7753 /* Send out a signal. */
7754 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
7755
7756 /* Tell link files pointing to this object about the change. */
7757 link_files = get_link_files (file);
7758 for (node = link_files; node != NULL((void*)0); node = node->next) {
7759 caja_file_updated_deep_count_in_progress (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))));
7760 }
7761 caja_file_list_free (link_files);
7762}
7763
7764/**
7765 * caja_file_emit_changed
7766 *
7767 * Emit a file changed signal.
7768 * This can only be called by the directory, since the directory
7769 * also has to emit a files_changed signal.
7770 *
7771 * @file: CajaFile representing the file in question.
7772 **/
7773void
7774caja_file_emit_changed (CajaFile *file)
7775{
7776 GList *link_files, *p;
7777
7778 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_684
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_684
= 1; else _g_boolean_var_684 = 0; _g_boolean_var_684; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7778, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7779
7780
7781 /* Invalidate the emblem compare cache. -- This is not the cleanest
7782 * place to do it but it is the one guaranteed bottleneck through
7783 * which all change notifications pass.
7784 */
7785 g_free (file->details->compare_by_emblem_cache);
7786 file->details->compare_by_emblem_cache = NULL((void*)0);
7787
7788 /* Send out a signal. */
7789 g_signal_emit (file, signals[CHANGED], 0, file);
7790
7791 /* Tell link files pointing to this object about the change. */
7792 link_files = get_link_files (file);
7793 for (p = link_files; p != NULL((void*)0); p = p->next) {
7794 if (p->data != file) {
7795 caja_file_changed (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
7796 }
7797 }
7798 caja_file_list_free (link_files);
7799}
7800
7801/**
7802 * caja_file_is_gone
7803 *
7804 * Check if a file has already been deleted.
7805 * @file: CajaFile representing the file in question.
7806 *
7807 * Returns: TRUE if the file is already gone.
7808 **/
7809gboolean
7810caja_file_is_gone (CajaFile *file)
7811{
7812 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_685
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_685
= 1; else _g_boolean_var_685 = 0; _g_boolean_var_685; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7813
7814 return file->details->is_gone;
7815}
7816
7817/**
7818 * caja_file_is_not_yet_confirmed
7819 *
7820 * Check if we're in a state where we don't know if a file really
7821 * exists or not, before the initial I/O is complete.
7822 * @file: CajaFile representing the file in question.
7823 *
7824 * Returns: TRUE if the file is already gone.
7825 **/
7826gboolean
7827caja_file_is_not_yet_confirmed (CajaFile *file)
7828{
7829 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_686
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_686
= 1; else _g_boolean_var_686 = 0; _g_boolean_var_686; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7830
7831 return !file->details->got_file_info;
7832}
7833
7834/**
7835 * caja_file_check_if_ready
7836 *
7837 * Check whether the values for a set of file attributes are
7838 * currently available, without doing any additional work. This
7839 * is useful for callers that want to reflect updated information
7840 * when it is ready but don't want to force the work required to
7841 * obtain the information, which might be slow network calls, e.g.
7842 *
7843 * @file: The file being queried.
7844 * @file_attributes: A bit-mask with the desired information.
7845 *
7846 * Return value: TRUE if all of the specified attributes are currently readable.
7847 */
7848gboolean
7849caja_file_check_if_ready (CajaFile *file,
7850 CajaFileAttributes file_attributes)
7851{
7852 /* To be parallel with call_when_ready, return
7853 * TRUE for NULL file.
7854 */
7855 if (file == NULL((void*)0)) {
7856 return TRUE(!(0));
7857 }
7858
7859 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_687
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_687
= 1; else _g_boolean_var_687 = 0; _g_boolean_var_687; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7860
7861 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7862 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7863 check_if_ready, (file, file_attributes))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
;
7864}
7865
7866void
7867caja_file_call_when_ready (CajaFile *file,
7868 CajaFileAttributes file_attributes,
7869 CajaFileCallback callback,
7870 gpointer callback_data)
7871
7872{
7873 if (file == NULL((void*)0)) {
7874 (* callback) (file, callback_data);
7875 return;
7876 }
7877
7878 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_688
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_688
= 1; else _g_boolean_var_688 = 0; _g_boolean_var_688; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7879
7880 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7881 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7882 call_when_ready, (file, file_attributes,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7883 callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
;
7884}
7885
7886void
7887caja_file_cancel_call_when_ready (CajaFile *file,
7888 CajaFileCallback callback,
7889 gpointer callback_data)
7890{
7891 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_689
; if (callback != ((void*)0)) _g_boolean_var_689 = 1; else _g_boolean_var_689
= 0; _g_boolean_var_689; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
7892
7893 if (file == NULL((void*)0)) {
7894 return;
7895 }
7896
7897 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_690
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_690
= 1; else _g_boolean_var_690 = 0; _g_boolean_var_690; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7898
7899 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7900 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7901 cancel_call_when_ready, (file, callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
;
7902}
7903
7904static void
7905invalidate_directory_count (CajaFile *file)
7906{
7907 file->details->directory_count_is_up_to_date = FALSE(0);
7908}
7909
7910static void
7911invalidate_deep_counts (CajaFile *file)
7912{
7913 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
7914}
7915
7916static void
7917invalidate_mime_list (CajaFile *file)
7918{
7919 file->details->mime_list_is_up_to_date = FALSE(0);
7920}
7921
7922static void
7923invalidate_top_left_text (CajaFile *file)
7924{
7925 file->details->top_left_text_is_up_to_date = FALSE(0);
7926}
7927
7928static void
7929invalidate_file_info (CajaFile *file)
7930{
7931 file->details->file_info_is_up_to_date = FALSE(0);
7932}
7933
7934static void
7935invalidate_link_info (CajaFile *file)
7936{
7937 file->details->link_info_is_up_to_date = FALSE(0);
7938}
7939
7940static void
7941invalidate_thumbnail (CajaFile *file)
7942{
7943 file->details->thumbnail_is_up_to_date = FALSE(0);
7944}
7945
7946static void
7947invalidate_mount (CajaFile *file)
7948{
7949 file->details->mount_is_up_to_date = FALSE(0);
7950}
7951
7952void
7953caja_file_invalidate_extension_info_internal (CajaFile *file)
7954{
7955 if (file->details->pending_info_providers)
7956 g_list_free_full (file->details->pending_info_providers, g_object_unref);
7957
7958 file->details->pending_info_providers =
7959 caja_extensions_get_for_type (CAJA_TYPE_INFO_PROVIDER(caja_info_provider_get_type ()));
7960}
7961
7962void
7963caja_file_invalidate_attributes_internal (CajaFile *file,
7964 CajaFileAttributes file_attributes)
7965{
7966 Request request;
7967
7968 if (file == NULL((void*)0)) {
7969 return;
7970 }
7971
7972 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
7973 /* Desktop icon files are always up to date.
7974 * If we invalidate their attributes they
7975 * will lose data, so we just ignore them.
7976 */
7977 return;
7978 }
7979
7980 request = caja_directory_set_up_request (file_attributes);
7981
7982 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)((request) & (1<<(REQUEST_DIRECTORY_COUNT)))) {
7983 invalidate_directory_count (file);
7984 }
7985 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)((request) & (1<<(REQUEST_DEEP_COUNT)))) {
7986 invalidate_deep_counts (file);
7987 }
7988 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)((request) & (1<<(REQUEST_MIME_LIST)))) {
7989 invalidate_mime_list (file);
7990 }
7991 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)((request) & (1<<(REQUEST_FILE_INFO)))) {
7992 invalidate_file_info (file);
7993 }
7994 if (REQUEST_WANTS_TYPE (request, REQUEST_TOP_LEFT_TEXT)((request) & (1<<(REQUEST_TOP_LEFT_TEXT)))) {
7995 invalidate_top_left_text (file);
7996 }
7997 if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)((request) & (1<<(REQUEST_LINK_INFO)))) {
7998 invalidate_link_info (file);
7999 }
8000 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)((request) & (1<<(REQUEST_EXTENSION_INFO)))) {
8001 caja_file_invalidate_extension_info_internal (file);
8002 }
8003 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)((request) & (1<<(REQUEST_THUMBNAIL)))) {
8004 invalidate_thumbnail (file);
8005 }
8006 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)((request) & (1<<(REQUEST_MOUNT)))) {
8007 invalidate_mount (file);
8008 }
8009
8010 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
8011}
8012
8013gboolean
8014caja_file_has_open_window (CajaFile *file)
8015{
8016 return file->details->has_open_window;
8017}
8018
8019void
8020caja_file_set_has_open_window (CajaFile *file,
8021 gboolean has_open_window)
8022{
8023 has_open_window = (has_open_window != FALSE(0));
8024
8025 if (file->details->has_open_window != has_open_window) {
8026 file->details->has_open_window = has_open_window;
8027 caja_file_changed (file);
8028 }
8029}
8030
8031
8032gboolean
8033caja_file_is_thumbnailing (CajaFile *file)
8034{
8035 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_691
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_691
= 1; else _g_boolean_var_691 = 0; _g_boolean_var_691; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
8036
8037 return file->details->is_thumbnailing;
8038}
8039
8040void
8041caja_file_set_is_thumbnailing (CajaFile *file,
8042 gboolean is_thumbnailing)
8043{
8044 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_692
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_692
= 1; else _g_boolean_var_692 = 0; _g_boolean_var_692; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
8045
8046 file->details->is_thumbnailing = is_thumbnailing;
8047}
8048
8049
8050/**
8051 * caja_file_invalidate_attributes
8052 *
8053 * Invalidate the specified attributes and force a reload.
8054 * @file: CajaFile representing the file in question.
8055 * @file_attributes: attributes to froget.
8056 **/
8057
8058void
8059caja_file_invalidate_attributes (CajaFile *file,
8060 CajaFileAttributes file_attributes)
8061{
8062 /* Cancel possible in-progress loads of any of these attributes */
8063 caja_directory_cancel_loading_file_attributes (file->details->directory,
8064 file,
8065 file_attributes);
8066
8067 /* Actually invalidate the values */
8068 caja_file_invalidate_attributes_internal (file, file_attributes);
8069
8070 caja_directory_add_file_to_work_queue (file->details->directory, file);
8071
8072 /* Kick off I/O if necessary */
8073 caja_directory_async_state_changed (file->details->directory);
8074}
8075
8076CajaFileAttributes
8077caja_file_get_all_attributes (void)
8078{
8079 return CAJA_FILE_ATTRIBUTE_INFO |
8080 CAJA_FILE_ATTRIBUTE_LINK_INFO |
8081 CAJA_FILE_ATTRIBUTE_DEEP_COUNTS |
8082 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8083 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8084 CAJA_FILE_ATTRIBUTE_TOP_LEFT_TEXT |
8085 CAJA_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
8086 CAJA_FILE_ATTRIBUTE_EXTENSION_INFO |
8087 CAJA_FILE_ATTRIBUTE_THUMBNAIL |
8088 CAJA_FILE_ATTRIBUTE_MOUNT;
8089}
8090
8091void
8092caja_file_invalidate_all_attributes (CajaFile *file)
8093{
8094 CajaFileAttributes all_attributes;
8095
8096 all_attributes = caja_file_get_all_attributes ();
8097 caja_file_invalidate_attributes (file, all_attributes);
8098}
8099
8100
8101/**
8102 * caja_file_dump
8103 *
8104 * Debugging call, prints out the contents of the file
8105 * fields.
8106 *
8107 * @file: file to dump.
8108 **/
8109void
8110caja_file_dump (CajaFile *file)
8111{
8112 long size = file->details->deep_size;
8113 long size_on_disk = file->details->deep_size_on_disk;
8114 char *uri;
8115 const char *file_kind;
8116
8117 uri = caja_file_get_uri (file);
8118 g_print ("uri: %s \n", uri);
8119 if (!file->details->got_file_info) {
8120 g_print ("no file info \n");
8121 } else if (file->details->get_info_failed) {
8122 g_print ("failed to get file info \n");
8123 } else {
8124 g_print ("size: %ld \n", size);
8125 g_print ("disk size: %ld \n", size_on_disk);
8126 switch (file->details->type) {
8127 case G_FILE_TYPE_REGULAR:
8128 file_kind = "regular file";
8129 break;
8130 case G_FILE_TYPE_DIRECTORY:
8131 file_kind = "folder";
8132 break;
8133 case G_FILE_TYPE_SPECIAL:
8134 file_kind = "special";
8135 break;
8136 case G_FILE_TYPE_SYMBOLIC_LINK:
8137 file_kind = "symbolic link";
8138 break;
8139 case G_FILE_TYPE_UNKNOWN:
8140 default:
8141 file_kind = "unknown";
8142 break;
8143 }
8144 g_print ("kind: %s \n", file_kind);
8145 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) {
8146 g_print ("link to %s \n", file->details->symlink_name);
8147 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8148 }
8149 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8150 }
8151 g_free (uri);
8152}
8153
8154/**
8155 * caja_file_list_ref
8156 *
8157 * Ref all the files in a list.
8158 * @list: GList of files.
8159 **/
8160GList *
8161caja_file_list_ref (GList *list)
8162{
8163 g_list_foreach (list, (GFunc) caja_file_ref, NULL((void*)0));
8164 return list;
8165}
8166
8167/**
8168 * caja_file_list_unref
8169 *
8170 * Unref all the files in a list.
8171 * @list: GList of files.
8172 **/
8173void
8174caja_file_list_unref (GList *list)
8175{
8176 g_list_foreach (list, (GFunc) caja_file_unref, NULL((void*)0));
8177}
8178
8179/**
8180 * caja_file_list_free
8181 *
8182 * Free a list of files after unrefing them.
8183 * @list: GList of files.
8184 **/
8185void
8186caja_file_list_free (GList *list)
8187{
8188 caja_file_list_unref (list);
8189 g_list_free (list);
8190}
8191
8192/**
8193 * caja_file_list_copy
8194 *
8195 * Copy the list of files, making a new ref of each,
8196 * @list: GList of files.
8197 **/
8198GList *
8199caja_file_list_copy (GList *list)
8200{
8201 return g_list_copy (caja_file_list_ref (list));
8202}
8203
8204static gboolean
8205get_attributes_for_default_sort_type (CajaFile *file,
8206 gboolean *is_download,
8207 gboolean *is_trash)
8208{
8209 gboolean is_download_dir, is_desktop_dir, is_trash_dir, retval;
8210
8211 *is_download = FALSE(0);
8212 *is_trash = FALSE(0);
8213 retval = FALSE(0);
8214
8215 /* special handling for certain directories */
8216 if (file && caja_file_is_directory (file)) {
8217 is_download_dir =
8218 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8219 is_desktop_dir =
8220 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP);
8221 is_trash_dir =
8222 caja_file_is_in_trash (file);
8223
8224 if (is_download_dir && !is_desktop_dir) {
8225 *is_download = TRUE(!(0));
8226 retval = TRUE(!(0));
8227 } else if (is_trash_dir) {
8228 *is_trash = TRUE(!(0));
8229 retval = TRUE(!(0));
8230 }
8231 }
8232
8233 return retval;
8234}
8235
8236CajaFileSortType
8237caja_file_get_default_sort_type (CajaFile *file,
8238 gboolean *reversed)
8239{
8240 CajaFileSortType retval;
8241 gboolean is_download, is_trash, res;
8242
8243 retval = CAJA_FILE_SORT_NONE;
8244 is_download = is_trash = FALSE(0);
8245 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8246
8247 if (res) {
8248 if (is_download) {
8249 retval = CAJA_FILE_SORT_BY_MTIME;
8250 } else if (is_trash) {
8251 retval = CAJA_FILE_SORT_BY_TRASHED_TIME;
8252 }
8253
8254 if (reversed != NULL((void*)0)) {
8255 *reversed = res;
8256 }
8257 }
8258
8259 return retval;
8260}
8261
8262const gchar *
8263caja_file_get_default_sort_attribute (CajaFile *file,
8264 gboolean *reversed)
8265{
8266 const gchar *retval;
8267 gboolean is_download, is_trash, res;
8268
8269 retval = NULL((void*)0);
8270 is_download = is_trash = FALSE(0);
8271 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8272
8273 if (res) {
8274 if (is_download) {
8275 retval = g_quark_to_string (attribute_date_modified_q);
8276 } else if (is_trash) {
8277 retval = g_quark_to_string (attribute_trashed_on_q);
8278 }
8279
8280 if (reversed != NULL((void*)0)) {
8281 *reversed = res;
8282 }
8283 }
8284
8285 return retval;
8286}
8287
8288static int
8289compare_by_display_name_cover (gconstpointer a, gconstpointer b)
8290{
8291 return compare_by_display_name (CAJA_FILE (a)((((CajaFile*) (void *) ((a))))), CAJA_FILE (b)((((CajaFile*) (void *) ((b))))));
8292}
8293
8294/**
8295 * caja_file_list_sort_by_display_name
8296 *
8297 * Sort the list of files by file name.
8298 * @list: GList of files.
8299 **/
8300GList *
8301caja_file_list_sort_by_display_name (GList *list)
8302{
8303 return g_list_sort (list, compare_by_display_name_cover);
8304}
8305
8306static GList *ready_data_list = NULL((void*)0);
8307
8308typedef struct
8309{
8310 GList *file_list;
8311 GList *remaining_files;
8312 CajaFileListCallback callback;
8313 gpointer callback_data;
8314} FileListReadyData;
8315
8316static void
8317file_list_ready_data_free (FileListReadyData *data)
8318{
8319 GList *l;
8320
8321 l = g_list_find (ready_data_list, data);
8322 if (l != NULL((void*)0)) {
8323 ready_data_list = g_list_delete_link (ready_data_list, l);
8324
8325 caja_file_list_free (data->file_list);
8326 g_list_free (data->remaining_files);
8327 g_free (data);
8328 }
8329}
8330
8331static FileListReadyData *
8332file_list_ready_data_new (GList *file_list,
8333 CajaFileListCallback callback,
8334 gpointer callback_data)
8335{
8336 FileListReadyData *data;
8337
8338 data = g_new0 (FileListReadyData, 1)(FileListReadyData *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (FileListReadyData); 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; }))
;
8339 data->file_list = caja_file_list_copy (file_list);
8340 data->remaining_files = g_list_copy (file_list);
8341 data->callback = callback;
8342 data->callback_data = callback_data;
8343
8344 ready_data_list = g_list_prepend (ready_data_list, data);
8345
8346 return data;
8347}
8348
8349static void
8350file_list_file_ready_callback (CajaFile *file,
8351 gpointer user_data)
8352{
8353 FileListReadyData *data;
8354
8355 data = user_data;
8356 data->remaining_files = g_list_remove (data->remaining_files, file);
8357
8358 if (data->remaining_files == NULL((void*)0)) {
8359 if (data->callback) {
8360 (*data->callback) (data->file_list, data->callback_data);
8361 }
8362
8363 file_list_ready_data_free (data);
8364 }
8365}
8366
8367void
8368caja_file_list_call_when_ready (GList *file_list,
8369 CajaFileAttributes attributes,
8370 CajaFileListHandle **handle,
8371 CajaFileListCallback callback,
8372 gpointer callback_data)
8373{
8374 GList *l;
8375 FileListReadyData *data;
8376 CajaFile *file = NULL((void*)0);
8377
8378 g_return_if_fail (file_list != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_693
; if (file_list != ((void*)0)) _g_boolean_var_693 = 1; else _g_boolean_var_693
= 0; _g_boolean_var_693; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_list != NULL"
); return; } } while (0)
;
8379
8380 data = file_list_ready_data_new
8381 (file_list, callback, callback_data);
8382
8383 if (handle) {
8384 *handle = (CajaFileListHandle *) data;
8385 }
8386
8387
8388 l = file_list;
8389 while (l != NULL((void*)0)) {
8390 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8391 /* Need to do this here, as the list can be modified by this call */
8392 l = l->next;
8393
8394 if (file)
8395 caja_file_call_when_ready (file,
8396 attributes,
8397 file_list_file_ready_callback,
8398 data);
8399 }
8400}
8401
8402void
8403caja_file_list_cancel_call_when_ready (CajaFileListHandle *handle)
8404{
8405 GList *l;
8406 FileListReadyData *data;
8407
8408 g_return_if_fail (handle != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_694
; if (handle != ((void*)0)) _g_boolean_var_694 = 1; else _g_boolean_var_694
= 0; _g_boolean_var_694; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "handle != NULL")
; return; } } while (0)
;
8409
8410 data = (FileListReadyData *) handle;
8411
8412 l = g_list_find (ready_data_list, data);
8413 if (l != NULL((void*)0)) {
8414 CajaFile *file = NULL((void*)0);
8415
8416 for (l = data->remaining_files; l != NULL((void*)0); l = l->next) {
8417 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8418
8419 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8420 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8421 cancel_call_when_ready, (file, file_list_file_ready_callback, data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
;
8422 }
8423
8424 file_list_ready_data_free (data);
8425 }
8426}
8427
8428static char *
8429try_to_make_utf8 (const char *text, int *length)
8430{
8431 static const char *encodings_to_try[2];
8432 static int n_encodings_to_try = 0;
8433 gsize converted_length;
8434 GError *conversion_error;
8435 char *utf8_text;
8436 int i;
8437
8438 if (n_encodings_to_try == 0) {
8439 const char *charset;
8440 gboolean charset_is_utf8;
8441
8442 charset_is_utf8 = g_get_charset (&charset);
8443 if (!charset_is_utf8) {
8444 encodings_to_try[n_encodings_to_try++] = charset;
8445 }
8446
8447 if (g_ascii_strcasecmp (charset, "ISO-8859-1") != 0) {
8448 encodings_to_try[n_encodings_to_try++] = "ISO-8859-1";
8449 }
8450 }
8451
8452 utf8_text = NULL((void*)0);
8453 for (i = 0; i < n_encodings_to_try; i++) {
8454 conversion_error = NULL((void*)0);
8455 utf8_text = g_convert (text, *length,
8456 "UTF-8", encodings_to_try[i],
8457 NULL((void*)0), &converted_length, &conversion_error);
8458 if (utf8_text != NULL((void*)0)) {
8459 *length = converted_length;
8460 break;
8461 }
8462 g_error_free (conversion_error);
8463 }
8464
8465 return utf8_text;
8466}
8467
8468
8469
8470/* Extract the top left part of the read-in text. */
8471char *
8472caja_extract_top_left_text (const char *text,
8473 gboolean large,
8474 int length)
8475{
8476 GString* buffer;
8477 const gchar *in;
8478 const gchar *end;
8479 int line, i;
8480 gunichar c;
8481 char *text_copy;
8482 const char *utf8_end;
8483 gboolean validated;
8484 int max_bytes, max_lines, max_cols;
8485
8486 if (large) {
8487 max_bytes = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES10000;
8488 max_lines = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES24;
8489 max_cols = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE80;
8490 } else {
8491 max_bytes = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES1024;
8492 max_lines = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES5;
8493 max_cols = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE10;
8494 }
8495
8496
8497
8498 text_copy = NULL((void*)0);
8499 if (text != NULL((void*)0)) {
8500 /* Might be a partial utf8 character at the end if we didn't read whole file */
8501 validated = g_utf8_validate (text, length, &utf8_end);
8502 if (!validated &&
8503 !(length >= max_bytes &&
8504 text + length - utf8_end < 6)) {
8505 text_copy = try_to_make_utf8 (text, &length);
8506 text = text_copy;
8507 } else if (!validated) {
8508 length = utf8_end - text;
8509 }
8510 }
8511
8512 if (text == NULL((void*)0) || length == 0) {
8513 return NULL((void*)0);
8514 }
8515
8516 buffer = g_string_new ("");
8517 end = text + length; in = text;
8518
8519 for (line = 0; line < max_lines; line++) {
8520 /* Extract one line. */
8521 for (i = 0; i < max_cols; ) {
8522 if (*in == '\n') {
8523 break;
8524 }
8525
8526 c = g_utf8_get_char (in);
8527
8528 if (g_unichar_isprint (c)) {
8529 g_string_append_unichar (buffer, c);
8530 i++;
8531 }
8532
8533 in = g_utf8_next_char (in)(char *)((in) + g_utf8_skip[*(const guchar *)(in)]);
8534 if (in == end) {
8535 goto done;
8536 }
8537 }
8538
8539 /* Skip the rest of the line. */
8540 while (*in != '\n') {
8541 if (++in == end) {
8542 goto done;
8543 }
8544 }
8545 if (++in == end) {
8546 goto done;
8547 }
8548
8549 /* Put a new-line separator in. */
8550 g_string_append_c(buffer, '\n')g_string_append_c_inline (buffer, '\n');
8551 }
8552 done:
8553 g_free (text_copy);
8554
8555 return g_string_free(buffer, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((buffer
), ((0))) : g_string_free_and_steal (buffer)) : (g_string_free
) ((buffer), ((0))))
;
8556}
8557
8558static void
8559thumbnail_limit_changed_callback (gpointer user_data)
8560{
8561 g_settings_get (caja_preferences,
8562 CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT"thumbnail-limit",
8563 "t", &cached_thumbnail_limit);
8564
8565 /* Tell the world that icons might have changed. We could invent a narrower-scope
8566 * signal to mean only "thumbnails might have changed" if this ends up being slow
8567 * for some reason.
8568 */
8569 emit_change_signals_for_all_files_in_all_directories ();
8570}
8571
8572static void
8573thumbnail_size_changed_callback (gpointer user_data)
8574{
8575 cached_thumbnail_size = g_settings_get_int (caja_icon_view_preferences, CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE"thumbnail-size");
8576
8577 /* Tell the world that icons might have changed. We could invent a narrower-scope
8578 * signal to mean only "thumbnails might have changed" if this ends up being slow
8579 * for some reason.
8580 */
8581 emit_change_signals_for_all_files_in_all_directories ();
8582}
8583
8584static void
8585show_thumbnails_changed_callback (gpointer user_data)
8586{
8587 show_image_thumbs = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS"show-image-thumbnails");
8588
8589 /* Tell the world that icons might have changed. We could invent a narrower-scope
8590 * signal to mean only "thumbnails might have changed" if this ends up being slow
8591 * for some reason.
8592 */
8593 emit_change_signals_for_all_files_in_all_directories ();
8594}
8595
8596static void
8597mime_type_data_changed_callback (GObject *signaller, gpointer user_data)
8598{
8599 /* Tell the world that icons might have changed. We could invent a narrower-scope
8600 * signal to mean only "thumbnails might have changed" if this ends up being slow
8601 * for some reason.
8602 */
8603 emit_change_signals_for_all_files_in_all_directories ();
8604}
8605
8606static void
8607icon_theme_changed_callback (GtkIconTheme *icon_theme,
8608 gpointer user_data)
8609{
8610 /* Clear all pixmap caches as the icon => pixmap lookup changed */
8611 caja_icon_info_clear_caches ();
8612
8613 /* Tell the world that icons might have changed. We could invent a narrower-scope
8614 * signal to mean only "thumbnails might have changed" if this ends up being slow
8615 * for some reason.
8616 */
8617 emit_change_signals_for_all_files_in_all_directories ();
8618}
8619
8620static void
8621caja_file_class_init (CajaFileClass *class)
8622{
8623 GtkIconTheme *icon_theme;
8624
8625 caja_file_info_getter = caja_file_get_internal;
8626
8627 attribute_name_q = g_quark_from_static_string ("name");
8628 attribute_size_q = g_quark_from_static_string ("size");
8629 attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
8630 attribute_type_q = g_quark_from_static_string ("type");
8631 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
8632 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
8633 attribute_creation_date_q = g_quark_from_static_string ("creation_date");
8634 attribute_date_created_q = g_quark_from_static_string ("date_created");
8635 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
8636 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
8637 attribute_emblems_q = g_quark_from_static_string ("emblems");
8638 attribute_extension_q = g_quark_from_static_string ("extension");
8639 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
8640 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
8641 attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
8642 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
8643 attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
8644 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
8645 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
8646 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
8647 attribute_date_changed_q = g_quark_from_static_string ("date_changed");
8648 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
8649 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
8650 attribute_date_permissions_q = g_quark_from_static_string ("date_permissions");
8651 attribute_permissions_q = g_quark_from_static_string ("permissions");
8652 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
8653 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
8654 attribute_owner_q = g_quark_from_static_string ("owner");
8655 attribute_group_q = g_quark_from_static_string ("group");
8656 attribute_uri_q = g_quark_from_static_string ("uri");
8657 attribute_where_q = g_quark_from_static_string ("where");
8658 attribute_link_target_q = g_quark_from_static_string ("link_target");
8659 attribute_volume_q = g_quark_from_static_string ("volume");
8660 attribute_free_space_q = g_quark_from_static_string ("free_space");
8661
8662 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = finalize;
8663 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->constructor = caja_file_constructor;
8664
8665 signals[CHANGED] =
8666 g_signal_new ("changed",
8667 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8668 G_SIGNAL_RUN_LAST,
8669 G_STRUCT_OFFSET (CajaFileClass, changed)((glong) __builtin_offsetof(CajaFileClass, changed)),
8670 NULL((void*)0), NULL((void*)0),
8671 g_cclosure_marshal_VOID__VOID,
8672 G_TYPE_NONE((GType) ((1) << (2))), 0);
8673
8674 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
8675 g_signal_new ("updated_deep_count_in_progress",
8676 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8677 G_SIGNAL_RUN_LAST,
8678 G_STRUCT_OFFSET (CajaFileClass, updated_deep_count_in_progress)((glong) __builtin_offsetof(CajaFileClass, updated_deep_count_in_progress
))
,
8679 NULL((void*)0), NULL((void*)0),
8680 g_cclosure_marshal_VOID__VOID,
8681 G_TYPE_NONE((GType) ((1) << (2))), 0);
8682
8683 eel_g_settings_add_auto_enum (caja_preferences,
8684 CAJA_PREFERENCES_DATE_FORMAT"date-format",
8685 &date_format_pref);
8686
8687 thumbnail_limit_changed_callback (NULL((void*)0));
8688 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8689 "changed::" CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8690 G_CALLBACK (thumbnail_limit_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8691 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8692 thumbnail_size_changed_callback (NULL((void*)0));
8693 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8694 "changed::" CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8695 G_CALLBACK (thumbnail_size_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8696 NULL)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8697 show_thumbnails_changed_callback (NULL((void*)0));
8698 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8699 "changed::" CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8700 G_CALLBACK (show_thumbnails_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8701 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8702
8703 icon_theme = gtk_icon_theme_get_default ();
8704 g_signal_connect_object (icon_theme,
8705 "changed",
8706 G_CALLBACK (icon_theme_changed_callback)((GCallback) (icon_theme_changed_callback)),
8707 NULL((void*)0), 0);
8708
8709 g_signal_connect (caja_signaller_get_current (),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8710 "mime_data_changed",g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8711 G_CALLBACK (mime_type_data_changed_callback),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8712 NULL)g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
8713}
8714
8715static void
8716caja_file_add_emblem (CajaFile *file,
8717 const char *emblem_name)
8718{
8719 if (file->details->pending_info_providers) {
8720 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
8721 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8722 } else {
8723 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
8724 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8725 }
8726
8727 caja_file_changed (file);
8728}
8729
8730static void
8731caja_file_add_string_attribute (CajaFile *file,
8732 const char *attribute_name,
8733 const char *value)
8734{
8735 if (file->details->pending_info_providers) {
8736 /* Lazily create hashtable */
8737 if (!file->details->pending_extension_attributes) {
8738 file->details->pending_extension_attributes =
8739 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8740 NULL((void*)0),
8741 (GDestroyNotify)g_free);
8742 }
8743 g_hash_table_insert (file->details->pending_extension_attributes,
8744 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8745 g_strdup (value)g_strdup_inline (value));
8746 } else {
8747 if (!file->details->extension_attributes) {
8748 file->details->extension_attributes =
8749 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8750 NULL((void*)0),
8751 (GDestroyNotify)g_free);
8752 }
8753 g_hash_table_insert (file->details->extension_attributes,
8754 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8755 g_strdup (value)g_strdup_inline (value));
8756 }
8757
8758 caja_file_changed (file);
8759}
8760
8761static void
8762caja_file_invalidate_extension_info (CajaFile *file)
8763{
8764 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_EXTENSION_INFO);
8765}
8766
8767void
8768caja_file_info_providers_done (CajaFile *file)
8769{
8770 g_list_free_full (file->details->extension_emblems, g_free);
8771 file->details->extension_emblems = file->details->pending_extension_emblems;
8772 file->details->pending_extension_emblems = NULL((void*)0);
8773
8774 if (file->details->extension_attributes) {
8775 g_hash_table_destroy (file->details->extension_attributes);
8776 }
8777
8778 file->details->extension_attributes = file->details->pending_extension_attributes;
8779 file->details->pending_extension_attributes = NULL((void*)0);
8780
8781 caja_file_changed (file);
8782}
8783
8784static void
8785caja_file_info_iface_init (CajaFileInfoIface *iface)
8786{
8787 iface->is_gone = caja_file_is_gone;
8788 iface->get_name = caja_file_get_name;
8789 iface->get_file_type = caja_file_get_file_type;
8790 iface->get_location = caja_file_get_location;
8791 iface->get_uri = caja_file_get_uri;
8792 iface->get_parent_location = caja_file_get_parent_location;
8793 iface->get_parent_uri = caja_file_get_parent_uri;
8794 iface->get_parent_info = caja_file_get_parent;
8795 iface->get_mount = caja_file_get_mount;
8796 iface->get_uri_scheme = caja_file_get_uri_scheme;
8797 iface->get_activation_uri = caja_file_get_activation_uri;
8798 iface->get_mime_type = caja_file_get_mime_type;
8799 iface->is_mime_type = caja_file_is_mime_type;
8800 iface->is_directory = caja_file_is_directory;
8801 iface->can_write = caja_file_can_write;
8802 iface->add_emblem = caja_file_add_emblem;
8803 iface->get_string_attribute = caja_file_get_string_attribute;
8804 iface->add_string_attribute = caja_file_add_string_attribute;
8805 iface->invalidate_extension_info = caja_file_invalidate_extension_info;
8806}
8807
8808#if !defined (CAJA_OMIT_SELF_CHECK)
8809
8810void
8811caja_self_check_file (void)
8812{
8813 CajaFile *file_1;
8814 CajaFile *file_2;
8815 GList *list;
8816
8817 /* refcount checks */
8818
8819 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8819); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8820
8821 file_1 = caja_file_get_by_uri ("file:///home/");
8822
8823 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8823); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8824 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1->details->directory)))))->ref_count"
, "caja-file.c", 8824); eel_check_integer_result (((((GObject
*) (void *) ((file_1->details->directory)))))->ref_count
, 1); } while (0)
;
8825 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 1)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8825); eel_check_integer_result (caja_directory_number_outstanding
(), 1); } while (0)
;
8826
8827 caja_file_unref (file_1);
8828
8829 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8829); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8830
8831 file_1 = caja_file_get_by_uri ("file:///etc");
8832 file_2 = caja_file_get_by_uri ("file:///usr");
8833
8834 list = NULL((void*)0);
8835 list = g_list_prepend (list, file_1);
8836 list = g_list_prepend (list, file_2);
8837
8838 caja_file_list_ref (list);
8839
8840 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8840); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 2); } while (0)
;
8841 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8841); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 2); } while (0)
;
8842
8843 caja_file_list_unref (list);
8844
8845 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8845); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8846 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8846); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8847
8848 caja_file_list_free (list);
8849
8850 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8850); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8851
8852
8853 /* name checks */
8854 file_1 = caja_file_get_by_uri ("file:///home/");
8855
8856 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8856); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8857
8858 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home/") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home/\") == file_1"
, "caja-file.c", 8858); eel_check_boolean_result (caja_file_get_by_uri
("file:///home/") == file_1, (!(0))); } while (0)
;
8859 caja_file_unref (file_1);
8860
8861 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home\") == file_1"
, "caja-file.c", 8861); eel_check_boolean_result (caja_file_get_by_uri
("file:///home") == file_1, (!(0))); } while (0)
;
8862 caja_file_unref (file_1);
8863
8864 caja_file_unref (file_1);
8865
8866 file_1 = caja_file_get_by_uri ("file:///home");
8867 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8867); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8868 caja_file_unref (file_1);
8869
8870#if 0
8871 /* ALEX: I removed this, because it was breaking distchecks.
8872 * It used to work, but when canonical uris changed from
8873 * foo: to foo:/// it broke. I don't expect it to matter
8874 * in real life */
8875 file_1 = caja_file_get_by_uri (":");
8876 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), ":")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8876); eel_check_string_result (caja_file_get_name (file_1)
, ":"); } while (0)
;
8877 caja_file_unref (file_1);
8878#endif
8879
8880 file_1 = caja_file_get_by_uri ("eazel:");
8881 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "eazel")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8881); eel_check_string_result (caja_file_get_name (file_1)
, "eazel"); } while (0)
;
8882 caja_file_unref (file_1);
8883
8884 /* sorting */
8885 file_1 = caja_file_get_by_uri ("file:///etc");
8886 file_2 = caja_file_get_by_uri ("file:///usr");
8887
8888 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8888); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8889 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8889); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8890
8891 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) < 0"
, "caja-file.c", 8891); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) <
0, (!(0))); } while (0)
;
8892 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) > 0"
, "caja-file.c", 8892); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) > 0, (!(0))); } while (0)
;
8893 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) == 0"
, "caja-file.c", 8893); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) ==
0, (!(0))); } while (0)
;
8894 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)) == 0"
, "caja-file.c", 8894); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)
) == 0, (!(0))); } while (0)
;
8895 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) == 0"
, "caja-file.c", 8895); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) == 0, (!(0))); } while (0)
;
8896 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(0))) == 0"
, "caja-file.c", 8896); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(
0))) == 0, (!(0))); } while (0)
;
8897
8898 caja_file_unref (file_1);
8899 caja_file_unref (file_2);
8900}
8901
8902#endif /* !CAJA_OMIT_SELF_CHECK */
diff --git a/2024-07-29-023715-6438-1/report-a0fbb3.html b/2024-07-29-023715-6438-1/report-a0fbb3.html new file mode 100644 index 000000000..69ef3527a --- /dev/null +++ b/2024-07-29-023715-6438-1/report-a0fbb3.html @@ -0,0 +1,909 @@ + + + +eel-vfs-extensions.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-vfs-extensions.c
Warning:line 136, column 9
Access of 'char' element in the region at index -1
+ +

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 eel-vfs-extensions.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-vfs-extensions.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* eel-vfs-extensions.c - mate-vfs extensions. Its likely some of these will
4 be part of mate-vfs in the future.
5
6 Copyright (C) 1999, 2000 Eazel, Inc.
7
8 The Mate Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 The Mate 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 the Mate Library; see the file COPYING.LIB. If not,
20 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 Authors: Darin Adler <darin@eazel.com>
24 Pavel Cisler <pavel@eazel.com>
25 Mike Fleming <mfleming@eazel.com>
26 John Sullivan <sullivan@eazel.com>
27*/
28
29#include <config.h>
30#include "eel-vfs-extensions.h"
31#include "eel-glib-extensions.h"
32#include "eel-lib-self-check-functions.h"
33#include <glib.h>
34#include <glib/gi18n-lib.h>
35#include <gio/gio.h>
36
37#include "eel-string.h"
38
39#include <string.h>
40#include <stdlib.h>
41
42gboolean
43eel_uri_is_trash (const char *uri)
44{
45 return eel_istr_has_prefix (uri, "trash:");
46}
47
48gboolean
49eel_uri_is_search (const char *uri)
50{
51 return eel_istr_has_prefix (uri, EEL_SEARCH_URI"x-caja-search:");
52}
53
54gboolean
55eel_uri_is_desktop (const char *uri)
56{
57 return eel_istr_has_prefix (uri, EEL_DESKTOP_URI"x-caja-desktop:");
58}
59
60char *
61eel_make_valid_utf8 (const char *name)
62{
63 GString *string;
64 const char *remainder, *invalid;
65 int remaining_bytes;
66
67 string = NULL((void*)0);
68 remainder = name;
69 remaining_bytes = strlen (name);
70
71 while (remaining_bytes != 0)
72 {
73 int valid_bytes;
74
75 if (g_utf8_validate (remainder, remaining_bytes, &invalid))
76 {
77 break;
78 }
79 valid_bytes = invalid - remainder;
80
81 if (string == NULL((void*)0))
82 {
83 string = g_string_sized_new (remaining_bytes);
84 }
85 g_string_append_len (string, remainder, valid_bytes)g_string_append_len_inline (string, remainder, valid_bytes);
86 g_string_append_c (string, '?')g_string_append_c_inline (string, '?');
87
88 remaining_bytes -= valid_bytes + 1;
89 remainder = invalid + 1;
90 }
91
92 if (string == NULL((void*)0))
93 {
94 return g_strdup (name)g_strdup_inline (name);
95 }
96
97 g_string_append (string, remainder)(__builtin_constant_p (remainder) ? __extension__ ({ const char
* const __val = (remainder); g_string_append_len_inline (string
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (__val != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
string, remainder, (gssize) -1))
;
98 g_string_append (string, _(" (invalid Unicode)"))(__builtin_constant_p (((char *) g_dgettext ("caja", " (invalid Unicode)"
))) ? __extension__ ({ const char * const __val = (((char *) g_dgettext
("caja", " (invalid Unicode)"))); g_string_append_len_inline
(string, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (__val != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
string, ((char *) g_dgettext ("caja", " (invalid Unicode)")),
(gssize) -1))
;
99 g_assert (g_utf8_validate (string->str, -1, NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (g_utf8_validate (string->str, -1, ((void*)0))) _g_boolean_var_24
= 1; else _g_boolean_var_24 = 0; _g_boolean_var_24; }), 1)) ;
else g_assertion_message_expr ("Eel", "eel-vfs-extensions.c"
, 99, ((const char*) (__func__)), "g_utf8_validate (string->str, -1, NULL)"
); } while (0)
;
100
101 return g_string_free (string, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((string
), ((0))) : g_string_free_and_steal (string)) : (g_string_free
) ((string), ((0))))
;
102}
103
104char *
105eel_filename_strip_extension (const char * filename_with_extension)
106{
107 char *filename, *end, *end2;
108
109 if (filename_with_extension
13.1
'filename_with_extension' is not equal to NULL
== NULL((void*)0))
14
Taking false branch
110 {
111 return NULL((void*)0);
112 }
113
114 filename = g_strdup (filename_with_extension)g_strdup_inline (filename_with_extension);
115
116 end = strrchr (filename, '.');
117
118 if (end && end != filename)
15
Assuming 'end' is non-null
16
Assuming 'end' is not equal to 'filename'
119 {
120 if (strcmp (end, ".gz") == 0 ||
121 strcmp (end, ".bz2") == 0 ||
122 strcmp (end, ".sit") == 0 ||
123 strcmp (end, ".Z") == 0)
124 {
125 end2 = end - 1;
126 while (end2 > filename &&
17
Assuming 'end2' is <= 'filename'
127 *end2 != '.')
128 {
129 end2--;
130 }
131 if (end2 != filename)
18
Assuming 'end2' is not equal to 'filename'
19
Taking true branch
132 {
133 end = end2;
134 }
135 }
136 *end = '\0';
20
Access of 'char' element in the region at index -1
137 }
138
139 return filename;
140}
141
142void
143eel_filename_get_rename_region (const char *filename,
144 int *start_offset,
145 int *end_offset)
146{
147 char *filename_without_extension;
148
149 g_return_if_fail (start_offset != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (start_offset != ((void*)0)) _g_boolean_var_25 = 1; else
_g_boolean_var_25 = 0; _g_boolean_var_25; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"start_offset != NULL"); return; } } while (0)
;
1
Assuming 'start_offset' is not equal to null
2
Taking true branch
3
Taking true branch
4
Loop condition is false. Exiting loop
150 g_return_if_fail (end_offset != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if (end_offset != ((void*)0)) _g_boolean_var_26 = 1; else _g_boolean_var_26
= 0; _g_boolean_var_26; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "end_offset != NULL"); return
; } } while (0)
;
5
Assuming 'end_offset' is not equal to null
6
Taking true branch
7
Taking true branch
8
Loop condition is false. Exiting loop
151
152 *start_offset = 0;
153 *end_offset = 0;
154
155 g_return_if_fail (filename != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if (filename != ((void*)0)) _g_boolean_var_27 = 1; else _g_boolean_var_27
= 0; _g_boolean_var_27; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "filename != NULL"); return
; } } while (0)
;
9
Assuming 'filename' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
156
157 filename_without_extension = eel_filename_strip_extension (filename);
13
Calling 'eel_filename_strip_extension'
158 *end_offset = g_utf8_strlen (filename_without_extension, -1);
159
160 g_free (filename_without_extension);
161}
diff --git a/2024-07-29-023715-6438-1/report-a6010e.html b/2024-07-29-023715-6438-1/report-a6010e.html new file mode 100644 index 000000000..097cf569f --- /dev/null +++ b/2024-07-29-023715-6438-1/report-a6010e.html @@ -0,0 +1,980 @@ + + + +test-eel-image-table.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:test/test-eel-image-table.c
Warning:line 193, column 9
This statement is never executed
+ +

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 test-eel-image-table.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 -fdebug-compilation-dir=/rootdir/test -fcoverage-compilation-dir=/rootdir/test -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D VERSION="1.26.4" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local//locale" -D PIXBUFDIR="/usr/local/share/pixmaps" -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c test-eel-image-table.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <stdlib.h>
2#include <gtk/gtk.h>
3
4#include <eel/eel-image-table.h>
5
6#include "test.h"
7
8static const char pixbuf_name[] = PIXBUFDIR"/usr/local/share/pixmaps" "/mate-logo-white.svg";
9
10static const char *names[] =
11{
12 "Tomaso Albinoni",
13 "Isaac Albéniz",
14 "Georges Bizet",
15 "Luigi Boccherini",
16 "Alexander Borodin",
17 "Johannes Brahms",
18 "Max Bruch",
19 "Anton Bruckner",
20 "Frédéric Chopin",
21 "Aaron Copland",
22 "John Corigliano",
23 "Claude Debussy",
24 "Léo Delibes",
25 "Antonín Dvorák",
26 "Edward Elgar",
27 "Manuel de Falla",
28 "George Gershwin",
29 "Alexander Glazunov",
30 "Mikhail Glinka",
31 "Enrique Granados",
32 "Edvard Grieg",
33 "Joseph Haydn",
34 "Scott Joplin",
35 "Franz Liszt",
36 "Gustav Mahler",
37 "Igor Markevitch",
38 "Felix Mendelssohn",
39 "Modest Mussorgsky",
40 "Sergei Prokofiev",
41 "Giacomo Puccini",
42 "Maurice Ravel",
43 "Ottorino Respighi",
44 "Joaquin Rodrigo",
45 "Gioachino Rossini",
46 "Domenico Scarlatti",
47 "Franz Schubert",
48 "Robert Schumann",
49 "Jean Sibelius",
50 "Bedrich Smetana",
51 "Johann Strauss",
52 "Igor Stravinsky",
53 "Giuseppe Verdi",
54 "Antonio Vivaldi",
55 "Richard Wagner",
56};
57
58static GtkWidget *
59labeled_image_new (const char *text,
60 const char *icon_name)
61{
62 GtkWidget *image;
63 GdkPixbuf *pixbuf = NULL((void*)0);
64
65 if (icon_name) {
66 float sizes[] = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
67 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0 };
68 pixbuf = test_pixbuf_new_named (icon_name, sizes[random () % G_N_ELEMENTS (sizes)(sizeof (sizes) / sizeof ((sizes)[0]))]);
69 }
70
71 image = eel_labeled_image_new (text, pixbuf);
72
73 eel_gdk_pixbuf_unref_if_not_null (pixbuf);
74
75 return image;
76}
77
78
79static void
80image_table_child_enter_callback (GtkWidget *image_table,
81 GtkWidget *item,
82 gpointer callback_data)
83{
84#if 0
85 char *text;
86
87 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_34 = 1; else _g_boolean_var_34 = 0; _g_boolean_var_34
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
88 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_35
= 1; else _g_boolean_var_35 = 0; _g_boolean_var_35; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
89
90 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
91
92 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
93#endif
94}
95
96static void
97image_table_child_leave_callback (GtkWidget *image_table,
98 GtkWidget *item,
99 gpointer callback_data)
100{
101#if 0
102 char *text;
103
104 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_36 = 1; else _g_boolean_var_36 = 0; _g_boolean_var_36
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
105 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_37
= 1; else _g_boolean_var_37 = 0; _g_boolean_var_37; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
106
107 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
108
109 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
110#endif
111}
112
113static void
114image_table_child_pressed_callback (GtkWidget *image_table,
115 GtkWidget *item,
116 gpointer callback_data)
117{
118 char *text;
119
120 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_38 = 1; else _g_boolean_var_38 = 0; _g_boolean_var_38
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
121 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_39
= 1; else _g_boolean_var_39 = 0; _g_boolean_var_39; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
122
123 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
124
125 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
126}
127
128static void
129image_table_child_released_callback (GtkWidget *image_table,
130 GtkWidget *item,
131 gpointer callback_data)
132{
133 char *text;
134
135 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_40
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_40 = 1; else _g_boolean_var_40 = 0; _g_boolean_var_40
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
136 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_41
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_41
= 1; else _g_boolean_var_41 = 0; _g_boolean_var_41; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
137
138 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
139
140 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
141}
142
143static void
144image_table_child_clicked_callback (GtkWidget *image_table,
145 GtkWidget *item,
146 gpointer callback_data)
147{
148 char *text;
149
150 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_42
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_42 = 1; else _g_boolean_var_42 = 0; _g_boolean_var_42
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
151 g_return_if_fail (EEL_IS_LABELED_IMAGE (item))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_43
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((item)); GType __t = (eel_labeled_image_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_43
= 1; else _g_boolean_var_43 = 0; _g_boolean_var_43; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "EEL_IS_LABELED_IMAGE (item)"); return; } } while
(0)
;
152
153 text = eel_labeled_image_get_text (EEL_LABELED_IMAGE (item)((((EelLabeledImage*) (void *) ((item))))));
154
155 g_print ("%s(%s)\n", G_STRFUNC((const char*) (__func__)), text);
156}
157
158static int
159foo_timeout (gpointer callback_data)
160{
161 static int recursion_count = 0;
162 g_return_val_if_fail (GTK_IS_WINDOW (callback_data), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_44
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = ((gtk_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_44 = 1; else _g_boolean_var_44 = 0; _g_boolean_var_44
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "GTK_IS_WINDOW (callback_data)")
; return ((0)); } } while (0)
;
163
164 recursion_count++;
165
166 g_print ("%s(%d)\n", G_STRFUNC((const char*) (__func__)), recursion_count);
167 gtk_widget_queue_resize (GTK_WIDGET (callback_data)((((GtkWidget*) (void *) ((callback_data))))));
168
169 recursion_count--;
170
171 return FALSE(0);
172}
173
174static void
175image_table_size_allocate (GtkWidget *image_table,
176 GtkAllocation *allocation,
177 gpointer callback_data)
178{
179 static int recursion_count = 0;
180 GtkAllocation w_allocation;
181
182 g_return_if_fail (EEL_IS_IMAGE_TABLE (image_table))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_45
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_table)); GType __t = (eel_image_table_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_45 = 1; else _g_boolean_var_45 = 0; _g_boolean_var_45
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "EEL_IS_IMAGE_TABLE (image_table)"
); return; } } while (0)
;
183 g_return_if_fail (allocation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_46
; if (allocation != ((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__)), "allocation != NULL"
); return; } } while (0)
;
184 g_return_if_fail (GTK_IS_WINDOW (callback_data))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_47
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = ((gtk_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_47 = 1; else _g_boolean_var_47 = 0; _g_boolean_var_47
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "GTK_IS_WINDOW (callback_data)")
; return; } } while (0)
;
185
186 recursion_count++;
187
188 if (0) g_timeout_add (0, foo_timeout, callback_data);
189
190 /*gtk_widget_queue_resize (GTK_WIDGET (callback_data));*/
191
192 gtk_widget_get_allocation (GTK_WIDGET (image_table)((((GtkWidget*) (void *) ((image_table))))), &w_allocation);
193 if (0) gtk_widget_size_allocate (GTK_WIDGET (image_table)((((GtkWidget*) (void *) ((image_table))))),
This statement is never executed
194 &w_allocation);
195
196 g_print ("%s(%d)\n", G_STRFUNC((const char*) (__func__)), recursion_count);
197
198 recursion_count--;
199}
200
201static GtkWidget *
202image_table_new_scrolled (void)
203{
204 GtkWidget *scrolled;
205 GtkWidget *viewport;
206 GtkWidget *window;
207 GtkWidget *image_table;
208 int i;
209
210 window = test_window_new ("Image Table Test", 10);
211
212 gtk_window_set_default_size (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), 400, 300);
213
214 /* Scrolled window */
215 scrolled = gtk_scrolled_window_new (NULL((void*)0), NULL((void*)0));
216 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled)((((GtkScrolledWindow*) (void *) ((scrolled))))),
217 GTK_POLICY_NEVER,
218 GTK_POLICY_AUTOMATIC);
219 gtk_container_add (GTK_CONTAINER (window)((((GtkContainer*) (void *) ((window))))), scrolled);
220
221 /* Viewport */
222 viewport = gtk_viewport_new (NULL((void*)0), NULL((void*)0));
223 gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport)((((GtkViewport*) (void *) ((viewport))))), GTK_SHADOW_OUT);
224 gtk_container_add (GTK_CONTAINER (scrolled)((((GtkContainer*) (void *) ((scrolled))))), viewport);
225
226 image_table = eel_image_table_new (FALSE(0));
227
228 if (0) g_signal_connect (image_table,g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
229 "size_allocate",g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
230 G_CALLBACK (image_table_size_allocate),g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
231 window)g_signal_connect_data ((image_table), ("size_allocate"), (((GCallback
) (image_table_size_allocate))), (window), ((void*)0), (GConnectFlags
) 0)
;
232
233 eel_wrap_table_set_x_justification (EEL_WRAP_TABLE (image_table)((((EelWrapTable*) (void *) ((image_table))))),
234 EEL_JUSTIFICATION_MIDDLE);
235 eel_wrap_table_set_y_justification (EEL_WRAP_TABLE (image_table)((((EelWrapTable*) (void *) ((image_table))))),
236 EEL_JUSTIFICATION_END);
237
238 gtk_container_add (GTK_CONTAINER (viewport)((((GtkContainer*) (void *) ((viewport))))), image_table);
239
240 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
241 "child_enter",g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
242 G_CALLBACK (image_table_child_enter_callback),g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
243 NULL)g_signal_connect_data ((image_table), ("child_enter"), (((GCallback
) (image_table_child_enter_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
;
244
245 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
246 "child_leave",g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
247 G_CALLBACK (image_table_child_leave_callback),g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
248 NULL)g_signal_connect_data ((image_table), ("child_leave"), (((GCallback
) (image_table_child_leave_callback))), (((void*)0)), ((void*
)0), (GConnectFlags) 0)
;
249
250 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
251 "child_pressed",g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
252 G_CALLBACK (image_table_child_pressed_callback),g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
253 NULL)g_signal_connect_data ((image_table), ("child_pressed"), (((GCallback
) (image_table_child_pressed_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
;
254
255 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
256 "child_released",g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
257 G_CALLBACK (image_table_child_released_callback),g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
258 NULL)g_signal_connect_data ((image_table), ("child_released"), (((
GCallback) (image_table_child_released_callback))), (((void*)
0)), ((void*)0), (GConnectFlags) 0)
;
259
260 g_signal_connect (image_table,g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
261 "child_clicked",g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
262 G_CALLBACK (image_table_child_clicked_callback),g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
263 NULL)g_signal_connect_data ((image_table), ("child_clicked"), (((GCallback
) (image_table_child_clicked_callback))), (((void*)0)), ((void
*)0), (GConnectFlags) 0)
;
264
265 for (i = 0; i < 100; i++) {
266 char *text;
267 GtkWidget *image;
268
269 text = g_strdup_printf ("%s %d",
270 names[random () % G_N_ELEMENTS (names)(sizeof (names) / sizeof ((names)[0]))],
271 i);
272 image = labeled_image_new (text, pixbuf_name);
273 g_free (text);
274
275 gtk_container_add (GTK_CONTAINER (image_table)((((GtkContainer*) (void *) ((image_table))))), image);
276 gtk_widget_show (image);
277 }
278
279 gtk_widget_show (viewport);
280 gtk_widget_show (scrolled);
281 gtk_widget_show (image_table);
282
283 return window;
284}
285
286int
287main (int argc, char* argv[])
288{
289 GtkWidget *window = NULL((void*)0);
290
291 test_init (&argc, &argv);
292
293 window = image_table_new_scrolled ();
294
295 gtk_widget_show (window);
296
297 gtk_main ();
298
299 return 0;
300}
diff --git a/2024-07-29-023715-6438-1/report-a7c48d.html b/2024-07-29-023715-6438-1/report-a7c48d.html new file mode 100644 index 000000000..54f5ac671 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-a7c48d.html @@ -0,0 +1,933 @@ + + + +caja-extensions.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-extensions.c
Warning:line 237, column 44
Access to field 'filename' results in a dereference of a null pointer (loaded from variable 'ext')
+ +

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 caja-extensions.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-extensions.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * caja-extension.c - extension management functions
3 *
4 * Copyright (C) 2012-2021 The MATE developers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * Author: Alexander van der Meij <alexandervdm@gliese.me>
22 */
23
24#include "caja-extensions.h"
25
26#include "caja-global-preferences.h"
27#include "caja-module.h"
28#include "caja-debug-log.h"
29
30#include <string.h>
31
32#define CAJA_EXTENSION_GROUP"Caja Extension" "Caja Extension"
33
34static GList *caja_extensions = NULL((void*)0);
35
36
37static Extension *
38extension_new (gchar *filename, gboolean state, gboolean python, GObject *module)
39{
40 GError *error = NULL((void*)0);
41 Extension *ext;
42 GKeyFile *extension_file;
43 gchar *extension_filename;
44
45 ext = g_new0 (Extension, 1)(Extension *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Extension); 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
; }))
;
46 ext->filename = filename;
47 ext->name = NULL((void*)0);
48 ext->description = NULL((void*)0);
49 ext->author = NULL((void*)0);
50 ext->copyright = NULL((void*)0);
51 ext->version = NULL((void*)0);
52 ext->website = NULL((void*)0);
53 ext->state = state;
54 ext->module = module;
55
56 extension_file = g_key_file_new ();
57 extension_filename = g_strdup_printf(CAJA_DATADIR"/usr/local/share/caja" "/extensions/%s.caja-extension", filename);
58 if (g_key_file_load_from_file (extension_file, extension_filename, G_KEY_FILE_NONE, &error))
59 {
60 ext->name = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Name", NULL((void*)0), NULL((void*)0));
61 ext->description = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Description", NULL((void*)0), NULL((void*)0));
62 ext->icon = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Icon", NULL((void*)0));
63 ext->author = g_key_file_get_string_list (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Author", NULL((void*)0), NULL((void*)0));
64 ext->copyright = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Copyright", NULL((void*)0), NULL((void*)0));
65 ext->version = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Version", NULL((void*)0));
66 ext->website = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP"Caja Extension", "Website", NULL((void*)0));
67 g_key_file_free (extension_file);
68 }
69 else
70 {
71 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER", "Error loading keys from file: %s\n", error->message);
72 g_error_free (error);
73 }
74 g_free (extension_filename);
75
76 if (python)
77 {
78 ext->name = g_strconcat("Python: ", filename, NULL((void*)0));
79 ext->description = "Python-caja extension";
80 }
81
82 return ext;
83}
84
85/* functions related to persistent configuration through gsettings: */
86
87static gboolean
88gsettings_key_has_value (const gchar *value)
89{
90 gchar **list;
91 gint i;
92
93 list = g_settings_get_strv (caja_extension_preferences,
94 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions");
95
96 if (list != NULL((void*)0))
97 {
98 for (i = 0; list[i]; i++)
99 {
100 if (g_ascii_strcasecmp (value, list[i]) == 0)
101 {
102 g_strfreev (list);
103 return TRUE(!(0));
104 }
105 }
106 }
107 g_strfreev (list);
108 return FALSE(0);
109}
110
111static gboolean
112gsettings_append_to_list (const char *value)
113{
114 gchar **current;
115 gchar **new;
116 gint size;
117 gboolean retval;
118
119 current = g_settings_get_strv (caja_extension_preferences,
120 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions");
121
122 for (size = 0; current[size] != NULL((void*)0); size++);
123
124 size += 1;
125 size += 1;
126
127 new = g_realloc_n (current, size, sizeof (gchar *));
128
129 new[size - 2] = g_strdup (value)g_strdup_inline (value);
130 new[size - 1] = NULL((void*)0);
131
132 retval = g_settings_set_strv (caja_extension_preferences,
133 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions",
134 (const gchar **) new);
135
136 g_strfreev (new);
137 return retval;
138}
139
140static gboolean
141gsettings_remove_from_list (const char *value)
142{
143 gchar **current;
144 GArray *array;
145 gint i;
146 gboolean retval;
147
148 current = g_settings_get_strv (caja_extension_preferences,
149 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions");
150
151 array = g_array_new (TRUE(!(0)), TRUE(!(0)), sizeof (gchar *));
152
153 for (i = 0; current[i] != NULL((void*)0); i++)
154 {
155 if (g_strcmp0 (current[i], value) != 0)
156 array = g_array_append_val (array, current[i])g_array_append_vals (array, &(current[i]), 1);
157 }
158
159 retval = g_settings_set_strv (caja_extension_preferences,
160 CAJA_PREFERENCES_DISABLED_EXTENSIONS"disabled-extensions",
161 (const gchar **) array->data);
162
163 g_strfreev (current);
164 g_array_free (array, TRUE(!(0)));
165 return retval;
166}
167
168/* functions related to the extension management */
169
170static gboolean
171caja_extension_get_state (const gchar *extname)
172{
173 return !gsettings_key_has_value (extname);
174}
175
176GList *
177caja_extensions_get_for_type (GType type)
178{
179 GList *l;
180 GList *ret = NULL((void*)0);
181
182 for (l = caja_extensions; l != NULL((void*)0); l = l->next)
183 {
184 Extension *ext = l->data;
185 ext->state = caja_extension_get_state (ext->filename);
186 if (ext->state) // only load enabled extensions
187 {
188 if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (ext->module), type)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
((((GObject*) (void *) ((ext->module)))))); GType __t = (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; })))
)
189 {
190 g_object_ref (ext->module)((__typeof__ (ext->module)) (g_object_ref) (ext->module
))
;
191 ret = g_list_prepend (ret, ext->module);
192 }
193 }
194 }
195
196 return ret;
197}
198
199GList *
200caja_extensions_get_list (void)
201{
202 return caja_extensions;
203}
204
205void
206caja_extension_register (gchar *filename, GObject *module)
207{
208 gboolean ext_state = TRUE(!(0)); // new extensions are enabled by default.
209 gboolean ext_python = FALSE(0);
210 gchar *ext_filename;
211
212 ext_filename = g_strndup (filename, strlen(filename) - 3);
213 ext_state = caja_extension_get_state (ext_filename);
214
215 if (g_str_has_suffix (filename, ".py")(__builtin_constant_p (".py")? __extension__ ({ const char * const
__str = (filename); const char * const __suffix = (".py"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (__str == ((void*)0) || __suffix == ((void*)0)) _g_boolean_var_16
= 1; else _g_boolean_var_16 = 0; _g_boolean_var_16; }), 0)) __result
= (g_str_has_suffix) (__str, __suffix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __suffix_len =
strlen (((__suffix) + !(__suffix))); if (__str_len >= __suffix_len
) __result = memcmp (__str + __str_len - __suffix_len, ((__suffix
) + !(__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".py") )
) {
216 ext_python = TRUE(!(0));
217 }
218
219 Extension *ext = extension_new (ext_filename, ext_state, ext_python, module);
220 caja_extensions = g_list_append (caja_extensions, ext);
221}
222
223gboolean
224caja_extension_set_state (Extension *ext, gboolean new_state)
225{
226 if (ext)
1
Assuming 'ext' is null
2
Taking false branch
227 {
228 g_return_val_if_fail (ext->state != new_state, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (ext->state != new_state) _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__
)), "ext->state != new_state"); return ((0)); } } while (0
)
;
229 ext->state = new_state;
230 }
231
232 gboolean retval;
233 if (new_state) {
3
Assuming 'new_state' is 0
4
Taking false branch
234 retval = gsettings_remove_from_list (ext->filename);
235 }
236 else {
237 retval = gsettings_append_to_list (ext->filename);
5
Access to field 'filename' results in a dereference of a null pointer (loaded from variable 'ext')
238 }
239
240 g_return_val_if_fail (retval == TRUE, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (retval == (!(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__)), "retval == TRUE")
; return ((0)); } } while (0)
;
241 return TRUE(!(0));
242}
243
diff --git a/2024-07-29-023715-6438-1/report-b8f564.html b/2024-07-29-023715-6438-1/report-b8f564.html new file mode 100644 index 000000000..32c9b9cf1 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-b8f564.html @@ -0,0 +1,2089 @@ + + + +eggsmclient-xsmp.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File: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 -fdebug-compilation-dir=/rootdir/mate-submodules/libegg -fcoverage-compilation-dir=/rootdir/mate-submodules/libegg -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I ../.. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/freetype2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/uuid -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -D WITH_GZFILEOP -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/gio-unix-2.0 -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/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/freetype2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/uuid -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -D WITH_GZFILEOP -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/gio-unix-2.0 -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-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 GType 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_pointer (
&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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (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/2024-07-29-023715-6438-1/report-be2b10.html b/2024-07-29-023715-6438-1/report-be2b10.html new file mode 100644 index 000000000..e8a4a1bc4 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-be2b10.html @@ -0,0 +1,7490 @@ + + + +caja-file-operations.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file-operations.c
Warning:line 2914, column 3
Value stored to 'response' 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 caja-file-operations.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file-operations.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* caja-file-operations.c - Caja file operations.
4
5 Copyright (C) 1999, 2000 Free Software Foundation
6 Copyright (C) 2000, 2001 Eazel, Inc.
7 Copyright (C) 2007 Red Hat, Inc.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (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 GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public
20 License along with this program; if not, write to the
21 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24 Authors: Alexander Larsson <alexl@redhat.com>
25 Ettore Perazzoli <ettore@gnu.org>
26 Pavel Cisler <pavel@eazel.com>
27 */
28
29#include <config.h>
30#include <string.h>
31#include <stdio.h>
32#include <stdarg.h>
33#include <locale.h>
34#include <math.h>
35#include <unistd.h>
36#include <sys/types.h>
37#include <stdlib.h>
38#include <glib/gi18n.h>
39#include <glib/gstdio.h>
40#include <gdk/gdk.h>
41#include <gdk/gdkx.h>
42#include <gtk/gtk.h>
43#include <gio/gio.h>
44#include <glib.h>
45#include <libnotify/notify.h>
46
47#include <eel/eel-glib-extensions.h>
48#include <eel/eel-gtk-extensions.h>
49#include <eel/eel-stock-dialogs.h>
50#include <eel/eel-vfs-extensions.h>
51
52#include "caja-file-operations.h"
53#include "caja-debug-log.h"
54#include "caja-file-changes-queue.h"
55#include "caja-lib-self-check-functions.h"
56#include "caja-progress-info.h"
57#include "caja-file-changes-queue.h"
58#include "caja-file-private.h"
59#include "caja-desktop-icon-file.h"
60#include "caja-desktop-link-monitor.h"
61#include "caja-global-preferences.h"
62#include "caja-link.h"
63#include "caja-autorun.h"
64#include "caja-trash-monitor.h"
65#include "caja-file-utilities.h"
66#include "caja-file-conflict-dialog.h"
67#include "caja-undostack-manager.h"
68#include "caja-metadata.h"
69
70/* TODO: TESTING!!! */
71
72typedef struct {
73 GIOSchedulerJob *io_job;
74 GTimer *time;
75 GtkWindow *parent_window;
76 int screen_num;
77 int inhibit_cookie;
78 CajaProgressInfo *progress;
79 GCancellable *cancellable;
80 GHashTable *skip_files;
81 GHashTable *skip_readdir_error;
82 gboolean skip_all_error;
83 gboolean skip_all_conflict;
84 gboolean merge_all;
85 gboolean replace_all;
86 gboolean delete_all;
87 CajaUndoStackActionData* undo_redo_data;
88} CommonJob;
89
90typedef struct {
91 CommonJob common;
92 gboolean is_move;
93 GList *files;
94 GFile *destination;
95 GFile *desktop_location;
96 GdkPoint *icon_positions;
97 int n_icon_positions;
98 GHashTable *debuting_files;
99 CajaCopyCallback done_callback;
100 gpointer done_callback_data;
101} CopyMoveJob;
102
103typedef struct {
104 CommonJob common;
105 GList *files;
106 gboolean try_trash;
107 gboolean user_cancel;
108 CajaDeleteCallback done_callback;
109 gpointer done_callback_data;
110} DeleteJob;
111
112typedef struct {
113 CommonJob common;
114 GFile *dest_dir;
115 char *filename;
116 gboolean make_dir;
117 GFile *src;
118 char *src_data;
119 int length;
120 GdkPoint position;
121 gboolean has_position;
122 GFile *created_file;
123 CajaCreateCallback done_callback;
124 gpointer done_callback_data;
125} CreateJob;
126
127
128typedef struct {
129 CommonJob common;
130 GList *trash_dirs;
131 gboolean should_confirm;
132 CajaOpCallback done_callback;
133 gpointer done_callback_data;
134} EmptyTrashJob;
135
136typedef struct {
137 CommonJob common;
138 GFile *file;
139 gboolean interactive;
140 CajaOpCallback done_callback;
141 gpointer done_callback_data;
142} MarkTrustedJob;
143
144typedef struct {
145 CommonJob common;
146 GFile *file;
147 CajaOpCallback done_callback;
148 gpointer done_callback_data;
149 guint32 file_permissions;
150 guint32 file_mask;
151 guint32 dir_permissions;
152 guint32 dir_mask;
153} SetPermissionsJob;
154
155typedef enum {
156 OP_KIND_COPY,
157 OP_KIND_MOVE,
158 OP_KIND_DELETE,
159 OP_KIND_TRASH
160} OpKind;
161
162typedef struct {
163 int num_files;
164 goffset num_bytes;
165 int num_files_since_progress;
166 OpKind op;
167} SourceInfo;
168
169typedef struct {
170 int num_files;
171 goffset num_bytes;
172 OpKind op;
173 guint64 last_report_time;
174 int last_reported_files_left;
175} TransferInfo;
176
177#define SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15 15
178#define NSEC_PER_MICROSEC1000 1000
179
180#define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50 50
181
182#define IS_IO_ERROR(__error, KIND)(((__error)->domain == g_io_error_quark() && (__error
)->code == G_IO_ERROR_KIND))
(((__error)->domain == G_IO_ERRORg_io_error_quark() && (__error)->code == G_IO_ERROR_ ## KIND))
183
184#define CANCELdcgettext (((void*)0), "_Cancel", 5) _("_Cancel")dcgettext (((void*)0), "_Cancel", 5)
185#define SKIPdcgettext (((void*)0), "_Skip", 5) _("_Skip")dcgettext (((void*)0), "_Skip", 5)
186#define SKIP_ALLdcgettext (((void*)0), "S_kip All", 5) _("S_kip All")dcgettext (((void*)0), "S_kip All", 5)
187#define RETRYdcgettext (((void*)0), "_Retry", 5) _("_Retry")dcgettext (((void*)0), "_Retry", 5)
188#define DELETEdcgettext (((void*)0), "_Delete", 5) _("_Delete")dcgettext (((void*)0), "_Delete", 5)
189#define DELETE_ALLdcgettext (((void*)0), "Delete _All", 5) _("Delete _All")dcgettext (((void*)0), "Delete _All", 5)
190#define REPLACE_ALLdcgettext (((void*)0), "Replace _All", 5) _("Replace _All")dcgettext (((void*)0), "Replace _All", 5)
191#define MERGE_ALLdcgettext (((void*)0), "Merge _All", 5) _("Merge _All")dcgettext (((void*)0), "Merge _All", 5)
192#define COPY_FORCEdcgettext (((void*)0), "Copy _Anyway", 5) _("Copy _Anyway")dcgettext (((void*)0), "Copy _Anyway", 5)
193
194NotifyNotification *unmount_notify;
195
196void
197caja_application_notify_unmount_show (const gchar *message)
198{
199 gchar **strings;
200 strings = g_strsplit (message, "\n", 0);
201
202 if (!g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_NOTIFICATIONS"show-notifications")) return;
203
204 if (unmount_notify == NULL((void*)0)) {
205 unmount_notify =
206 notify_notification_new (strings[0], strings[1],
207 "media-removable");
208
209 notify_notification_set_hint (unmount_notify,
210 "transient", g_variant_new_boolean (TRUE(!(0))));
211 notify_notification_set_urgency (unmount_notify,
212 NOTIFY_URGENCY_CRITICAL);
213 } else {
214 notify_notification_update (unmount_notify,
215 strings[0], strings[1],
216 "media-removable");
217 }
218
219 notify_notification_show (unmount_notify, NULL((void*)0));
220 g_strfreev (strings);
221}
222
223static void
224mark_desktop_file_trusted (CommonJob *common,
225 GCancellable *cancellable,
226 GFile *file,
227 gboolean interactive);
228
229static gboolean
230is_all_button_text (const char *button_text)
231{
232 g_assert (button_text != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_50
; if (button_text != ((void*)0)) _g_boolean_var_50 = 1; else _g_boolean_var_50
= 0; _g_boolean_var_50; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 232, ((const char*)
(__func__)), "button_text != NULL"); } while (0)
;
233
234 return !strcmp (button_text, SKIP_ALLdcgettext (((void*)0), "S_kip All", 5)) ||
235 !strcmp (button_text, REPLACE_ALLdcgettext (((void*)0), "Replace _All", 5)) ||
236 !strcmp (button_text, DELETE_ALLdcgettext (((void*)0), "Delete _All", 5)) ||
237 !strcmp (button_text, MERGE_ALLdcgettext (((void*)0), "Merge _All", 5));
238}
239
240static void scan_sources (GList *files,
241 SourceInfo *source_info,
242 CommonJob *job,
243 OpKind kind);
244
245
246static gboolean empty_trash_job (GIOSchedulerJob *io_job,
247 GCancellable *cancellable,
248 gpointer user_data);
249
250static char * query_fs_type (GFile *file,
251 GCancellable *cancellable);
252
253/* keep in time with format_time()
254 *
255 * This counts and outputs the number of “time units”
256 * formatted and displayed by format_time().
257 * For instance, if format_time outputs “3 hours, 4 minutes”
258 * it yields 7.
259 */
260static int
261seconds_count_format_time_units (int seconds)
262{
263 int minutes;
264 int hours;
265
266 if (seconds < 0) {
267 /* Just to make sure... */
268 seconds = 0;
269 }
270
271 if (seconds < 60) {
272 /* seconds */
273 return seconds;
274 }
275
276 if (seconds < 60*60) {
277 /* minutes */
278 minutes = seconds / 60;
279 return minutes;
280 }
281
282 hours = seconds / (60*60);
283
284 if (seconds < 60*60*4) {
285 /* minutes + hours */
286 minutes = (seconds - hours * 60 * 60) / 60;
287 return minutes + hours;
288 }
289
290 return hours;
291}
292
293static char *
294format_time (int seconds)
295{
296 int minutes;
297 int hours;
298
299 if (seconds < 0) {
300 /* Just to make sure... */
301 seconds = 0;
302 }
303
304 if (seconds < 60) {
305 return g_strdup_printf (ngettext ("%'d second","%'d seconds", (int) seconds)dcngettext (((void*)0), "%'d second", "%'d seconds", (int) seconds
, 5)
, (int) seconds);
306 }
307
308 if (seconds < 60*60) {
309 minutes = seconds / 60;
310 return g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes)dcngettext (((void*)0), "%'d minute", "%'d minutes", minutes,
5)
, minutes);
311 }
312
313 hours = seconds / (60*60);
314
315 if (seconds < 60*60*4) {
316 char *h, *m;
317 char *res;
318
319 minutes = (seconds - hours * 60 * 60) / 60;
320
321 h = g_strdup_printf (ngettext ("%'d hour", "%'d hours", hours)dcngettext (((void*)0), "%'d hour", "%'d hours", hours, 5), hours);
322 m = g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes)dcngettext (((void*)0), "%'d minute", "%'d minutes", minutes,
5)
, minutes);
323 res = g_strconcat (h, ", ", m, NULL((void*)0));
324 g_free (h);
325 g_free (m);
326 return res;
327 }
328
329 return g_strdup_printf (ngettext ("approximately %'d hour",dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
330 "approximately %'d hours",dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
331 hours)dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
, hours);
332}
333
334static char *
335shorten_utf8_string (const char *base, int reduce_by_num_bytes)
336{
337 int len;
338 char *ret;
339 const char *p;
340
341 len = strlen (base);
342 len -= reduce_by_num_bytes;
343
344 if (len <= 0) {
345 return NULL((void*)0);
346 }
347
348 ret = g_new (char, len + 1)(char *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
349
350 p = base;
351 while (len) {
352 char *next;
353 next = g_utf8_next_char (p)(char *)((p) + g_utf8_skip[*(const guchar *)(p)]);
354 if (next - p > len || *next == '\0') {
355 break;
356 }
357
358 len -= next - p;
359 p = next;
360 }
361
362 if (p - base == 0) {
363 g_free (ret);
364 return NULL((void*)0);
365 } else {
366 memcpy (ret, base, p - base);
367 ret[p - base] = '\0';
368 return ret;
369 }
370}
371
372/* Note that we have these two separate functions with separate format
373 * strings for ease of localization.
374 */
375
376static char *
377get_link_name (const char *name, int count, int max_length)
378{
379 const char *format;
380 char *result;
381 int unshortened_length;
382 gboolean use_count;
383
384 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_51
; if (name != ((void*)0)) _g_boolean_var_51 = 1; else _g_boolean_var_51
= 0; _g_boolean_var_51; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 384, ((const char*)
(__func__)), "name != NULL"); } while (0)
;
385
386 if (count < 0) {
387 g_warning ("bad count in get_link_name");
388 count = 0;
389 }
390
391 if (count <= 2) {
392 /* Handle special cases for low numbers.
393 * Perhaps for some locales we will need to add more.
394 */
395 switch (count) {
396 default:
397 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 397, ((const char*) (__func__)), ((void*)0)); } while (0)
;
398 /* fall through */
399 case 0:
400 /* duplicate original file name */
401 format = "%s";
402 break;
403 case 1:
404 /* appended to new link file */
405 format = _("Link to %s")dcgettext (((void*)0), "Link to %s", 5);
406 break;
407 case 2:
408 /* appended to new link file */
409 format = _("Another link to %s")dcgettext (((void*)0), "Another link to %s", 5);
410 break;
411 }
412
413 use_count = FALSE(0);
414 } else {
415 /* Handle special cases for the first few numbers of each ten.
416 * For locales where getting this exactly right is difficult,
417 * these can just be made all the same as the general case below.
418 */
419 switch (count % 10) {
420 case 1:
421 /* Translators: Feel free to leave out the "st" suffix
422 * if there's no way to do that nicely for a
423 * particular language.
424 */
425 format = _("%'dst link to %s")dcgettext (((void*)0), "%'dst link to %s", 5);
426 break;
427 case 2:
428 /* appended to new link file */
429 format = _("%'dnd link to %s")dcgettext (((void*)0), "%'dnd link to %s", 5);
430 break;
431 case 3:
432 /* appended to new link file */
433 format = _("%'drd link to %s")dcgettext (((void*)0), "%'drd link to %s", 5);
434 break;
435 default:
436 /* appended to new link file */
437 format = _("%'dth link to %s")dcgettext (((void*)0), "%'dth link to %s", 5);
438 break;
439 }
440
441 use_count = TRUE(!(0));
442 }
443
444 if (use_count)
445 result = g_strdup_printf (format, count, name);
446 else
447 result = g_strdup_printf (format, name);
448
449 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
450 char *new_name;
451
452 new_name = shorten_utf8_string (name, unshortened_length - max_length);
453 if (new_name) {
454 g_free (result);
455
456 if (use_count)
457 result = g_strdup_printf (format, count, new_name);
458 else
459 result = g_strdup_printf (format, new_name);
460
461 g_assert (strlen (result) <= max_length)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_52
; if (strlen (result) <= max_length) _g_boolean_var_52 = 1
; else _g_boolean_var_52 = 0; _g_boolean_var_52; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 461, ((const char*) (__func__)), "strlen (result) <= max_length"
); } while (0)
;
462 g_free (new_name);
463 }
464 }
465
466 return result;
467}
468
469
470/* Translators:
471 * Feel free to leave out the st, nd, rd and th suffix or
472 * make some or all of them match.
473 */
474
475/* Translators: tag used to detect the first copy of a file */
476static const char untranslated_copy_duplicate_tag[] = N_(" (copy)")(" (copy)");
477/* Translators: tag used to detect the second copy of a file */
478static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)")(" (another copy)");
479
480/* Translators: tag used to detect the x11th copy of a file */
481static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
482/* Translators: tag used to detect the x12th copy of a file */
483static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
484/* Translators: tag used to detect the x13th copy of a file */
485static const char untranslated_x13th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
486
487/* Translators: tag used to detect the x1st copy of a file */
488static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)")("st copy)");
489/* Translators: tag used to detect the x2nd copy of a file */
490static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)")("nd copy)");
491/* Translators: tag used to detect the x3rd copy of a file */
492static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)")("rd copy)");
493
494/* Translators: tag used to detect the xxth copy of a file */
495static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
496
497#define COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_copy_duplicate_tag, 5) _(untranslated_copy_duplicate_tag)dcgettext (((void*)0), untranslated_copy_duplicate_tag, 5)
498#define ANOTHER_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
_(untranslated_another_copy_duplicate_tag)dcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
499#define X11TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
_(untranslated_x11th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
500#define X12TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
_(untranslated_x12th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
501#define X13TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
_(untranslated_x13th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
502
503#define ST_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5) _(untranslated_st_copy_duplicate_tag)dcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5)
504#define ND_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5) _(untranslated_nd_copy_duplicate_tag)dcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5)
505#define RD_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5) _(untranslated_rd_copy_duplicate_tag)dcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5)
506#define TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5) _(untranslated_th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5)
507
508/* Translators: appended to first file copy */
509static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s")("%s (copy)%s");
510/* Translators: appended to second file copy */
511static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s")("%s (another copy)%s");
512
513/* Translators: appended to x11th file copy */
514static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
515/* Translators: appended to x12th file copy */
516static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
517/* Translators: appended to x13th file copy */
518static const char untranslated_x13th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
519
520/* Translators: if in your language there's no difference between 1st, 2nd, 3rd and nth
521 * plurals, you can leave the st, nd, rd suffixes out and just make all the translated
522 * strings look like "%s (copy %'d)%s".
523 */
524
525/* Translators: appended to x1st file copy */
526static const char untranslated_st_copy_duplicate_format[] = N_("%s (%'dst copy)%s")("%s (%'dst copy)%s");
527/* Translators: appended to x2nd file copy */
528static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%'dnd copy)%s")("%s (%'dnd copy)%s");
529/* Translators: appended to x3rd file copy */
530static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%'drd copy)%s")("%s (%'drd copy)%s");
531/* Translators: appended to xxth file copy */
532static const char untranslated_th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
533
534#define FIRST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
_(untranslated_first_copy_duplicate_format)dcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
535#define SECOND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
_(untranslated_second_copy_duplicate_format)dcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
536#define X11TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
_(untranslated_x11th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
537#define X12TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
_(untranslated_x12th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
538#define X13TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
_(untranslated_x13th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
539
540#define ST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
_(untranslated_st_copy_duplicate_format)dcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
541#define ND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
_(untranslated_nd_copy_duplicate_format)dcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
542#define RD_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
_(untranslated_rd_copy_duplicate_format)dcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
543#define TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
_(untranslated_th_copy_duplicate_format)dcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
544
545static char *
546extract_string_until (const char *original, const char *until_substring)
547{
548 char *result;
549
550 g_assert ((int) strlen (original) >= until_substring - original)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_53
; if ((int) strlen (original) >= until_substring - original
) _g_boolean_var_53 = 1; else _g_boolean_var_53 = 0; _g_boolean_var_53
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 550, ((const char*) (__func__)), "(int) strlen (original) >= until_substring - original"
); } while (0)
;
551 g_assert (until_substring - original >= 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_54
; if (until_substring - original >= 0) _g_boolean_var_54 =
1; else _g_boolean_var_54 = 0; _g_boolean_var_54; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 551, ((const char*) (__func__)), "until_substring - original >= 0"
); } while (0)
;
552
553 result = g_malloc (until_substring - original + 1);
554 strncpy (result, original, until_substring - original);
555 result[until_substring - original] = '\0';
556
557 return result;
558}
559
560/* Dismantle a file name, separating the base name, the file suffix and removing any
561 * (xxxcopy), etc. string. Figure out the count that corresponds to the given
562 * (xxxcopy) substring.
563 */
564static void
565parse_previous_duplicate_name (const char *name,
566 char **name_base,
567 const char **suffix,
568 int *count)
569{
570 const char *tag;
571
572 g_assert (name[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_55
; if (name[0] != '\0') _g_boolean_var_55 = 1; else _g_boolean_var_55
= 0; _g_boolean_var_55; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 572, ((const char*)
(__func__)), "name[0] != '\\0'"); } while (0)
;
573
574 *suffix = strchr (name + 1, '.');
575 if (*suffix == NULL((void*)0) || (*suffix)[1] == '\0') {
576 /* no suffix */
577 *suffix = "";
578 }
579
580 tag = strstr (name, COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_copy_duplicate_tag, 5));
581 if (tag != NULL((void*)0)) {
582 if (tag > *suffix) {
583 /* handle case "foo. (copy)" */
584 *suffix = "";
585 }
586 *name_base = extract_string_until (name, tag);
587 *count = 1;
588 return;
589 }
590
591
592 tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
);
593 if (tag != NULL((void*)0)) {
594 if (tag > *suffix) {
595 /* handle case "foo. (another copy)" */
596 *suffix = "";
597 }
598 *name_base = extract_string_until (name, tag);
599 *count = 2;
600 return;
601 }
602
603
604 /* Check to see if we got one of st, nd, rd, th. */
605 tag = strstr (name, X11TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
);
606
607 if (tag == NULL((void*)0)) {
608 tag = strstr (name, X12TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
);
609 }
610 if (tag == NULL((void*)0)) {
611 tag = strstr (name, X13TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
);
612 }
613
614 if (tag == NULL((void*)0)) {
615 tag = strstr (name, ST_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5));
616 }
617 if (tag == NULL((void*)0)) {
618 tag = strstr (name, ND_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5));
619 }
620 if (tag == NULL((void*)0)) {
621 tag = strstr (name, RD_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5));
622 }
623 if (tag == NULL((void*)0)) {
624 tag = strstr (name, TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5));
625 }
626
627 /* If we got one of st, nd, rd, th, fish out the duplicate number. */
628 if (tag != NULL((void*)0)) {
629 /* Translators: opening parentheses to match the "th copy)" string */
630 tag = strstr (name, _(" (")dcgettext (((void*)0), " (", 5));
631 if (tag != NULL((void*)0)) {
632 if (tag > *suffix) {
633 /* handle case "foo. (22nd copy)" */
634 *suffix = "";
635 }
636 *name_base = extract_string_until (name, tag);
637 /* Translators: opening parentheses of the "th copy)" string */
638 if (sscanf (tag, _(" (%'d")dcgettext (((void*)0), " (%'d", 5), count) == 1) {
639 if (*count < 1 || *count > 1000000) {
640 /* keep the count within a reasonable range */
641 *count = 0;
642 }
643 return;
644 }
645 *count = 0;
646 return;
647 }
648 }
649
650
651 *count = 0;
652 if (**suffix != '\0') {
653 *name_base = extract_string_until (name, *suffix);
654 } else {
655 *name_base = g_strdup (name)g_strdup_inline (name);
656 }
657}
658
659static char *
660make_next_duplicate_name (const char *base, const char *suffix, int count, int max_length)
661{
662 const char *format;
663 char *result;
664 int unshortened_length;
665 gboolean use_count;
666
667 if (count < 1) {
668 g_warning ("bad count %d in get_duplicate_name", count);
669 count = 1;
670 }
671
672 if (count <= 2) {
673
674 /* Handle special cases for low numbers.
675 * Perhaps for some locales we will need to add more.
676 */
677 switch (count) {
678 default:
679 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 679, ((const char*) (__func__)), ((void*)0)); } while (0)
;
680 /* fall through */
681 case 1:
682 format = FIRST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
;
683 break;
684 case 2:
685 format = SECOND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
;
686 break;
687
688 }
689
690 use_count = FALSE(0);
691 } else {
692
693 /* Handle special cases for the first few numbers of each ten.
694 * For locales where getting this exactly right is difficult,
695 * these can just be made all the same as the general case below.
696 */
697
698 /* Handle special cases for x11th - x20th.
699 */
700 switch (count % 100) {
701 case 11:
702 format = X11TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
;
703 break;
704 case 12:
705 format = X12TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
;
706 break;
707 case 13:
708 format = X13TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
;
709 break;
710 default:
711 format = NULL((void*)0);
712 break;
713 }
714
715 if (format == NULL((void*)0)) {
716 switch (count % 10) {
717 case 1:
718 format = ST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
;
719 break;
720 case 2:
721 format = ND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
;
722 break;
723 case 3:
724 format = RD_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
;
725 break;
726 default:
727 /* The general case. */
728 format = TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
;
729 break;
730 }
731 }
732
733 use_count = TRUE(!(0));
734
735 }
736
737 if (use_count)
738 result = g_strdup_printf (format, base, count, suffix);
739 else
740 result = g_strdup_printf (format, base, suffix);
741
742 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
743 char *new_base;
744
745 new_base = shorten_utf8_string (base, unshortened_length - max_length);
746 if (new_base) {
747 g_free (result);
748
749 if (use_count)
750 result = g_strdup_printf (format, new_base, count, suffix);
751 else
752 result = g_strdup_printf (format, new_base, suffix);
753
754 g_assert (strlen (result) <= max_length)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_56
; if (strlen (result) <= max_length) _g_boolean_var_56 = 1
; else _g_boolean_var_56 = 0; _g_boolean_var_56; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 754, ((const char*) (__func__)), "strlen (result) <= max_length"
); } while (0)
;
755 g_free (new_base);
756 }
757 }
758
759 return result;
760}
761
762static char *
763get_duplicate_name (const char *name, int count_increment, int max_length)
764{
765 char *result;
766 char *name_base;
767 const char *suffix;
768 int count;
769
770 parse_previous_duplicate_name (name, &name_base, &suffix, &count);
771 result = make_next_duplicate_name (name_base, suffix, count + count_increment, max_length);
772
773 g_free (name_base);
774
775 return result;
776}
777
778static gboolean
779has_invalid_xml_char (char *str)
780{
781 gunichar c;
782
783 while (*str != 0) {
784 c = g_utf8_get_char (str);
785 /* characters XML permits */
786 if (!(c == 0x9 ||
787 c == 0xA ||
788 c == 0xD ||
789 (c >= 0x20 && c <= 0xD7FF) ||
790 (c >= 0xE000 && c <= 0xFFFD) ||
791 (c >= 0x10000 && c <= 0x10FFFF))) {
792 return TRUE(!(0));
793 }
794 str = g_utf8_next_char (str)(char *)((str) + g_utf8_skip[*(const guchar *)(str)]);
795 }
796 return FALSE(0);
797}
798
799
800static char *
801custom_full_name_to_string (char *format, va_list va)
802{
803 GFile *file;
804
805 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
806
807 return g_file_get_parse_name (file);
808}
809
810static void
811custom_full_name_skip (va_list *va)
812{
813 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
814}
815
816static char *
817custom_basename_to_string (char *format, va_list va)
818{
819 GFile *file;
820 GFileInfo *info;
821 char *name, *basename, *tmp;
822
823 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
824
825 info = g_file_query_info (file,
826 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME"standard::display-name",
827 0,
828 g_cancellable_get_current (),
829 NULL((void*)0));
830
831 name = NULL((void*)0);
832 if (info) {
833 name = g_strdup (g_file_info_get_display_name (info))g_strdup_inline (g_file_info_get_display_name (info));
834 g_object_unref (info);
835 }
836
837 if (name == NULL((void*)0)) {
838 basename = g_file_get_basename (file);
839 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
840 name = basename;
841 } else {
842 name = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
843 g_free (basename);
844 }
845 }
846
847 /* Some chars can't be put in the markup we use for the dialogs... */
848 if (has_invalid_xml_char (name)) {
849 tmp = name;
850 name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
851 g_free (tmp);
852 }
853
854 /* Finally, if the string is too long, truncate it. */
855 if (name != NULL((void*)0)) {
856 tmp = name;
857 name = eel_str_middle_truncate (tmp, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50);
858 g_free (tmp);
859 }
860
861
862 return name;
863}
864
865static void
866custom_basename_skip (va_list *va)
867{
868 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
869}
870
871
872static char *
873custom_size_to_string (char *format, va_list va)
874{
875 goffset size;
876
877 size = va_arg (va, goffset)__builtin_va_arg(va, goffset);
878
879 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
880 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
881 else
882 return g_format_size(size);
883}
884
885static void
886custom_size_skip (va_list *va)
887{
888 (void) va_arg (*va, goffset)__builtin_va_arg(*va, goffset);
889}
890
891static char *
892custom_time_to_string (char *format, va_list va)
893{
894 int secs;
895
896 secs = va_arg (va, int)__builtin_va_arg(va, int);
897 return format_time (secs);
898}
899
900static void
901custom_time_skip (va_list *va)
902{
903 (void) va_arg (*va, int)__builtin_va_arg(*va, int);
904}
905
906static char *
907custom_mount_to_string (char *format, va_list va)
908{
909 GMount *mount;
910
911 mount = va_arg (va, GMount *)__builtin_va_arg(va, GMount *);
912 return g_mount_get_name (mount);
913}
914
915static void
916custom_mount_skip (va_list *va)
917{
918 (void) va_arg (*va, GMount *)__builtin_va_arg(*va, GMount *);
919}
920
921
922static EelPrintfHandler handlers[] = {
923 { 'F', custom_full_name_to_string, custom_full_name_skip },
924 { 'B', custom_basename_to_string, custom_basename_skip },
925 { 'S', custom_size_to_string, custom_size_skip },
926 { 'T', custom_time_to_string, custom_time_skip },
927 { 'V', custom_mount_to_string, custom_mount_skip },
928 { 0 }
929};
930
931
932static char *
933f (const char *format, ...) {
934 va_list va;
935 char *res;
936
937 va_start (va, format)__builtin_va_start(va, format);
938 res = eel_strdup_vprintf_with_custom (handlers, format, va);
939 va_end (va)__builtin_va_end(va);
940
941 return res;
942}
943
944#define op_job_new(__type, parent_window, should_start, can_pause)((__type *)(init_common (sizeof(__type), parent_window, should_start
, can_pause)))
((__type *)(init_common (sizeof(__type), parent_window, should_start, can_pause)))
945
946static gpointer
947init_common (gsize job_size,
948 GtkWindow *parent_window,
949 gboolean should_start, gboolean can_pause)
950{
951 CommonJob *common;
952
953 /* expected warning with Clang static analyzer: *
954 * "Cast a region whose size is not a multiple of the destination type size" *
955 * *
956 * It is expected for job_size to be larger than sizeof(CommonJob) no matter *
957 * what Clang analyzer reports: we're allocating the whole structure for a job *
958 * (e.g. a TrashJob), but only initializing the common part of it (CommonJob) *
959 * which is a subset of all "real" job structures, structures that all start *
960 * with a CommonJob, and that thus can be used as such. */
961 common = g_malloc0 (job_size);
962
963 if (parent_window) {
964 common->parent_window = parent_window;
965 eel_add_weak_pointer (&common->parent_window);
966 }
967 common->progress = caja_progress_info_new (should_start, can_pause);
968 common->cancellable = caja_progress_info_get_cancellable (common->progress);
969 common->time = g_timer_new ();
970 common->inhibit_cookie = -1;
971 common->screen_num = 0;
972 if (parent_window) {
973 GdkScreen *screen;
974
975 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) (void *) ((parent_window))))));
976 common->screen_num = gdk_x11_screen_get_screen_number (screen);
977 }
978
979 return common;
980}
981
982static void
983finalize_common (CommonJob *common)
984{
985 caja_progress_info_finish (common->progress);
986
987 if (common->inhibit_cookie != -1) {
988 caja_uninhibit_power_manager (common->inhibit_cookie);
989 }
990
991 common->inhibit_cookie = -1;
992 g_timer_destroy (common->time);
993 eel_remove_weak_pointer (&common->parent_window);
994 if (common->skip_files) {
995 g_hash_table_destroy (common->skip_files);
996 }
997 if (common->skip_readdir_error) {
998 g_hash_table_destroy (common->skip_readdir_error);
999 }
1000 // Start UNDO-REDO
1001 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1002 common->undo_redo_data);
1003 // End UNDO-REDO
1004 g_object_unref (common->progress);
1005 g_object_unref (common->cancellable);
1006 g_free (common);
1007}
1008
1009static void
1010skip_file (CommonJob *common,
1011 GFile *file)
1012{
1013 if (common->skip_files == NULL((void*)0)) {
1014 common->skip_files =
1015 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1016 }
1017
1018 g_hash_table_insert (common->skip_files, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)), file);
1019}
1020
1021static void
1022skip_readdir_error (CommonJob *common,
1023 GFile *dir)
1024{
1025 if (common->skip_readdir_error == NULL((void*)0)) {
1026 common->skip_readdir_error =
1027 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1028 }
1029
1030 g_hash_table_insert (common->skip_readdir_error, g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir)), dir);
1031}
1032
1033static gboolean
1034should_skip_file (CommonJob *common,
1035 GFile *file)
1036{
1037 if (common->skip_files != NULL((void*)0)) {
1038 return g_hash_table_lookup (common->skip_files, file) != NULL((void*)0);
1039 }
1040
1041 return FALSE(0);
1042}
1043
1044static gboolean
1045should_skip_readdir_error (CommonJob *common,
1046 GFile *dir)
1047{
1048 if (common->skip_readdir_error != NULL((void*)0)) {
1049 return g_hash_table_lookup (common->skip_readdir_error, dir) != NULL((void*)0);
1050 }
1051 return FALSE(0);
1052}
1053
1054static gboolean
1055can_delete_without_confirm (GFile *file)
1056{
1057 if (g_file_has_uri_scheme (file, "burn") ||
1058 g_file_has_uri_scheme (file, "x-caja-desktop")) {
1059 return TRUE(!(0));
1060 }
1061
1062 return FALSE(0);
1063}
1064
1065static gboolean
1066can_delete_files_without_confirm (GList *files)
1067{
1068 g_assert (files != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_57
; if (files != ((void*)0)) _g_boolean_var_57 = 1; else _g_boolean_var_57
= 0; _g_boolean_var_57; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1068, ((const char*
) (__func__)), "files != NULL"); } while (0)
;
1069
1070 while (files != NULL((void*)0)) {
1071 if (!can_delete_without_confirm (files->data)) {
1072 return FALSE(0);
1073 }
1074
1075 files = files->next;
1076 }
1077
1078 return TRUE(!(0));
1079}
1080
1081typedef struct {
1082 GtkWindow **parent_window;
1083 gboolean ignore_close_box;
1084 GtkMessageType message_type;
1085 const char *primary_text;
1086 const char *secondary_text;
1087 const char *details_text;
1088 const char **button_titles;
1089 gboolean show_all;
1090
1091 int result;
1092} RunSimpleDialogData;
1093
1094static gboolean
1095do_run_simple_dialog (gpointer _data)
1096{
1097 RunSimpleDialogData *data = _data;
1098 GtkWidget *dialog;
1099 int result;
1100 int response_id;
1101
1102 /* Create the dialog. */
1103 dialog = gtk_message_dialog_new (*data->parent_window,
1104 0,
1105 data->message_type,
1106 GTK_BUTTONS_NONE,
1107 NULL((void*)0));
1108
1109 g_object_set (dialog,
1110 "text", data->primary_text,
1111 "secondary-text", data->secondary_text,
1112 NULL((void*)0));
1113
1114 for (response_id = 0;
1115 data->button_titles[response_id] != NULL((void*)0);
1116 response_id++) {
1117 const char *button_title;
1118
1119 button_title = data->button_titles[response_id];
1120 if (!data->show_all && is_all_button_text (button_title)) {
1121 continue;
1122 }
1123
1124 if (g_strcmp0 (button_title, CANCELdcgettext (((void*)0), "_Cancel", 5)) == 0)
1125 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, "process-stop", response_id);
1126 else if (g_strcmp0 (button_title, DELETEdcgettext (((void*)0), "_Delete", 5)) == 0)
1127 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, "edit-delete", response_id);
1128 else
1129 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, response_id);
1130
1131 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), response_id);
1132 }
1133
1134 if (data->details_text) {
1135 eel_gtk_message_dialog_set_details_label (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
1136 data->details_text);
1137 }
1138
1139 /* Run it. */
1140 gtk_widget_show (dialog);
1141 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
1142
1143 while ((result == GTK_RESPONSE_NONE || result == GTK_RESPONSE_DELETE_EVENT) && data->ignore_close_box) {
1144 gtk_widget_show (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1145 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
1146 }
1147
1148 gtk_widget_destroy (dialog);
1149
1150 data->result = result;
1151
1152 return FALSE(0);
1153}
1154
1155/* NOTE: This frees the primary / secondary strings, in order to
1156 avoid doing that everywhere. So, make sure they are strduped */
1157
1158static int
1159run_simple_dialog_va (CommonJob *job,
1160 gboolean ignore_close_box,
1161 GtkMessageType message_type,
1162 char *primary_text,
1163 char *secondary_text,
1164 const char *details_text,
1165 gboolean show_all,
1166 va_list varargs)
1167{
1168 RunSimpleDialogData *data;
1169 int res;
1170 const char *button_title;
1171 GPtrArray *ptr_array;
1172
1173 g_timer_stop (job->time);
1174
1175 data = g_new0 (RunSimpleDialogData, 1)(RunSimpleDialogData *) (__extension__ ({ gsize __n = (gsize)
(1); gsize __s = sizeof (RunSimpleDialogData); 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; }))
;
1176 data->parent_window = &job->parent_window;
1177 data->ignore_close_box = ignore_close_box;
1178 data->message_type = message_type;
1179 data->primary_text = primary_text;
1180 data->secondary_text = secondary_text;
1181 data->details_text = details_text;
1182 data->show_all = show_all;
1183
1184 ptr_array = g_ptr_array_new ();
1185 while ((button_title = va_arg (varargs, const char *)__builtin_va_arg(varargs, const char *)) != NULL((void*)0)) {
1186 g_ptr_array_add (ptr_array, (char *)button_title);
1187 }
1188 g_ptr_array_add (ptr_array, NULL((void*)0));
1189 data->button_titles = (const char **)g_ptr_array_free (ptr_array, FALSE(0));
1190
1191 caja_progress_info_pause (job->progress);
1192 g_io_scheduler_job_send_to_mainloop (job->io_job,
1193 do_run_simple_dialog,
1194 data,
1195 NULL((void*)0));
1196 caja_progress_info_resume (job->progress);
1197 res = data->result;
1198
1199 g_free (data->button_titles);
1200 g_free (data);
1201
1202 g_timer_continue (job->time);
1203
1204 g_free (primary_text);
1205 g_free (secondary_text);
1206
1207 return res;
1208}
1209
1210#if 0 /* Not used at the moment */
1211static int
1212run_simple_dialog (CommonJob *job,
1213 gboolean ignore_close_box,
1214 GtkMessageType message_type,
1215 char *primary_text,
1216 char *secondary_text,
1217 const char *details_text,
1218 ...)
1219{
1220 va_list varargs;
1221 int res;
1222
1223 va_start (varargs, details_text)__builtin_va_start(varargs, details_text);
1224 res = run_simple_dialog_va (job,
1225 ignore_close_box,
1226 message_type,
1227 primary_text,
1228 secondary_text,
1229 details_text,
1230 varargs);
1231 va_end (varargs)__builtin_va_end(varargs);
1232 return res;
1233}
1234#endif
1235
1236static int
1237run_error (CommonJob *job,
1238 char *primary_text,
1239 char *secondary_text,
1240 const char *details_text,
1241 gboolean show_all,
1242 ...)
1243{
1244 va_list varargs;
1245 int res;
1246
1247 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1248 res = run_simple_dialog_va (job,
1249 FALSE(0),
1250 GTK_MESSAGE_ERROR,
1251 primary_text,
1252 secondary_text,
1253 details_text,
1254 show_all,
1255 varargs);
1256 va_end (varargs)__builtin_va_end(varargs);
1257 return res;
1258}
1259
1260static int
1261run_warning (CommonJob *job,
1262 char *primary_text,
1263 char *secondary_text,
1264 const char *details_text,
1265 gboolean show_all,
1266 ...)
1267{
1268 va_list varargs;
1269 int res;
1270
1271 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1272 res = run_simple_dialog_va (job,
1273 FALSE(0),
1274 GTK_MESSAGE_WARNING,
1275 primary_text,
1276 secondary_text,
1277 details_text,
1278 show_all,
1279 varargs);
1280 va_end (varargs)__builtin_va_end(varargs);
1281 return res;
1282}
1283
1284static int
1285run_question (CommonJob *job,
1286 char *primary_text,
1287 char *secondary_text,
1288 const char *details_text,
1289 gboolean show_all,
1290 ...)
1291{
1292 va_list varargs;
1293 int res;
1294
1295 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1296 res = run_simple_dialog_va (job,
1297 FALSE(0),
1298 GTK_MESSAGE_QUESTION,
1299 primary_text,
1300 secondary_text,
1301 details_text,
1302 show_all,
1303 varargs);
1304 va_end (varargs)__builtin_va_end(varargs);
1305 return res;
1306}
1307
1308static void
1309inhibit_power_manager (CommonJob *job, const char *message)
1310{
1311 job->inhibit_cookie = caja_inhibit_power_manager (message);
1312}
1313
1314static void
1315abort_job (CommonJob *job)
1316{
1317 g_cancellable_cancel (job->cancellable);
1318
1319}
1320
1321/* Since this happens on a thread we can't use the global prefs object */
1322static gboolean
1323should_confirm_trash (void)
1324{
1325 GSettings *prefs;
1326 gboolean confirm_trash;
1327
1328 prefs = g_settings_new ("org.mate.caja.preferences");
1329 confirm_trash = g_settings_get_boolean (prefs, CAJA_PREFERENCES_CONFIRM_TRASH"confirm-trash");
1330 g_object_unref (prefs);
1331 return confirm_trash;
1332}
1333
1334static gboolean
1335should_confirm_move_to_trash (void)
1336{
1337 GSettings *prefs;
1338 gboolean confirm_trash;
1339
1340 prefs = g_settings_new ("org.mate.caja.preferences");
1341 confirm_trash = g_settings_get_boolean (prefs, CAJA_PREFERENCES_CONFIRM_MOVE_TO_TRASH"confirm-move-to-trash");
1342 g_object_unref (prefs);
1343 return confirm_trash;
1344}
1345
1346static gboolean
1347job_aborted (CommonJob *job)
1348{
1349 return g_cancellable_is_cancelled (job->cancellable);
1350}
1351
1352static gboolean
1353confirm_delete_from_trash (CommonJob *job,
1354 GList *files)
1355{
1356 char *prompt;
1357 int file_count;
1358 int response;
1359
1360 /* Just Say Yes if the preference says not to confirm. */
1361 if (!should_confirm_trash ()) {
1362 return TRUE(!(0));
1363 }
1364
1365 file_count = g_list_length (files);
1366 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_58
; if (file_count > 0) _g_boolean_var_58 = 1; else _g_boolean_var_58
= 0; _g_boolean_var_58; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1366, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1367
1368 if (file_count == 1) {
1369 prompt = f (_("Are you sure you want to permanently delete \"%B\" "dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\" "
"from the trash?", 5)
1370 "from the trash?")dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\" "
"from the trash?", 5)
, files->data);
1371 } else {
1372 prompt = f (ngettext("Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1373 "the %'d selected item from the trash?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1374 "Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1375 "the %'d selected items from the trash?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1376 file_count)dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
,
1377 file_count);
1378 }
1379
1380 response = run_warning (job,
1381 prompt,
1382 f (_("If you delete an item, it will be permanently lost.")dcgettext (((void*)0), "If you delete an item, it will be permanently lost."
, 5)
),
1383 NULL((void*)0),
1384 FALSE(0),
1385 CANCELdcgettext (((void*)0), "_Cancel", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1386 NULL((void*)0));
1387
1388 return (response == 1);
1389}
1390
1391static gboolean
1392confirm_empty_trash (CommonJob *job)
1393{
1394 char *prompt;
1395 int response;
1396
1397 /* Just Say Yes if the preference says not to confirm. */
1398 if (!should_confirm_trash ()) {
1399 return TRUE(!(0));
1400 }
1401
1402 prompt = f (_("Empty all items from Trash?")dcgettext (((void*)0), "Empty all items from Trash?", 5));
1403
1404 response = run_warning (job,
1405 prompt,
1406 f(_("All items in the Trash will be permanently deleted.")dcgettext (((void*)0), "All items in the Trash will be permanently deleted."
, 5)
),
1407 NULL((void*)0),
1408 FALSE(0),
1409 CANCELdcgettext (((void*)0), "_Cancel", 5), _("Empty _Trash")dcgettext (((void*)0), "Empty _Trash", 5),
1410 NULL((void*)0));
1411
1412 return (response == 1);
1413}
1414
1415static gboolean
1416confirm_delete_directly (CommonJob *job,
1417 GList *files)
1418{
1419 char *prompt;
1420 int file_count;
1421 int response;
1422
1423 /* Just Say Yes if the preference says not to confirm. */
1424 if (!should_confirm_trash ()) {
1425 return TRUE(!(0));
1426 }
1427
1428 file_count = g_list_length (files);
1429 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_59
; if (file_count > 0) _g_boolean_var_59 = 1; else _g_boolean_var_59
= 0; _g_boolean_var_59; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1429, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1430
1431 if (can_delete_files_without_confirm (files)) {
1432 return TRUE(!(0));
1433 }
1434
1435 if (file_count == 1) {
1436 prompt = f (_("Are you sure you want to permanently delete \"%B\"?")dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\"?"
, 5)
,
1437 files->data);
1438 } else {
1439 prompt = f (ngettext("Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1440 "the %'d selected item?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1441 "Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1442 "the %'d selected items?", file_count)dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
,
1443 file_count);
1444 }
1445
1446 response = run_warning (job,
1447 prompt,
1448 f (_("If you delete an item, it will be permanently lost.")dcgettext (((void*)0), "If you delete an item, it will be permanently lost."
, 5)
),
1449 NULL((void*)0),
1450 FALSE(0),
1451 CANCELdcgettext (((void*)0), "_Cancel", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1452 NULL((void*)0));
1453
1454 return response == 1;
1455}
1456
1457static gboolean
1458confirm_trash (CommonJob *job,
1459 GList *files)
1460{
1461 char *prompt;
1462 int file_count;
1463 int response;
1464
1465 /* Just Say Yes if the preference says not to confirm. */
1466 if (!should_confirm_move_to_trash ()) {
1467 return TRUE(!(0));
1468 }
1469
1470 file_count = g_list_length (files);
1471 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_60
; if (file_count > 0) _g_boolean_var_60 = 1; else _g_boolean_var_60
= 0; _g_boolean_var_60; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1471, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1472
1473 if (can_delete_files_without_confirm (files)) {
1474 return TRUE(!(0));
1475 }
1476
1477 if (file_count == 1) {
1478 prompt = f (_("Are you sure you want to trash \"%B\"?")dcgettext (((void*)0), "Are you sure you want to trash \"%B\"?"
, 5)
,
1479 files->data);
1480 } else {
1481 prompt = f (ngettext("Are you sure you want to trash "dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1482 "the %'d selected item?",dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1483 "Are you sure you want to trash "dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1484 "the %'d selected items?", file_count)dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
,
1485 file_count);
1486 }
1487
1488 response = run_warning (job,
1489 prompt,
1490 f (_("Items moved to the trash may be recovered until the trash is emptied.")dcgettext (((void*)0), "Items moved to the trash may be recovered until the trash is emptied."
, 5)
),
1491 NULL((void*)0),
1492 FALSE(0),
1493 CANCELdcgettext (((void*)0), "_Cancel", 5), _("Move to _Trash")dcgettext (((void*)0), "Move to _Trash", 5),
1494 NULL((void*)0));
1495
1496 return response == 1;
1497}
1498
1499static void
1500report_delete_progress (CommonJob *job,
1501 SourceInfo *source_info,
1502 TransferInfo *transfer_info)
1503{
1504 int files_left;
1505 double elapsed;
1506 gint64 now;
1507 char *files_left_s;
1508
1509 now = g_get_monotonic_time ();
1510 if (transfer_info->last_report_time != 0 &&
1511 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
1512 return;
1513 }
1514 transfer_info->last_report_time = now;
1515
1516 files_left = source_info->num_files - transfer_info->num_files;
1517
1518 /* Races and whatnot could cause this to be negative... */
1519 if (files_left < 0) {
1520 files_left = 1;
1521 }
1522
1523 files_left_s = f (ngettext ("%'d file left to delete",dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
1524 "%'d files left to delete",dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
1525 files_left)dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
,
1526 files_left);
1527
1528 caja_progress_info_take_status (job->progress,
1529 f (_("Deleting files")dcgettext (((void*)0), "Deleting files", 5)));
1530
1531 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
1532 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15) {
1533
1534 caja_progress_info_set_details (job->progress, files_left_s);
1535 } else {
1536 char *details, *time_left_s;
1537 int remaining_time;
1538 double transfer_rate;
1539
1540 transfer_rate = transfer_info->num_files / elapsed;
1541 remaining_time = files_left / transfer_rate;
1542
1543 /* Translators: %T will expand to a time like "2 minutes".
1544 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
1545 */
1546 time_left_s = f (ngettext ("%T left",dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
1547 "%T left",dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
1548 seconds_count_format_time_units (remaining_time))dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
,
1549 remaining_time);
1550
1551 details = g_strconcat (files_left_s, "\xE2\x80\x94", time_left_s, NULL((void*)0));
1552 caja_progress_info_take_details (job->progress, details);
1553
1554 g_free (time_left_s);
1555 }
1556
1557 g_free (files_left_s);
1558
1559 if (source_info->num_files != 0) {
1560 caja_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files);
1561 }
1562}
1563
1564static void delete_file (CommonJob *job, GFile *file,
1565 gboolean *skipped_file,
1566 SourceInfo *source_info,
1567 TransferInfo *transfer_info,
1568 gboolean toplevel);
1569
1570static void
1571delete_dir (CommonJob *job, GFile *dir,
1572 gboolean *skipped_file,
1573 SourceInfo *source_info,
1574 TransferInfo *transfer_info,
1575 gboolean toplevel)
1576{
1577 GFileInfo *info;
1578 GError *error;
1579 GFile *file;
1580 GFileEnumerator *enumerator;
1581 char *primary, *secondary, *details;
1582 int response;
1583 gboolean skip_error;
1584 gboolean local_skipped_file;
1585
1586 local_skipped_file = FALSE(0);
1587
1588 skip_error = should_skip_readdir_error (job, dir);
1589 retry:
1590 error = NULL((void*)0);
1591 enumerator = g_file_enumerate_children (dir,
1592 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
1593 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1594 job->cancellable,
1595 &error);
1596 if (enumerator) {
1597 error = NULL((void*)0);
1598
1599 while (!job_aborted (job) &&
1600 (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error)) != NULL((void*)0)) {
1601 file = g_file_get_child (dir,
1602 g_file_info_get_name (info));
1603 delete_file (job, file, &local_skipped_file, source_info, transfer_info, FALSE(0));
1604 g_object_unref (file);
1605 g_object_unref (info);
1606 }
1607 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
1608 g_object_unref (enumerator);
1609
1610 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1611 g_error_free (error);
1612 } else if (error) {
1613 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1614 details = NULL((void*)0);
1615
1616 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1617 secondary = f (_("Files in the folder \"%B\" cannot be deleted because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be deleted because you do "
"not have permissions to see them.", 5)
1618 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be deleted because you do "
"not have permissions to see them.", 5)
, dir);
1619 } else {
1620 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, dir);
1621 details = error->message;
1622 }
1623
1624 response = run_warning (job,
1625 primary,
1626 secondary,
1627 details,
1628 FALSE(0),
1629 CANCELdcgettext (((void*)0), "_Cancel", 5), _("_Skip files")dcgettext (((void*)0), "_Skip files", 5),
1630 NULL((void*)0));
1631
1632 g_error_free (error);
1633
1634 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1635 abort_job (job);
1636 } else if (response == 1) {
1637 /* Skip: Do Nothing */
1638 local_skipped_file = TRUE(!(0));
1639 } else {
1640 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1640, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1641 }
1642 }
1643
1644 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1645 g_error_free (error);
1646 } else {
1647 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1648 details = NULL((void*)0);
1649 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1650 secondary = f (_("The folder \"%B\" cannot be deleted because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be deleted because you do not have "
"permissions to read it.", 5)
1651 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be deleted because you do not have "
"permissions to read it.", 5)
, dir);
1652 } else {
1653 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, dir);
1654 details = error->message;
1655 }
1656
1657 response = run_warning (job,
1658 primary,
1659 secondary,
1660 details,
1661 FALSE(0),
1662 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
1663 NULL((void*)0));
1664
1665 g_error_free (error);
1666
1667 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1668 abort_job (job);
1669 } else if (response == 1) {
1670 /* Skip: Do Nothing */
1671 local_skipped_file = TRUE(!(0));
1672 } else if (response == 2) {
1673 goto retry;
1674 } else {
1675 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1675, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1676 }
1677 }
1678
1679 if (!job_aborted (job) &&
1680 /* Don't delete dir if there was a skipped file */
1681 !local_skipped_file) {
1682 if (!g_file_delete (dir, job->cancellable, &error)) {
1683 if (job->skip_all_error) {
1684 goto skip;
1685 }
1686 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1687 secondary = f (_("Could not remove the folder %B.")dcgettext (((void*)0), "Could not remove the folder %B.", 5), dir);
1688 details = error->message;
1689
1690 response = run_warning (job,
1691 primary,
1692 secondary,
1693 details,
1694 (source_info->num_files - transfer_info->num_files) > 1,
1695 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
1696 NULL((void*)0));
1697
1698 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1699 abort_job (job);
1700 } else if (response == 1) { /* skip all */
1701 job->skip_all_error = TRUE(!(0));
1702 local_skipped_file = TRUE(!(0));
1703 } else if (response == 2) { /* skip */
1704 local_skipped_file = TRUE(!(0));
1705 } else {
1706 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1706, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1707 }
1708
1709 skip:
1710 g_error_free (error);
1711 } else {
1712 caja_file_changes_queue_file_removed (dir);
1713 transfer_info->num_files ++;
1714 report_delete_progress (job, source_info, transfer_info);
1715 return;
1716 }
1717 }
1718
1719 if (local_skipped_file) {
1720 *skipped_file = TRUE(!(0));
1721 }
1722}
1723
1724static void
1725delete_file (CommonJob *job, GFile *file,
1726 gboolean *skipped_file,
1727 SourceInfo *source_info,
1728 TransferInfo *transfer_info,
1729 gboolean toplevel)
1730{
1731 GError *error;
1732 char *primary, *secondary, *details;
1733 int response;
1734
1735 if (should_skip_file (job, file)) {
1736 *skipped_file = TRUE(!(0));
1737 return;
1738 }
1739
1740 error = NULL((void*)0);
1741 if (g_file_delete (file, job->cancellable, &error)) {
1742 caja_file_changes_queue_file_removed (file);
1743 transfer_info->num_files ++;
1744 report_delete_progress (job, source_info, transfer_info);
1745 return;
1746 }
1747
1748 if (IS_IO_ERROR (error, NOT_EMPTY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_EMPTY))
) {
1749 g_error_free (error);
1750 delete_dir (job, file,
1751 skipped_file,
1752 source_info, transfer_info,
1753 toplevel);
1754 return;
1755
1756 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1757 g_error_free (error);
1758
1759 } else {
1760 if (job->skip_all_error) {
1761 goto skip;
1762 }
1763 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1764 secondary = f (_("There was an error deleting %B.")dcgettext (((void*)0), "There was an error deleting %B.", 5), file);
1765 details = error->message;
1766
1767 response = run_warning (job,
1768 primary,
1769 secondary,
1770 details,
1771 (source_info->num_files - transfer_info->num_files) > 1,
1772 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
1773 NULL((void*)0));
1774
1775 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1776 abort_job (job);
1777 } else if (response == 1) { /* skip all */
1778 job->skip_all_error = TRUE(!(0));
1779 } else if (response == 2) { /* skip */
1780 /* do nothing */
1781 } else {
1782 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1782, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1783 }
1784 skip:
1785 g_error_free (error);
1786 }
1787
1788 *skipped_file = TRUE(!(0));
1789}
1790
1791static void
1792delete_files (CommonJob *job, GList *files, int *files_skipped)
1793{
1794 GList *l;
1795 SourceInfo source_info;
1796 TransferInfo transfer_info;
1797 gboolean skipped_file;
1798 GFile *file = NULL((void*)0);
1799
1800 if (job_aborted (job)) {
1801 return;
1802 }
1803
1804 scan_sources (files,
1805 &source_info,
1806 job,
1807 OP_KIND_DELETE);
1808 if (job_aborted (job)) {
1809 return;
1810 }
1811
1812 g_timer_start (job->time);
1813
1814 memset (&transfer_info, 0, sizeof (transfer_info));
1815 report_delete_progress (job, &source_info, &transfer_info);
1816
1817 for (l = files;
1818 l != NULL((void*)0) && !job_aborted (job);
1819 l = l->next) {
1820 file = l->data;
1821
1822 skipped_file = FALSE(0);
1823 delete_file (job, file,
1824 &skipped_file,
1825 &source_info, &transfer_info,
1826 TRUE(!(0)));
1827 if (skipped_file) {
1828 (*files_skipped)++;
1829 }
1830 }
1831}
1832
1833static void
1834report_trash_progress (CommonJob *job,
1835 int files_trashed,
1836 int total_files)
1837{
1838 int files_left;
1839 char *s;
1840
1841 files_left = total_files - files_trashed;
1842
1843 caja_progress_info_take_status (job->progress,
1844 f (_("Moving files to trash")dcgettext (((void*)0), "Moving files to trash", 5)));
1845
1846 s = f (ngettext ("%'d file left to trash",dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
1847 "%'d files left to trash",dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
1848 files_left)dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
,
1849 files_left);
1850 caja_progress_info_take_details (job->progress, s);
1851
1852 if (total_files != 0) {
1853 caja_progress_info_set_progress (job->progress, files_trashed, total_files);
1854 }
1855}
1856
1857
1858static void
1859trash_files (CommonJob *job, GList *files, int *files_skipped)
1860{
1861 GList *l;
1862 GFile *file;
1863 GList *to_delete;
1864 GError *error;
1865 int total_files, files_trashed;
1866 char *primary, *secondary, *details;
1867 int response;
1868
1869 guint64 mtime;
1870
1871 if (job_aborted (job)) {
1872 return;
1873 }
1874
1875 total_files = g_list_length (files);
1876 files_trashed = 0;
1877
1878 report_trash_progress (job, files_trashed, total_files);
1879
1880 to_delete = NULL((void*)0);
1881 for (l = files;
1882 l != NULL((void*)0) && !job_aborted (job);
1883 l = l->next) {
1884 caja_progress_info_get_ready (job->progress);
1885
1886 file = l->data;
1887
1888 error = NULL((void*)0);
1889
1890 mtime = caja_undostack_manager_get_file_modification_time (file);
1891
1892 if (!g_file_trash (file, job->cancellable, &error)) {
1893 if (job->skip_all_error) {
1894 (*files_skipped)++;
1895 goto skip;
1896 }
1897
1898 if (job->delete_all) {
1899 to_delete = g_list_prepend (to_delete, file);
1900 goto skip;
1901 }
1902
1903 primary = f (_("Cannot move file to trash, do you want to delete immediately?")dcgettext (((void*)0), "Cannot move file to trash, do you want to delete immediately?"
, 5)
);
1904 secondary = f (_("The file \"%B\" cannot be moved to the trash.")dcgettext (((void*)0), "The file \"%B\" cannot be moved to the trash."
, 5)
, file);
1905 details = NULL((void*)0);
1906 if (!IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
1907 details = error->message;
1908 }
1909
1910 response = run_question (job,
1911 primary,
1912 secondary,
1913 details,
1914 (total_files - files_trashed) > 1,
1915 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), DELETE_ALLdcgettext (((void*)0), "Delete _All", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1916 NULL((void*)0));
1917
1918 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1919 ((DeleteJob *) job)->user_cancel = TRUE(!(0));
1920 abort_job (job);
1921 } else if (response == 1) { /* skip all */
1922 (*files_skipped)++;
1923 job->skip_all_error = TRUE(!(0));
1924 } else if (response == 2) { /* skip */
1925 (*files_skipped)++;
1926 } else if (response == 3) { /* delete all */
1927 to_delete = g_list_prepend (to_delete, file);
1928 job->delete_all = TRUE(!(0));
1929 } else if (response == 4) { /* delete */
1930 to_delete = g_list_prepend (to_delete, file);
1931 }
1932
1933 skip:
1934 g_error_free (error);
1935 total_files--;
1936 } else {
1937 caja_file_changes_queue_file_removed (file);
1938
1939 // Start UNDO-REDO
1940 caja_undostack_manager_data_add_trashed_file (job->undo_redo_data, file, mtime);
1941 // End UNDO-REDO
1942
1943 files_trashed++;
1944 report_trash_progress (job, files_trashed, total_files);
1945 }
1946 }
1947
1948 if (to_delete) {
1949 to_delete = g_list_reverse (to_delete);
1950 delete_files (job, to_delete, files_skipped);
1951 g_list_free (to_delete);
1952 }
1953}
1954
1955static gboolean
1956delete_job_done (gpointer user_data)
1957{
1958 DeleteJob *job;
1959
1960 job = user_data;
1961
1962 g_list_free_full (job->files, g_object_unref);
1963
1964 if (job->done_callback) {
1965 GHashTable *debuting_uris;
1966
1967 debuting_uris = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1968 job->done_callback (debuting_uris, job->user_cancel, job->done_callback_data);
1969 g_hash_table_unref (debuting_uris);
1970 }
1971
1972 finalize_common ((CommonJob *)job);
1973
1974 caja_file_changes_consume_changes (TRUE(!(0)));
1975
1976 return FALSE(0);
1977}
1978
1979static gboolean
1980delete_job (GIOSchedulerJob *io_job,
1981 GCancellable *cancellable,
1982 gpointer user_data)
1983{
1984 DeleteJob *job = user_data;
1985 GList *to_trash_files;
1986 GList *to_delete_files;
1987 GList *l;
1988 gboolean confirmed;
1989 CommonJob *common;
1990 gboolean must_confirm_delete_in_trash;
1991 gboolean must_confirm_delete;
1992 gboolean must_confirm_trash;
1993 int files_skipped;
1994 GFile *file = NULL((void*)0);
1995
1996 common = (CommonJob *)job;
1997 common->io_job = io_job;
1998
1999 caja_progress_info_start (job->common.progress);
2000
2001 to_trash_files = NULL((void*)0);
2002 to_delete_files = NULL((void*)0);
2003
2004 must_confirm_delete_in_trash = FALSE(0);
2005 must_confirm_delete = FALSE(0);
2006 must_confirm_trash = FALSE(0);
2007 files_skipped = 0;
2008
2009 for (l = job->files; l != NULL((void*)0); l = l->next) {
2010 file = l->data;
2011
2012 if (job->try_trash &&
2013 g_file_has_uri_scheme (file, "trash")) {
2014 must_confirm_delete_in_trash = TRUE(!(0));
2015 to_delete_files = g_list_prepend (to_delete_files, file);
2016 } else if (can_delete_without_confirm (file)) {
2017 to_delete_files = g_list_prepend (to_delete_files, file);
2018 } else {
2019 if (job->try_trash) {
2020 must_confirm_trash = TRUE(!(0));
2021 to_trash_files = g_list_prepend (to_trash_files, file);
2022 } else {
2023 must_confirm_delete = TRUE(!(0));
2024 to_delete_files = g_list_prepend (to_delete_files, file);
2025 }
2026 }
2027 }
2028
2029 if (to_delete_files != NULL((void*)0)) {
2030 to_delete_files = g_list_reverse (to_delete_files);
2031 confirmed = TRUE(!(0));
2032 if (must_confirm_delete_in_trash) {
2033 confirmed = confirm_delete_from_trash (common, to_delete_files);
2034 } else if (must_confirm_delete) {
2035 confirmed = confirm_delete_directly (common, to_delete_files);
2036 }
2037 if (confirmed) {
2038 delete_files (common, to_delete_files, &files_skipped);
2039 } else {
2040 job->user_cancel = TRUE(!(0));
2041 }
2042 }
2043
2044 if (to_trash_files != NULL((void*)0)) {
2045 to_trash_files = g_list_reverse (to_trash_files);
2046
2047 if (! must_confirm_trash || confirm_trash (common, to_trash_files)) {
2048 trash_files (common, to_trash_files, &files_skipped);
2049 } else {
2050 job->user_cancel = TRUE(!(0));
2051 }
2052 }
2053
2054 g_list_free (to_trash_files);
2055 g_list_free (to_delete_files);
2056
2057 if (files_skipped == g_list_length (job->files)) {
2058 /* User has skipped all files, report user cancel */
2059 job->user_cancel = TRUE(!(0));
2060 }
2061
2062 g_io_scheduler_job_send_to_mainloop_async (io_job,
2063 delete_job_done,
2064 job,
2065 NULL((void*)0));
2066
2067 return FALSE(0);
2068}
2069
2070static void
2071trash_or_delete_internal (GList *files,
2072 GtkWindow *parent_window,
2073 gboolean try_trash,
2074 CajaDeleteCallback done_callback,
2075 gpointer done_callback_data)
2076{
2077 DeleteJob *job;
2078
2079 /* TODO: special case desktop icon link files ... */
2080
2081 job = op_job_new (DeleteJob, parent_window, TRUE, FALSE)((DeleteJob *)(init_common (sizeof(DeleteJob), parent_window,
(!(0)), (0))))
;
2082 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
2083 job->try_trash = try_trash;
2084 job->user_cancel = FALSE(0);
2085 job->done_callback = done_callback;
2086 job->done_callback_data = done_callback_data;
2087
2088 if (try_trash) {
2089 inhibit_power_manager ((CommonJob *)job, _("Trashing Files")dcgettext (((void*)0), "Trashing Files", 5));
2090 } else {
2091 inhibit_power_manager ((CommonJob *)job, _("Deleting Files")dcgettext (((void*)0), "Deleting Files", 5));
2092 }
2093 // Start UNDO-REDO
2094 // FIXME: Disabled, because of missing mechanism to restore a file from trash in a clean way
2095 // see https://www.mail-archive.com/nautilus-list@gnome.org/msg04664.html
2096 if (try_trash && !caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
2097 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_MOVETOTRASH, g_list_length(files));
2098 GFile* src_dir = g_file_get_parent (files->data);
2099 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
2100 }
2101 // End UNDO-REDO
2102
2103 g_io_scheduler_push_job (delete_job,
2104 job,
2105 NULL((void*)0),
2106 0,
2107 NULL((void*)0));
2108}
2109
2110void
2111caja_file_operations_trash_or_delete (GList *files,
2112 GtkWindow *parent_window,
2113 CajaDeleteCallback done_callback,
2114 gpointer done_callback_data)
2115{
2116 trash_or_delete_internal (files, parent_window,
2117 TRUE(!(0)),
2118 done_callback, done_callback_data);
2119}
2120
2121void
2122caja_file_operations_delete (GList *files,
2123 GtkWindow *parent_window,
2124 CajaDeleteCallback done_callback,
2125 gpointer done_callback_data)
2126{
2127 trash_or_delete_internal (files, parent_window,
2128 FALSE(0),
2129 done_callback, done_callback_data);
2130}
2131
2132
2133
2134typedef struct {
2135 gboolean eject;
2136 GMount *mount;
2137 GtkWindow *parent_window;
2138 CajaUnmountCallback callback;
2139 gpointer callback_data;
2140} UnmountData;
2141
2142static void
2143unmount_mount_callback (GObject *source_object,
2144 GAsyncResult *res,
2145 gpointer user_data)
2146{
2147 UnmountData *data = user_data;
2148 GError *error;
2149 gboolean unmounted;
2150
2151 error = NULL((void*)0);
2152 if (data->eject) {
2153 unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object)((((GMount*) (void *) ((source_object))))),
2154 res, &error);
2155 if ((!error) || (unmounted == TRUE(!(0)))){
2156 caja_application_notify_unmount_show (_("It is now safe to remove the drive")dcgettext (((void*)0), "It is now safe to remove the drive", 5
)
);
2157 }
2158
2159 } else {
2160 unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object)((((GMount*) (void *) ((source_object))))),
2161 res, &error);
2162 }
2163
2164 if (! unmounted) {
2165 if (error && error->code != G_IO_ERROR_FAILED_HANDLED) {
2166 char *primary;
2167
2168 if (data->eject) {
2169 primary = f (_("Unable to eject %V")dcgettext (((void*)0), "Unable to eject %V", 5), source_object);
2170 } else {
2171 primary = f (_("Unable to unmount %V")dcgettext (((void*)0), "Unable to unmount %V", 5), source_object);
2172 }
2173 eel_show_error_dialog (primary,
2174 error->message,
2175 data->parent_window);
2176 g_free (primary);
2177 }
2178 }
2179
2180 if (data->callback) {
2181 data->callback (data->callback_data);
2182 }
2183
2184 if (error != NULL((void*)0)) {
2185 g_error_free (error);
2186 }
2187
2188 eel_remove_weak_pointer (&data->parent_window);
2189 g_object_unref (data->mount);
2190 g_free (data);
2191}
2192
2193static void
2194do_unmount (UnmountData *data)
2195{
2196 GMountOperation *mount_op;
2197
2198 mount_op = gtk_mount_operation_new (data->parent_window);
2199 if (data->eject) {
2200 g_mount_eject_with_operation (data->mount,
2201 0,
2202 mount_op,
2203 NULL((void*)0),
2204 unmount_mount_callback,
2205 data);
2206
2207 caja_application_notify_unmount_show (_("Writing data to the drive -- do not unplug")dcgettext (((void*)0), "Writing data to the drive -- do not unplug"
, 5)
);
2208
2209 } else {
2210 g_mount_unmount_with_operation (data->mount,
2211 0,
2212 mount_op,
2213 NULL((void*)0),
2214 unmount_mount_callback,
2215 data);
2216 }
2217 g_object_unref (mount_op);
2218}
2219
2220static gboolean
2221dir_has_files (GFile *dir)
2222{
2223 GFileEnumerator *enumerator;
2224 gboolean res;
2225
2226 res = FALSE(0);
2227
2228 enumerator = g_file_enumerate_children (dir,
2229 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
2230 0,
2231 NULL((void*)0), NULL((void*)0));
2232 if (enumerator) {
2233 GFileInfo *file_info;
2234
2235 file_info = g_file_enumerator_next_file (enumerator, NULL((void*)0), NULL((void*)0));
2236 if (file_info != NULL((void*)0)) {
2237 res = TRUE(!(0));
2238 g_object_unref (file_info);
2239 }
2240
2241 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2242 g_object_unref (enumerator);
2243 }
2244
2245
2246 return res;
2247}
2248
2249static GList *
2250get_trash_dirs_for_mount (GMount *mount)
2251{
2252 GFile *root;
2253 GList *list;
2254
2255 root = g_mount_get_root (mount);
2256 if (root == NULL((void*)0)) {
2257 return NULL((void*)0);
2258 }
2259
2260 list = NULL((void*)0);
2261
2262 if (g_file_is_native (root)) {
2263 GFile *trash;
2264 char *relpath;
2265
2266 relpath = g_strdup_printf (".Trash/%d", getuid ());
2267 trash = g_file_resolve_relative_path (root, relpath);
2268 g_free (relpath);
2269
2270 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2271 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2272
2273 g_object_unref (trash);
2274
2275 relpath = g_strdup_printf (".Trash-%d", getuid ());
2276 trash = g_file_get_child (root, relpath);
2277 g_free (relpath);
2278
2279 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2280 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2281
2282 g_object_unref (trash);
2283 }
2284
2285 g_object_unref (root);
2286
2287 return list;
2288}
2289
2290static gboolean
2291has_trash_files (GMount *mount)
2292{
2293 gboolean res;
2294 GList *dirs, *l;
2295 GFile *dir = NULL((void*)0);
2296
2297 dirs = get_trash_dirs_for_mount (mount);
2298
2299 res = FALSE(0);
2300
2301 for (l = dirs; l != NULL((void*)0); l = l->next) {
2302 dir = l->data;
2303
2304 if (dir_has_files (dir)) {
2305 res = TRUE(!(0));
2306 break;
2307 }
2308 }
2309
2310 g_list_free_full (dirs, g_object_unref);
2311
2312 return res;
2313}
2314
2315
2316static gint
2317prompt_empty_trash (GtkWindow *parent_window)
2318{
2319 gint result;
2320 GtkWidget *dialog;
2321 GdkScreen *screen;
2322
2323 screen = NULL((void*)0);
2324 if (parent_window != NULL((void*)0)) {
2325 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) (void *) ((parent_window))))));
2326 }
2327
2328 /* Do we need to be modal ? */
2329 dialog = gtk_message_dialog_new (NULL((void*)0), GTK_DIALOG_MODAL,
2330 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
2331 _("Do you want to empty the trash before you unmount?")dcgettext (((void*)0), "Do you want to empty the trash before you unmount?"
, 5)
);
2332 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
2333 _("In order to regain the "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2334 "free space on this volume "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2335 "the trash must be emptied. "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2336 "All trashed items on the volume "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2337 "will be permanently lost.")dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
);
2338
2339 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2340 _("Do _not Empty Trash")dcgettext (((void*)0), "Do _not Empty Trash", 5), GTK_RESPONSE_REJECT);
2341
2342 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2343 CANCELdcgettext (((void*)0), "_Cancel", 5), "process-stop", GTK_RESPONSE_CANCEL);
2344
2345 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2346 _("Empty _Trash")dcgettext (((void*)0), "Empty _Trash", 5), GTK_RESPONSE_ACCEPT);
2347
2348 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_ACCEPT);
2349 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), ""); /* as per HIG */
2350 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
2351 if (screen) {
2352 gtk_window_set_screen (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), screen);
2353 }
2354 atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
2355
2356 /* Make transient for the window group */
2357 gtk_widget_realize (dialog);
2358 if (screen != NULL((void*)0)) {
2359 gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog)))))),
2360 gdk_screen_get_root_window (screen));
2361 }
2362
2363 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
2364 gtk_widget_destroy (dialog);
2365 return result;
2366}
2367
2368void
2369caja_file_operations_unmount_mount_full (GtkWindow *parent_window,
2370 GMount *mount,
2371 gboolean eject,
2372 gboolean check_trash,
2373 CajaUnmountCallback callback,
2374 gpointer callback_data)
2375{
2376 UnmountData *data;
2377
2378 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
2379 data->callback = callback;
2380 data->callback_data = callback_data;
2381 if (parent_window) {
2382 data->parent_window = parent_window;
2383 eel_add_weak_pointer (&data->parent_window);
2384
2385 }
2386 data->eject = eject;
2387 data->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
2388
2389 if (check_trash && has_trash_files (mount)) {
2390 int response;
2391
2392 response = prompt_empty_trash (parent_window);
2393
2394 if (response == GTK_RESPONSE_ACCEPT) {
2395 EmptyTrashJob *job;
2396
2397 job = op_job_new (EmptyTrashJob, parent_window, TRUE, FALSE)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
, (!(0)), (0))))
;
2398 job->should_confirm = FALSE(0);
2399 job->trash_dirs = get_trash_dirs_for_mount (mount);
2400 job->done_callback = (CajaOpCallback)do_unmount;
2401 job->done_callback_data = data;
2402 g_io_scheduler_push_job (empty_trash_job,
2403 job,
2404 NULL((void*)0),
2405 0,
2406 NULL((void*)0));
2407 return;
2408 } else if (response == GTK_RESPONSE_CANCEL) {
2409 if (callback) {
2410 callback (callback_data);
2411 }
2412 eel_remove_weak_pointer (&data->parent_window);
2413 g_object_unref (data->mount);
2414 g_free (data);
2415 return;
2416 }
2417 }
2418
2419 do_unmount (data);
2420}
2421
2422void
2423caja_file_operations_unmount_mount (GtkWindow *parent_window,
2424 GMount *mount,
2425 gboolean eject,
2426 gboolean check_trash)
2427{
2428 caja_file_operations_unmount_mount_full (parent_window, mount, eject,
2429 check_trash, NULL((void*)0), NULL((void*)0));
2430}
2431
2432static void
2433mount_callback_data_notify (gpointer data,
2434 GObject *object)
2435{
2436 GMountOperation *mount_op;
2437
2438 mount_op = G_MOUNT_OPERATION (data)((((GMountOperation*) (void *) ((data)))));
2439 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback", NULL((void*)0));
2440 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback-data", NULL((void*)0));
2441}
2442
2443static void
2444volume_mount_cb (GObject *source_object,
2445 GAsyncResult *res,
2446 gpointer user_data)
2447{
2448 CajaMountCallback mount_callback;
2449 GObject *mount_callback_data_object;
2450 GMountOperation *mount_op = user_data;
2451 GError *error;
2452
2453 error = NULL((void*)0);
2454 caja_allow_autorun_for_volume_finish (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))));
2455 if (!g_volume_mount_finish (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))), res, &error)) {
2456 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2457 char *name;
2458 char *primary;
2459
2460 name = g_volume_get_name (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))));
2461 primary = g_strdup_printf (_("Unable to mount %s")dcgettext (((void*)0), "Unable to mount %s", 5), name);
2462 g_free (name);
2463 eel_show_error_dialog (primary,
2464 error->message,
2465 NULL((void*)0));
2466 g_free (primary);
2467 }
2468 g_error_free (error);
2469 }
2470
2471 mount_callback = (CajaMountCallback)
2472 g_object_get_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback");
2473 mount_callback_data_object =
2474 g_object_get_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback-data");
2475
2476 if (mount_callback != NULL((void*)0)) {
2477 (* mount_callback) (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))),
2478 mount_callback_data_object);
2479
2480 if (mount_callback_data_object != NULL((void*)0)) {
2481 g_object_weak_unref (mount_callback_data_object,
2482 mount_callback_data_notify,
2483 mount_op);
2484 }
2485 }
2486
2487 g_object_unref (mount_op);
2488}
2489
2490
2491void
2492caja_file_operations_mount_volume (GtkWindow *parent_window,
2493 GVolume *volume,
2494 gboolean allow_autorun)
2495{
2496 caja_file_operations_mount_volume_full (parent_window, volume,
2497 allow_autorun, NULL((void*)0), NULL((void*)0));
2498}
2499
2500void
2501caja_file_operations_mount_volume_full (GtkWindow *parent_window,
2502 GVolume *volume,
2503 gboolean allow_autorun,
2504 CajaMountCallback mount_callback,
2505 GObject *mount_callback_data_object)
2506{
2507 GMountOperation *mount_op;
2508
2509 mount_op = gtk_mount_operation_new (parent_window);
2510 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2511 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))),
2512 "mount-callback",
2513 mount_callback);
2514
2515 if (mount_callback != NULL((void*)0) &&
2516 mount_callback_data_object != NULL((void*)0)) {
2517 g_object_weak_ref (mount_callback_data_object,
2518 mount_callback_data_notify,
2519 mount_op);
2520 }
2521 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))),
2522 "mount-callback-data",
2523 mount_callback_data_object);
2524
2525 if (allow_autorun)
2526 caja_allow_autorun_for_volume (volume);
2527 g_volume_mount (volume, 0, mount_op, NULL((void*)0), volume_mount_cb, mount_op);
2528}
2529
2530static void
2531report_count_progress (CommonJob *job,
2532 SourceInfo *source_info)
2533{
2534 char *s;
2535
2536 switch (source_info->op) {
2537 default:
2538 case OP_KIND_COPY:
2539 s = f (ngettext("Preparing to copy %'d file (%S)",dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
2540 "Preparing to copy %'d files (%S)",dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
2541 source_info->num_files)dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
,
2542 source_info->num_files, source_info->num_bytes);
2543 break;
2544 case OP_KIND_MOVE:
2545 s = f (ngettext("Preparing to move %'d file (%S)",dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
2546 "Preparing to move %'d files (%S)",dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
2547 source_info->num_files)dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
,
2548 source_info->num_files, source_info->num_bytes);
2549 break;
2550 case OP_KIND_DELETE:
2551 s = f (ngettext("Preparing to delete %'d file (%S)",dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
2552 "Preparing to delete %'d files (%S)",dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
2553 source_info->num_files)dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
,
2554 source_info->num_files, source_info->num_bytes);
2555 break;
2556 case OP_KIND_TRASH:
2557 s = f (ngettext("Preparing to trash %'d file",dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
2558 "Preparing to trash %'d files",dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
2559 source_info->num_files)dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
,
2560 source_info->num_files);
2561 break;
2562 }
2563
2564 caja_progress_info_take_details (job->progress, s);
2565 caja_progress_info_pulse_progress (job->progress);
2566}
2567
2568static void
2569count_file (GFileInfo *info,
2570 CommonJob *job,
2571 SourceInfo *source_info)
2572{
2573 source_info->num_files += 1;
2574 source_info->num_bytes += g_file_info_get_size (info);
2575
2576 if (source_info->num_files_since_progress++ > 100) {
2577 report_count_progress (job, source_info);
2578 source_info->num_files_since_progress = 0;
2579 }
2580}
2581
2582static char *
2583get_scan_primary (OpKind kind)
2584{
2585 switch (kind) {
2586 default:
2587 case OP_KIND_COPY:
2588 return f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
2589 case OP_KIND_MOVE:
2590 return f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
2591 case OP_KIND_DELETE:
2592 return f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
2593 case OP_KIND_TRASH:
2594 return f (_("Error while moving files to trash.")dcgettext (((void*)0), "Error while moving files to trash.", 5
)
);
2595 }
2596}
2597
2598static void
2599scan_dir (GFile *dir,
2600 SourceInfo *source_info,
2601 CommonJob *job,
2602 GQueue *dirs)
2603{
2604 GFileInfo *info;
2605 GError *error;
2606 GFile *subdir;
2607 GFileEnumerator *enumerator;
2608 char *primary, *secondary, *details;
2609 int response;
2610 SourceInfo saved_info;
2611
2612 saved_info = *source_info;
2613
2614 retry:
2615 error = NULL((void*)0);
2616 enumerator = g_file_enumerate_children (dir,
2617 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
2618 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2619 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size"","
2620 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size",
2621 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2622 job->cancellable,
2623 &error);
2624 if (enumerator) {
2625 error = NULL((void*)0);
2626 while ((info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
2627 count_file (info, job, source_info);
2628
2629 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2630 subdir = g_file_get_child (dir,
2631 g_file_info_get_name (info));
2632
2633 /* Push to head, since we want depth-first */
2634 g_queue_push_head (dirs, subdir);
2635 }
2636
2637 g_object_unref (info);
2638 }
2639 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
2640 g_object_unref (enumerator);
2641
2642 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2643 g_error_free (error);
2644 } else if (error) {
2645 primary = get_scan_primary (source_info->op);
2646 details = NULL((void*)0);
2647
2648 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2649 secondary = f (_("Files in the folder \"%B\" cannot be handled because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be handled because you do "
"not have permissions to see them.", 5)
2650 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be handled because you do "
"not have permissions to see them.", 5)
, dir);
2651 } else {
2652 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, dir);
2653 details = error->message;
2654 }
2655
2656 response = run_warning (job,
2657 primary,
2658 secondary,
2659 details,
2660 FALSE(0),
2661 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
2662 NULL((void*)0));
2663
2664 g_error_free (error);
2665
2666 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2667 abort_job (job);
2668 } else if (response == 1) {
2669 *source_info = saved_info;
2670 goto retry;
2671 } else if (response == 2) {
2672 skip_readdir_error (job, dir);
2673 } else {
2674 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2674, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2675 }
2676 }
2677
2678 } else if (job->skip_all_error) {
2679 g_error_free (error);
2680 skip_file (job, dir);
2681 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2682 g_error_free (error);
2683 } else {
2684 primary = get_scan_primary (source_info->op);
2685 details = NULL((void*)0);
2686
2687 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2688 secondary = f (_("The folder \"%B\" cannot be handled because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
2689 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
, dir);
2690 } else {
2691 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, dir);
2692 details = error->message;
2693 }
2694 /* set show_all to TRUE here, as we don't know how many
2695 * files we'll end up processing yet.
2696 */
2697 response = run_warning (job,
2698 primary,
2699 secondary,
2700 details,
2701 TRUE(!(0)),
2702 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2703 NULL((void*)0));
2704
2705 g_error_free (error);
2706
2707 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2708 abort_job (job);
2709 } else if (response == 1 || response == 2) {
2710 if (response == 1) {
2711 job->skip_all_error = TRUE(!(0));
2712 }
2713 skip_file (job, dir);
2714 } else if (response == 3) {
2715 goto retry;
2716 } else {
2717 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2717, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2718 }
2719 }
2720}
2721
2722static void
2723scan_file (GFile *file,
2724 SourceInfo *source_info,
2725 CommonJob *job)
2726{
2727 GFileInfo *info;
2728 GError *error;
2729 GQueue *dirs;
2730 GFile *dir;
2731 char *primary;
2732 char *secondary;
2733 char *details;
2734 int response;
2735
2736 dirs = g_queue_new ();
2737
2738 retry:
2739 error = NULL((void*)0);
2740 info = g_file_query_info (file,
2741 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2742 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size"","
2743 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size",
2744 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2745 job->cancellable,
2746 &error);
2747
2748 if (info) {
2749 count_file (info, job, source_info);
2750
2751 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2752 g_queue_push_head (dirs, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)));
2753 }
2754
2755 g_object_unref (info);
2756 } else if (job->skip_all_error) {
2757 g_error_free (error);
2758 skip_file (job, file);
2759 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2760 g_error_free (error);
2761 } else {
2762 primary = get_scan_primary (source_info->op);
2763 details = NULL((void*)0);
2764
2765 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2766 secondary = f (_("The file \"%B\" cannot be handled because you do not have "dcgettext (((void*)0), "The file \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
2767 "permissions to read it.")dcgettext (((void*)0), "The file \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
, file);
2768 } else {
2769 secondary = f (_("There was an error getting information about \"%B\".")dcgettext (((void*)0), "There was an error getting information about \"%B\"."
, 5)
, file);
2770 details = error->message;
2771 }
2772 /* set show_all to TRUE here, as we don't know how many
2773 * files we'll end up processing yet.
2774 */
2775 response = run_warning (job,
2776 primary,
2777 secondary,
2778 details,
2779 TRUE(!(0)),
2780 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2781 NULL((void*)0));
2782
2783 g_error_free (error);
2784
2785 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2786 abort_job (job);
2787 } else if (response == 1 || response == 2) {
2788 if (response == 1) {
2789 job->skip_all_error = TRUE(!(0));
2790 }
2791 skip_file (job, file);
2792 } else if (response == 3) {
2793 goto retry;
2794 } else {
2795 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2795, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2796 }
2797 }
2798
2799 while (!job_aborted (job) &&
2800 (dir = g_queue_pop_head (dirs)) != NULL((void*)0)) {
2801 scan_dir (dir, source_info, job, dirs);
2802 g_object_unref (dir);
2803 }
2804
2805 /* Free all from queue if we exited early */
2806 g_queue_foreach (dirs, (GFunc)g_object_unref, NULL((void*)0));
2807 g_queue_free (dirs);
2808}
2809
2810static void
2811scan_sources (GList *files,
2812 SourceInfo *source_info,
2813 CommonJob *job,
2814 OpKind kind)
2815{
2816 GList *l;
2817 GFile *file = NULL((void*)0);
2818
2819 memset (source_info, 0, sizeof (SourceInfo));
2820 source_info->op = kind;
2821
2822 report_count_progress (job, source_info);
2823
2824 for (l = files; l != NULL((void*)0) && !job_aborted (job); l = l->next) {
2825 file = l->data;
2826
2827 scan_file (file,
2828 source_info,
2829 job);
2830 }
2831
2832 /* Make sure we report the final count */
2833 report_count_progress (job, source_info);
2834}
2835
2836static void
2837verify_destination (CommonJob *job,
2838 GFile *dest,
2839 char **dest_fs_id,
2840 goffset required_size)
2841{
2842 GFileInfo *info, *fsinfo;
2843 GError *error;
2844 guint64 free_size;
2845 char *primary, *secondary, *details;
2846 int response;
2847 GFileType file_type;
2848
2849 if (dest_fs_id) {
2850 *dest_fs_id = NULL((void*)0);
2851 }
2852
2853 retry:
2854
2855 error = NULL((void*)0);
2856 info = g_file_query_info (dest,
2857 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2858 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
2859 0,
2860 job->cancellable,
2861 &error);
2862
2863 if (info == NULL((void*)0)) {
2864 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2865 g_error_free (error);
2866 return;
2867 }
2868
2869 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2870 details = NULL((void*)0);
2871
2872 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2873 secondary = f (_("You do not have permissions to access the destination folder.")dcgettext (((void*)0), "You do not have permissions to access the destination folder."
, 5)
);
2874 } else {
2875 secondary = f (_("There was an error getting information about the destination.")dcgettext (((void*)0), "There was an error getting information about the destination."
, 5)
);
2876 details = error->message;
2877 }
2878
2879 response = run_error (job,
2880 primary,
2881 secondary,
2882 details,
2883 FALSE(0),
2884 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2885 NULL((void*)0));
2886
2887 g_error_free (error);
2888
2889 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2890 abort_job (job);
2891 } else if (response == 1) {
2892 goto retry;
2893 } else {
2894 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2894, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2895 }
2896
2897 return;
2898 }
2899
2900 file_type = g_file_info_get_file_type (info);
2901
2902 if (dest_fs_id) {
2903 *dest_fs_id =
2904 g_strdup (g_file_info_get_attribute_string (info,g_strdup_inline (g_file_info_get_attribute_string (info, "id::filesystem"
))
2905 G_FILE_ATTRIBUTE_ID_FILESYSTEM))g_strdup_inline (g_file_info_get_attribute_string (info, "id::filesystem"
))
;
2906 }
2907
2908 g_object_unref (info);
2909
2910 if (file_type != G_FILE_TYPE_DIRECTORY) {
2911 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2912 secondary = f (_("The destination is not a folder.")dcgettext (((void*)0), "The destination is not a folder.", 5));
2913
2914 response = run_error (job,
Value stored to 'response' is never read
2915 primary,
2916 secondary,
2917 NULL((void*)0),
2918 FALSE(0),
2919 CANCELdcgettext (((void*)0), "_Cancel", 5),
2920 NULL((void*)0));
2921
2922 abort_job (job);
2923 return;
2924 }
2925
2926 fsinfo = g_file_query_filesystem_info (dest,
2927 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free"","
2928 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly",
2929 job->cancellable,
2930 NULL((void*)0));
2931 if (fsinfo == NULL((void*)0)) {
2932 /* All sorts of things can go wrong getting the fs info (like not supported)
2933 * only check these things if the fs returns them
2934 */
2935 return;
2936 }
2937
2938 if (required_size > 0 &&
2939 g_file_info_has_attribute (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
2940 free_size = g_file_info_get_attribute_uint64 (fsinfo,
2941 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
2942
2943 if (free_size < required_size) {
2944 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2945 secondary = f(_("There is not enough space on the destination. Try to remove files to make space.")dcgettext (((void*)0), "There is not enough space on the destination. Try to remove files to make space."
, 5)
);
2946
2947 details = f (_("There is %S available, but %S is required.")dcgettext (((void*)0), "There is %S available, but %S is required."
, 5)
, free_size, required_size);
2948
2949 response = run_warning (job,
2950 primary,
2951 secondary,
2952 details,
2953 FALSE(0),
2954 CANCELdcgettext (((void*)0), "_Cancel", 5),
2955 COPY_FORCEdcgettext (((void*)0), "Copy _Anyway", 5),
2956 RETRYdcgettext (((void*)0), "_Retry", 5),
2957 NULL((void*)0));
2958
2959 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2960 abort_job (job);
2961 } else if (response == 2) {
2962 goto retry;
2963 } else if (response == 1) {
2964 /* We are forced to copy - just fall through ... */
2965 } else {
2966 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2966, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2967 }
2968 }
2969 }
2970
2971 if (!job_aborted (job) &&
2972 g_file_info_get_attribute_boolean (fsinfo,
2973 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly")) {
2974 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2975 secondary = f (_("The destination is read-only.")dcgettext (((void*)0), "The destination is read-only.", 5));
2976
2977 response = run_error (job,
2978 primary,
2979 secondary,
2980 NULL((void*)0),
2981 FALSE(0),
2982 CANCELdcgettext (((void*)0), "_Cancel", 5),
2983 NULL((void*)0));
2984
2985 g_error_free (error);
2986
2987 abort_job (job);
2988 }
2989
2990 g_object_unref (fsinfo);
2991}
2992
2993static void
2994report_copy_progress (CopyMoveJob *copy_job,
2995 SourceInfo *source_info,
2996 TransferInfo *transfer_info)
2997{
2998 int files_left;
2999 goffset total_size;
3000 double elapsed, transfer_rate;
3001 guint64 now;
3002 CommonJob *job;
3003 gboolean is_move;
3004
3005 job = (CommonJob *)copy_job;
3006
3007 is_move = copy_job->is_move;
3008
3009 now = g_get_monotonic_time ();
3010
3011 if (transfer_info->last_report_time != 0 &&
3012 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
3013 return;
3014 }
3015 transfer_info->last_report_time = now;
3016
3017 files_left = source_info->num_files - transfer_info->num_files;
3018
3019 /* Races and whatnot could cause this to be negative... */
3020 if (files_left < 0) {
3021 files_left = 1;
3022 }
3023
3024 if (files_left != transfer_info->last_reported_files_left ||
3025 transfer_info->last_reported_files_left == 0) {
3026 /* Avoid changing this unless files_left changed since last time */
3027 transfer_info->last_reported_files_left = files_left;
3028
3029 if (source_info->num_files == 1) {
3030 if (copy_job->destination != NULL((void*)0)) {
3031 caja_progress_info_take_status (job->progress,
3032 f (is_move ?
3033 _("Moving \"%B\" to \"%B\"")dcgettext (((void*)0), "Moving \"%B\" to \"%B\"", 5):
3034 _("Copying \"%B\" to \"%B\"")dcgettext (((void*)0), "Copying \"%B\" to \"%B\"", 5),
3035 (GFile *)copy_job->files->data,
3036 copy_job->destination));
3037 } else {
3038 caja_progress_info_take_status (job->progress,
3039 f (_("Duplicating \"%B\"")dcgettext (((void*)0), "Duplicating \"%B\"", 5),
3040 (GFile *)copy_job->files->data));
3041 }
3042 } else if (copy_job->files != NULL((void*)0) &&
3043 copy_job->files->next == NULL((void*)0)) {
3044 if (copy_job->destination != NULL((void*)0)) {
3045 caja_progress_info_take_status (job->progress,
3046 f (is_move?
3047 ngettext ("Moving %'d file (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3048 "Moving %'d files (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3049 files_left)dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3050 :
3051 ngettext ("Copying %'d file (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
3052 "Copying %'d files (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
3053 files_left)dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
,
3054 files_left,
3055 (GFile *)copy_job->files->data,
3056 copy_job->destination));
3057 } else {
3058 caja_progress_info_take_status (job->progress,
3059 f (ngettext ("Duplicating %'d file (in \"%B\")",dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
3060 "Duplicating %'d files (in \"%B\")",dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
3061 files_left)dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
,
3062 files_left,
3063 (GFile *)copy_job->files->data));
3064 }
3065 } else {
3066 if (copy_job->destination != NULL((void*)0)) {
3067 caja_progress_info_take_status (job->progress,
3068 f (is_move?
3069 ngettext ("Moving %'d file to \"%B\"",dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3070 "Moving %'d files to \"%B\"",dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3071 files_left)dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3072 :
3073 ngettext ("Copying %'d file to \"%B\"",dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
3074 "Copying %'d files to \"%B\"",dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
3075 files_left)dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
,
3076 files_left, copy_job->destination));
3077 } else {
3078 caja_progress_info_take_status (job->progress,
3079 f (ngettext ("Duplicating %'d file",dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
3080 "Duplicating %'d files",dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
3081 files_left)dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
,
3082 files_left));
3083 }
3084 }
3085 }
3086
3087 total_size = MAX (source_info->num_bytes, transfer_info->num_bytes)(((source_info->num_bytes) > (transfer_info->num_bytes
)) ? (source_info->num_bytes) : (transfer_info->num_bytes
))
;
3088
3089 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
3090 transfer_rate = 0;
3091 if (elapsed > 0) {
3092 transfer_rate = transfer_info->num_bytes / elapsed;
3093 }
3094
3095 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15 &&
3096 transfer_rate > 0) {
3097 char *s;
3098 /* Translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */
3099 s = f (_("%S of %S")dcgettext (((void*)0), "%S of %S", 5), transfer_info->num_bytes, total_size);
3100 caja_progress_info_take_details (job->progress, s);
3101 } else {
3102 int remaining_time;
3103 char *s;
3104
3105 remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate;
3106
3107 /* Translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like
3108 * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)"
3109 *
3110 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
3111 */
3112 s = f (ngettext ("%S of %S \xE2\x80\x94 %T left (%S/sec)",dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
3113 "%S of %S \xE2\x80\x94 %T left (%S/sec)",dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
3114 seconds_count_format_time_units (remaining_time))dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
,
3115 transfer_info->num_bytes, total_size,
3116 remaining_time,
3117 (goffset)transfer_rate);
3118 caja_progress_info_take_details (job->progress, s);
3119 }
3120
3121 caja_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size);
3122}
3123
3124static int
3125get_max_name_length (GFile *file_dir)
3126{
3127 int max_length;
3128 char *dir;
3129 long max_path;
3130 long max_name;
3131
3132 max_length = -1;
3133
3134 if (!g_file_has_uri_scheme (file_dir, "file"))
3135 return max_length;
3136
3137 dir = g_file_get_path (file_dir);
3138 if (!dir)
3139 return max_length;
3140
3141 max_path = pathconf (dir, _PC_PATH_MAX_PC_PATH_MAX);
3142 max_name = pathconf (dir, _PC_NAME_MAX_PC_NAME_MAX);
3143
3144 if (max_name == -1 && max_path == -1) {
3145 max_length = -1;
3146 } else if (max_name == -1 && max_path != -1) {
3147 max_length = max_path - (strlen (dir) + 1);
3148 } else if (max_name != -1 && max_path == -1) {
3149 max_length = max_name;
3150 } else {
3151 int leftover;
3152
3153 leftover = max_path - (strlen (dir) + 1);
3154
3155 max_length = MIN (leftover, max_name)(((leftover) < (max_name)) ? (leftover) : (max_name));
3156 }
3157
3158 g_free (dir);
3159
3160 return max_length;
3161}
3162
3163#define FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>" "/:;*?\"<>"
3164
3165static gboolean
3166str_replace (char *str,
3167 const char *chars_to_replace,
3168 char replacement)
3169{
3170 gboolean success;
3171 int i;
3172
3173 success = FALSE(0);
3174 for (i = 0; str[i] != '\0'; i++) {
3175 if (strchr (chars_to_replace, str[i])) {
3176 success = TRUE(!(0));
3177 str[i] = replacement;
3178 }
3179 }
3180
3181 return success;
3182}
3183
3184static gboolean
3185make_file_name_valid_for_dest_fs (char *filename,
3186 const char *dest_fs_type)
3187{
3188 if (dest_fs_type != NULL((void*)0) && filename != NULL((void*)0)) {
3189 if (!strcmp (dest_fs_type, "fat") ||
3190 !strcmp (dest_fs_type, "vfat") ||
3191 !strcmp (dest_fs_type, "msdos") ||
3192 !strcmp (dest_fs_type, "msdosfs")) {
3193 gboolean ret;
3194 int i, old_len;
3195
3196 ret = str_replace (filename, FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>", '_');
3197
3198 old_len = strlen (filename);
3199 for (i = 0; i < old_len; i++) {
3200 if (filename[i] != ' ') {
3201 g_strchomp (filename);
3202 ret |= (old_len != strlen (filename));
3203 break;
3204 }
3205 }
3206
3207 return ret;
3208 }
3209 }
3210
3211 return FALSE(0);
3212}
3213
3214static GFile *
3215get_unique_target_file (GFile *src,
3216 GFile *dest_dir,
3217 gboolean same_fs,
3218 const char *dest_fs_type,
3219 int count)
3220{
3221 char *new_name;
3222 GFileInfo *info;
3223 GFile *dest;
3224 int max_length;
3225
3226 max_length = get_max_name_length (dest_dir);
3227
3228 dest = NULL((void*)0);
3229 info = g_file_query_info (src,
3230 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3231 0, NULL((void*)0), NULL((void*)0));
3232 if (info != NULL((void*)0)) {
3233 const char *editname;
3234
3235 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3236
3237 if (editname != NULL((void*)0)) {
3238 new_name = get_duplicate_name (editname, count, max_length);
3239 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3240 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3241 g_free (new_name);
3242 }
3243
3244 g_object_unref (info);
3245 }
3246
3247 if (dest == NULL((void*)0)) {
3248 char *basename;
3249
3250 basename = g_file_get_basename (src);
3251
3252 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3253 new_name = get_duplicate_name (basename, count, max_length);
3254 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3255 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3256 g_free (new_name);
3257 }
3258
3259 if (dest == NULL((void*)0)) {
3260 const char *end;
3261
3262 end = strrchr (basename, '.');
3263 if (end != NULL((void*)0)) {
3264 count += atoi (end + 1);
3265 }
3266 new_name = g_strdup_printf ("%s.%d", basename, count);
3267 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3268 dest = g_file_get_child (dest_dir, new_name);
3269 g_free (new_name);
3270 }
3271
3272 g_free (basename);
3273 }
3274
3275 return dest;
3276}
3277
3278static GFile *
3279get_target_file_for_link (GFile *src,
3280 GFile *dest_dir,
3281 const char *dest_fs_type,
3282 int count)
3283{
3284 char *new_name;
3285 GFileInfo *info;
3286 GFile *dest;
3287 int max_length;
3288
3289 max_length = get_max_name_length (dest_dir);
3290
3291 dest = NULL((void*)0);
3292 info = g_file_query_info (src,
3293 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3294 0, NULL((void*)0), NULL((void*)0));
3295 if (info != NULL((void*)0)) {
3296 const char *editname;
3297
3298 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3299
3300 if (editname != NULL((void*)0)) {
3301 new_name = get_link_name (editname, count, max_length);
3302 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3303 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3304 g_free (new_name);
3305 }
3306
3307 g_object_unref (info);
3308 }
3309
3310 if (dest == NULL((void*)0)) {
3311 char *basename;
3312
3313 basename = g_file_get_basename (src);
3314 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3315
3316 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3317 new_name = get_link_name (basename, count, max_length);
3318 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3319 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3320 g_free (new_name);
3321 }
3322
3323 if (dest == NULL((void*)0)) {
3324 if (count == 1) {
3325 new_name = g_strdup_printf ("%s.lnk", basename);
3326 } else {
3327 new_name = g_strdup_printf ("%s.lnk%d", basename, count);
3328 }
3329 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3330 dest = g_file_get_child (dest_dir, new_name);
3331 g_free (new_name);
3332 }
3333
3334 g_free (basename);
3335 }
3336
3337 return dest;
3338}
3339
3340static GFile *
3341get_target_file (GFile *src,
3342 GFile *dest_dir,
3343 const char *dest_fs_type,
3344 gboolean same_fs)
3345{
3346 GFile *dest;
3347
3348 dest = NULL((void*)0);
3349 if (!same_fs) {
3350 GFileInfo *info;
3351
3352 info = g_file_query_info (src,
3353 G_FILE_ATTRIBUTE_STANDARD_COPY_NAME"standard::copy-name",
3354 0, NULL((void*)0), NULL((void*)0));
3355
3356 if (info) {
3357 char *copyname;
3358
3359 copyname = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME))g_strdup_inline (g_file_info_get_attribute_string (info, "standard::copy-name"
))
;
3360
3361 if (copyname) {
3362 make_file_name_valid_for_dest_fs (copyname, dest_fs_type);
3363 dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL((void*)0));
3364 g_free (copyname);
3365 }
3366
3367 g_object_unref (info);
3368 }
3369 }
3370
3371 if (dest == NULL((void*)0)) {
3372 char *basename;
3373
3374 basename = g_file_get_basename (src);
3375 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3376 dest = g_file_get_child (dest_dir, basename);
3377 g_free (basename);
3378 }
3379
3380 return dest;
3381}
3382
3383static gboolean
3384has_fs_id (GFile *file, const char *fs_id)
3385{
3386 GFileInfo *info;
3387 gboolean res;
3388
3389 res = FALSE(0);
3390 info = g_file_query_info (file,
3391 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
3392 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3393 NULL((void*)0), NULL((void*)0));
3394
3395 if (info) {
3396 const char *id;
3397
3398 id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
3399
3400 if (id && strcmp (id, fs_id) == 0) {
3401 res = TRUE(!(0));
3402 }
3403
3404 g_object_unref (info);
3405 }
3406
3407 return res;
3408}
3409
3410static gboolean
3411is_dir (GFile *file)
3412{
3413 GFileInfo *info;
3414 gboolean res;
3415
3416 res = FALSE(0);
3417 info = g_file_query_info (file,
3418 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
3419 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3420 NULL((void*)0), NULL((void*)0));
3421 if (info) {
3422 res = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
3423 g_object_unref (info);
3424 }
3425
3426 return res;
3427}
3428
3429static void copy_move_file (CopyMoveJob *job,
3430 GFile *src,
3431 GFile *dest_dir,
3432 gboolean same_fs,
3433 gboolean unique_names,
3434 char **dest_fs_type,
3435 SourceInfo *source_info,
3436 TransferInfo *transfer_info,
3437 GHashTable *debuting_files,
3438 GdkPoint *point,
3439 gboolean overwrite,
3440 gboolean *skipped_file,
3441 gboolean readonly_source_fs,
3442 gboolean last_item);
3443
3444typedef enum {
3445 CREATE_DEST_DIR_RETRY,
3446 CREATE_DEST_DIR_FAILED,
3447 CREATE_DEST_DIR_SUCCESS
3448} CreateDestDirResult;
3449
3450static CreateDestDirResult
3451create_dest_dir (CommonJob *job,
3452 GFile *src,
3453 GFile **dest,
3454 gboolean same_fs,
3455 char **dest_fs_type)
3456{
3457 GError *error;
3458 GFile *new_dest, *dest_dir;
3459 char *primary, *secondary, *details;
3460 int response;
3461 gboolean handled_invalid_filename;
3462
3463 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
3464
3465 retry:
3466 /* First create the directory, then copy stuff to it before
3467 copying the attributes, because we need to be sure we can write to it */
3468
3469 error = NULL((void*)0);
3470 if (!g_file_make_directory (*dest, job->cancellable, &error)) {
3471 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3472 g_error_free (error);
3473 return CREATE_DEST_DIR_FAILED;
3474 } else if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
3475 !handled_invalid_filename) {
3476 handled_invalid_filename = TRUE(!(0));
3477
3478 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_61
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_61 = 1; else
_g_boolean_var_61 = 0; _g_boolean_var_61; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 3478, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
3479
3480 dest_dir = g_file_get_parent (*dest);
3481
3482 if (dest_dir != NULL((void*)0)) {
3483 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
3484
3485 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
3486 g_object_unref (dest_dir);
3487
3488 if (!g_file_equal (*dest, new_dest)) {
3489 g_object_unref (*dest);
3490 *dest = new_dest;
3491 g_error_free (error);
3492 return CREATE_DEST_DIR_RETRY;
3493 } else {
3494 g_object_unref (new_dest);
3495 }
3496 }
3497 }
3498
3499 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3500 details = NULL((void*)0);
3501
3502 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3503 secondary = f (_("The folder \"%B\" cannot be copied because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to create it in the destination.", 5)
3504 "permissions to create it in the destination.")dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to create it in the destination.", 5)
, src);
3505 } else {
3506 secondary = f (_("There was an error creating the folder \"%B\".")dcgettext (((void*)0), "There was an error creating the folder \"%B\"."
, 5)
, src);
3507 details = error->message;
3508 }
3509
3510 response = run_warning (job,
3511 primary,
3512 secondary,
3513 details,
3514 FALSE(0),
3515 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
3516 NULL((void*)0));
3517
3518 g_error_free (error);
3519
3520 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3521 abort_job (job);
3522 } else if (response == 1) {
3523 /* Skip: Do Nothing */
3524 } else if (response == 2) {
3525 goto retry;
3526 } else {
3527 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3527, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3528 }
3529 return CREATE_DEST_DIR_FAILED;
3530 }
3531 // Start UNDO-REDO
3532 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, *dest);
3533 // End UNDO-REDO
3534 caja_file_changes_queue_file_added (*dest);
3535 return CREATE_DEST_DIR_SUCCESS;
3536}
3537
3538/* a return value of FALSE means retry, i.e.
3539 * the destination has changed and the source
3540 * is expected to re-try the preceeding
3541 * g_file_move() or g_file_copy() call with
3542 * the new destination.
3543 */
3544static gboolean
3545copy_move_directory (CopyMoveJob *copy_job,
3546 GFile *src,
3547 GFile **dest,
3548 gboolean same_fs,
3549 gboolean create_dest,
3550 char **parent_dest_fs_type,
3551 SourceInfo *source_info,
3552 TransferInfo *transfer_info,
3553 GHashTable *debuting_files,
3554 gboolean *skipped_file,
3555 gboolean readonly_source_fs,
3556 gboolean last_item_above)
3557{
3558 GFileInfo *info, *nextinfo;
3559 GError *error;
3560 GFile *src_file;
3561 GFileEnumerator *enumerator;
3562 char *primary, *secondary, *details;
3563 char *dest_fs_type;
3564 int response;
3565 gboolean skip_error;
3566 gboolean local_skipped_file;
3567 CommonJob *job;
3568 GFileCopyFlags flags;
3569 gboolean last_item;
3570
3571 job = (CommonJob *)copy_job;
3572
3573 if (create_dest) {
3574 switch (create_dest_dir (job, src, dest, same_fs, parent_dest_fs_type)) {
3575 case CREATE_DEST_DIR_RETRY:
3576 /* next time copy_move_directory() is called,
3577 * create_dest will be FALSE if a directory already
3578 * exists under the new name (i.e. WOULD_RECURSE)
3579 */
3580 return FALSE(0);
3581
3582 case CREATE_DEST_DIR_FAILED:
3583 *skipped_file = TRUE(!(0));
3584 return TRUE(!(0));
3585
3586 case CREATE_DEST_DIR_SUCCESS:
3587 default:
3588 break;
3589 }
3590
3591 if (debuting_files) {
3592 g_hash_table_replace (debuting_files, g_object_ref (*dest)((__typeof__ (*dest)) (g_object_ref) (*dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
3593 }
3594
3595 }
3596
3597 local_skipped_file = FALSE(0);
3598 dest_fs_type = NULL((void*)0);
3599
3600 skip_error = should_skip_readdir_error (job, src);
3601 retry:
3602 error = NULL((void*)0);
3603 enumerator = g_file_enumerate_children (src,
3604 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3605 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3606 job->cancellable,
3607 &error);
3608 if (enumerator) {
3609 error = NULL((void*)0);
3610
3611 nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error);
3612 while (!job_aborted (job) &&
3613 (info = nextinfo) != NULL((void*)0)) {
3614 caja_progress_info_get_ready (job->progress);
3615
3616 nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error);
3617 src_file = g_file_get_child (src,
3618 g_file_info_get_name (info));
3619
3620 last_item = (last_item_above) && (!nextinfo);
3621 copy_move_file (copy_job, src_file, *dest, same_fs, FALSE(0), &dest_fs_type,
3622 source_info, transfer_info, NULL((void*)0), NULL((void*)0), FALSE(0), &local_skipped_file,
3623 readonly_source_fs, last_item);
3624 g_object_unref (src_file);
3625 g_object_unref (info);
3626 }
3627 if (nextinfo)
3628 g_object_unref (nextinfo);
3629
3630 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3631 g_object_unref (enumerator);
3632
3633 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3634 g_error_free (error);
3635 } else if (error) {
3636 if (copy_job->is_move) {
3637 primary = f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
3638 } else {
3639 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3640 }
3641 details = NULL((void*)0);
3642
3643 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3644 secondary = f (_("Files in the folder \"%B\" cannot be copied because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be copied because you do "
"not have permissions to see them.", 5)
3645 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be copied because you do "
"not have permissions to see them.", 5)
, src);
3646 } else {
3647 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, src);
3648 details = error->message;
3649 }
3650
3651 response = run_warning (job,
3652 primary,
3653 secondary,
3654 details,
3655 FALSE(0),
3656 CANCELdcgettext (((void*)0), "_Cancel", 5), _("_Skip files")dcgettext (((void*)0), "_Skip files", 5),
3657 NULL((void*)0));
3658
3659 g_error_free (error);
3660
3661 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3662 abort_job (job);
3663 } else if (response == 1) {
3664 /* Skip: Do Nothing */
3665 local_skipped_file = TRUE(!(0));
3666 } else {
3667 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3667, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3668 }
3669 }
3670
3671 /* Count the copied directory as a file */
3672 transfer_info->num_files ++;
3673 report_copy_progress (copy_job, source_info, transfer_info);
3674
3675 if (debuting_files) {
3676 g_hash_table_replace (debuting_files, g_object_ref (*dest)((__typeof__ (*dest)) (g_object_ref) (*dest)), GINT_TO_POINTER (create_dest)((gpointer) (glong) (create_dest)));
3677 }
3678 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3679 g_error_free (error);
3680 } else {
3681 if (copy_job->is_move) {
3682 primary = f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
3683 } else {
3684 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3685 }
3686 details = NULL((void*)0);
3687
3688 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3689 secondary = f (_("The folder \"%B\" cannot be copied because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to read it.", 5)
3690 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to read it.", 5)
, src);
3691 } else {
3692 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, src);
3693 details = error->message;
3694 }
3695
3696 response = run_warning (job,
3697 primary,
3698 secondary,
3699 details,
3700 FALSE(0),
3701 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
3702 NULL((void*)0));
3703
3704 g_error_free (error);
3705
3706 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3707 abort_job (job);
3708 } else if (response == 1) {
3709 /* Skip: Do Nothing */
3710 local_skipped_file = TRUE(!(0));
3711 } else if (response == 2) {
3712 goto retry;
3713 } else {
3714 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3714, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3715 }
3716 }
3717
3718 if (create_dest) {
3719 flags = (readonly_source_fs) ? G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_PERMS
3720 : G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA;
3721 /* Ignore errors here. Failure to copy metadata is not a hard error */
3722 g_file_copy_attributes (src, *dest,
3723 flags,
3724 job->cancellable, NULL((void*)0));
3725 }
3726
3727 if (!job_aborted (job) && copy_job->is_move &&
3728 /* Don't delete source if there was a skipped file */
3729 !local_skipped_file) {
3730 if (!g_file_delete (src, job->cancellable, &error)) {
3731 if (job->skip_all_error) {
3732 goto skip;
3733 }
3734 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
3735 secondary = f (_("Could not remove the source folder.")dcgettext (((void*)0), "Could not remove the source folder.",
5)
);
3736 details = error->message;
3737
3738 response = run_warning (job,
3739 primary,
3740 secondary,
3741 details,
3742 (source_info->num_files - transfer_info->num_files) > 1,
3743 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3744 NULL((void*)0));
3745
3746 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3747 abort_job (job);
3748 } else if (response == 1) { /* skip all */
3749 job->skip_all_error = TRUE(!(0));
3750 local_skipped_file = TRUE(!(0));
3751 } else if (response == 2) { /* skip */
3752 local_skipped_file = TRUE(!(0));
3753 } else {
3754 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3754, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3755 }
3756
3757 skip:
3758 g_error_free (error);
3759 }
3760 }
3761
3762 if (local_skipped_file) {
3763 *skipped_file = TRUE(!(0));
3764 }
3765
3766 g_free (dest_fs_type);
3767 return TRUE(!(0));
3768}
3769
3770static gboolean
3771remove_target_recursively (CommonJob *job,
3772 GFile *src,
3773 GFile *toplevel_dest,
3774 GFile *file)
3775{
3776 GFileEnumerator *enumerator;
3777 GError *error;
3778 GFile *child;
3779 gboolean stop;
3780 char *primary, *secondary, *details;
3781 int response;
3782 GFileInfo *info;
3783
3784 stop = FALSE(0);
3785
3786 error = NULL((void*)0);
3787 enumerator = g_file_enumerate_children (file,
3788 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3789 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3790 job->cancellable,
3791 &error);
3792 if (enumerator) {
3793 error = NULL((void*)0);
3794
3795 while (!job_aborted (job) &&
3796 (info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
3797 child = g_file_get_child (file,
3798 g_file_info_get_name (info));
3799 if (!remove_target_recursively (job, src, toplevel_dest, child)) {
3800 stop = TRUE(!(0));
3801 break;
3802 }
3803 g_object_unref (child);
3804 g_object_unref (info);
3805 }
3806 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3807 g_object_unref (enumerator);
3808
3809 } else if (IS_IO_ERROR (error, NOT_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_DIRECTORY))
) {
3810 /* Not a dir, continue */
3811 g_error_free (error);
3812
3813 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3814 g_error_free (error);
3815 } else {
3816 if (job->skip_all_error) {
3817 goto skip1;
3818 }
3819
3820 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
3821 secondary = f (_("Could not remove files from the already existing folder %F.")dcgettext (((void*)0), "Could not remove files from the already existing folder %F."
, 5)
, file);
3822 details = error->message;
3823
3824 /* set show_all to TRUE here, as we don't know how many
3825 * files we'll end up processing yet.
3826 */
3827 response = run_warning (job,
3828 primary,
3829 secondary,
3830 details,
3831 TRUE(!(0)),
3832 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3833 NULL((void*)0));
3834
3835 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3836 abort_job (job);
3837 } else if (response == 1) { /* skip all */
3838 job->skip_all_error = TRUE(!(0));
3839 } else if (response == 2) { /* skip */
3840 /* do nothing */
3841 } else {
3842 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3842, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3843 }
3844 skip1:
3845 g_error_free (error);
3846
3847 stop = TRUE(!(0));
3848 }
3849
3850 if (stop) {
3851 return FALSE(0);
3852 }
3853
3854 error = NULL((void*)0);
3855
3856 if (!g_file_delete (file, job->cancellable, &error)) {
3857 if (job->skip_all_error ||
3858 IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3859 goto skip2;
3860 }
3861 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
3862 secondary = f (_("Could not remove the already existing file %F.")dcgettext (((void*)0), "Could not remove the already existing file %F."
, 5)
, file);
3863 details = error->message;
3864
3865 /* set show_all to TRUE here, as we don't know how many
3866 * files we'll end up processing yet.
3867 */
3868 response = run_warning (job,
3869 primary,
3870 secondary,
3871 details,
3872 TRUE(!(0)),
3873 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3874 NULL((void*)0));
3875
3876 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3877 abort_job (job);
3878 } else if (response == 1) { /* skip all */
3879 job->skip_all_error = TRUE(!(0));
3880 } else if (response == 2) { /* skip */
3881 /* do nothing */
3882 } else {
3883 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3883, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3884 }
3885
3886 skip2:
3887 g_error_free (error);
3888
3889 return FALSE(0);
3890 }
3891 caja_file_changes_queue_file_removed (file);
3892
3893 return TRUE(!(0));
3894
3895}
3896
3897typedef struct {
3898 CopyMoveJob *job;
3899 goffset last_size;
3900 SourceInfo *source_info;
3901 TransferInfo *transfer_info;
3902} ProgressData;
3903
3904static void
3905copy_file_progress_callback (goffset current_num_bytes,
3906 goffset total_num_bytes,
3907 gpointer user_data)
3908{
3909 ProgressData *pdata;
3910 goffset new_size;
3911
3912 pdata = user_data;
3913
3914 new_size = current_num_bytes - pdata->last_size;
3915
3916 if (new_size > 0) {
3917 pdata->transfer_info->num_bytes += new_size;
3918 pdata->last_size = current_num_bytes;
3919 report_copy_progress (pdata->job,
3920 pdata->source_info,
3921 pdata->transfer_info);
3922 }
3923}
3924
3925static gboolean
3926test_dir_is_parent (GFile *child, GFile *root)
3927{
3928 GFile *f;
3929
3930 f = g_file_dup (child);
3931 while (f) {
3932 if (g_file_equal (f, root)) {
3933 g_object_unref (f);
3934 return TRUE(!(0));
3935 }
3936 f = g_file_get_parent (f);
3937 }
3938 if (f) {
3939 g_object_unref (f);
3940 }
3941 return FALSE(0);
3942}
3943
3944static char *
3945query_fs_type (GFile *file,
3946 GCancellable *cancellable)
3947{
3948 GFileInfo *fsinfo;
3949 char *ret;
3950
3951 ret = NULL((void*)0);
3952
3953 fsinfo = g_file_query_filesystem_info (file,
3954 G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3955 cancellable,
3956 NULL((void*)0));
3957 if (fsinfo != NULL((void*)0)) {
3958 ret = g_strdup (g_file_info_get_attribute_string (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))g_strdup_inline (g_file_info_get_attribute_string (fsinfo, "filesystem::type"
))
;
3959 g_object_unref (fsinfo);
3960 }
3961
3962 if (ret == NULL((void*)0)) {
3963 /* ensure that we don't attempt to query
3964 * the FS type for each file in a given
3965 * directory, if it can't be queried. */
3966 ret = g_strdup ("")g_strdup_inline ("");
3967 }
3968
3969 return ret;
3970}
3971
3972static gboolean
3973is_trusted_desktop_file (GFile *file,
3974 GCancellable *cancellable)
3975{
3976 char *basename;
3977 gboolean res;
3978 GFileInfo *info;
3979
3980 /* Don't trust non-local files */
3981 if (!g_file_is_native (file)) {
3982 return FALSE(0);
3983 }
3984
3985 basename = g_file_get_basename (file);
3986 if (!g_str_has_suffix (basename, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (basename); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_62; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_62 = 1; else _g_boolean_var_62
= 0; _g_boolean_var_62; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (basename, ".desktop") )
) {
3987 g_free (basename);
3988 return FALSE(0);
3989 }
3990 g_free (basename);
3991
3992 info = g_file_query_info (file,
3993 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" ","
3994 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute",
3995 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3996 cancellable,
3997 NULL((void*)0));
3998
3999 if (info == NULL((void*)0)) {
4000 return FALSE(0);
4001 }
4002
4003 res = FALSE(0);
4004
4005 /* Weird file => not trusted,
4006 Already executable => no need to mark trusted */
4007 if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR &&
4008 !g_file_info_get_attribute_boolean (info,
4009 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute") &&
4010 caja_is_in_system_dir (file)) {
4011 res = TRUE(!(0));
4012 }
4013 g_object_unref (info);
4014
4015 return res;
4016}
4017
4018typedef struct {
4019 int id;
4020 char *new_name;
4021 gboolean apply_to_all;
4022} ConflictResponseData;
4023
4024typedef struct {
4025 GFile *src;
4026 GFile *dest;
4027 GFile *dest_dir;
4028 GtkWindow *parent;
4029 ConflictResponseData *resp_data;
4030} ConflictDialogData;
4031
4032static gboolean
4033do_run_conflict_dialog (gpointer _data)
4034{
4035 ConflictDialogData *data = _data;
4036 GtkWidget *dialog;
4037 int response;
4038
4039 dialog = caja_file_conflict_dialog_new (data->parent,
4040 data->src,
4041 data->dest,
4042 data->dest_dir);
4043 response = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
4044
4045 if (response == CONFLICT_RESPONSE_RENAME) {
4046 data->resp_data->new_name =
4047 caja_file_conflict_dialog_get_new_name (CAJA_FILE_CONFLICT_DIALOG (dialog)((((CajaFileConflictDialog*) (void *) ((dialog))))));
4048 } else if (response != GTK_RESPONSE_CANCEL ||
4049 response != GTK_RESPONSE_NONE) {
4050 data->resp_data->apply_to_all =
4051 caja_file_conflict_dialog_get_apply_to_all
4052 (CAJA_FILE_CONFLICT_DIALOG (dialog)((((CajaFileConflictDialog*) (void *) ((dialog))))));
4053 }
4054
4055 data->resp_data->id = response;
4056
4057 gtk_widget_destroy (dialog);
4058
4059 return FALSE(0);
4060}
4061
4062static ConflictResponseData *
4063run_conflict_dialog (CommonJob *job,
4064 GFile *src,
4065 GFile *dest,
4066 GFile *dest_dir)
4067{
4068 ConflictDialogData *data;
4069 ConflictResponseData *resp_data;
4070
4071 g_timer_stop (job->time);
4072
4073 data = g_slice_new0 (ConflictDialogData)(ConflictDialogData *) (__extension__ ({ gsize __s = sizeof (
ConflictDialogData); gpointer __p; __p = g_slice_alloc (__s);
memset (__p, 0, __s); __p; }))
;
4074 data->parent = job->parent_window;
4075 data->src = src;
4076 data->dest = dest;
4077 data->dest_dir = dest_dir;
4078
4079 resp_data = g_slice_new0 (ConflictResponseData)(ConflictResponseData *) (__extension__ ({ gsize __s = sizeof
(ConflictResponseData); gpointer __p; __p = g_slice_alloc (__s
); memset (__p, 0, __s); __p; }))
;
4080 resp_data->new_name = NULL((void*)0);
4081 data->resp_data = resp_data;
4082
4083 caja_progress_info_pause (job->progress);
4084 g_io_scheduler_job_send_to_mainloop (job->io_job,
4085 do_run_conflict_dialog,
4086 data,
4087 NULL((void*)0));
4088 caja_progress_info_resume (job->progress);
4089
4090 g_slice_free (ConflictDialogData, data)do { if (1) g_slice_free1 (sizeof (ConflictDialogData), (data
)); else (void) ((ConflictDialogData*) 0 == (data)); } while (
0)
;
4091
4092 g_timer_continue (job->time);
4093
4094 return resp_data;
4095}
4096
4097static void
4098conflict_response_data_free (ConflictResponseData *data)
4099{
4100 g_free (data->new_name);
4101 g_slice_free (ConflictResponseData, data)do { if (1) g_slice_free1 (sizeof (ConflictResponseData), (data
)); else (void) ((ConflictResponseData*) 0 == (data)); } while
(0)
;
4102}
4103
4104static GFile *
4105get_target_file_for_display_name (GFile *dir,
4106 char *name)
4107{
4108 GFile *dest;
4109
4110 dest = NULL((void*)0);
4111 dest = g_file_get_child_for_display_name (dir, name, NULL((void*)0));
4112
4113 if (dest == NULL((void*)0)) {
4114 dest = g_file_get_child (dir, name);
4115 }
4116
4117 return dest;
4118}
4119
4120/* Debuting files is non-NULL only for toplevel items */
4121static void
4122copy_move_file (CopyMoveJob *copy_job,
4123 GFile *src,
4124 GFile *dest_dir,
4125 gboolean same_fs,
4126 gboolean unique_names,
4127 char **dest_fs_type,
4128 SourceInfo *source_info,
4129 TransferInfo *transfer_info,
4130 GHashTable *debuting_files,
4131 GdkPoint *position,
4132 gboolean overwrite,
4133 gboolean *skipped_file,
4134 gboolean readonly_source_fs,
4135 gboolean last_item)
4136{
4137 GFile *dest, *new_dest;
4138 GError *error;
4139 GFileCopyFlags flags;
4140 char *primary, *secondary, *details;
4141 int response;
4142 ProgressData pdata;
4143 gboolean would_recurse, is_merge;
4144 CommonJob *job;
4145 gboolean res;
4146 int unique_name_nr;
4147 gboolean handled_invalid_filename;
4148
4149 job = (CommonJob *)copy_job;
4150
4151 if (should_skip_file (job, src)) {
4152 *skipped_file = TRUE(!(0));
4153 return;
4154 }
4155
4156 unique_name_nr = 1;
4157
4158 // TODO: Here we should get the previous file name UNDO
4159
4160 /* another file in the same directory might have handled the invalid
4161 * filename condition for us
4162 */
4163 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4164
4165 if (unique_names) {
4166 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4167 } else {
4168 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4169 }
4170
4171
4172 /* Don't allow recursive move/copy into itself.
4173 * (We would get a file system error if we proceeded but it is nicer to
4174 * detect and report it at this level) */
4175 if (test_dir_is_parent (dest_dir, src)) {
4176 if (job->skip_all_error) {
4177 goto out;
4178 }
4179
4180 /* the run_warning() frees all strings passed in automatically */
4181 primary = copy_job->is_move ? g_strdup (_("You cannot move a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a folder into itself."
, 5))
4182 : g_strdup (_("You cannot copy a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a folder into itself."
, 5))
;
4183 secondary = g_strdup (_("The destination folder is inside the source folder."))g_strdup_inline (dcgettext (((void*)0), "The destination folder is inside the source folder."
, 5))
;
4184
4185 response = run_warning (job,
4186 primary,
4187 secondary,
4188 NULL((void*)0),
4189 (source_info->num_files - transfer_info->num_files) > 1,
4190 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4191 NULL((void*)0));
4192
4193 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4194 abort_job (job);
4195 } else if (response == 1) { /* skip all */
4196 job->skip_all_error = TRUE(!(0));
4197 } else if (response == 2) { /* skip */
4198 /* do nothing */
4199 } else {
4200 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4200, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4201 }
4202
4203 goto out;
4204 }
4205
4206 /* Don't allow copying over the source or one of the parents of the source.
4207 */
4208 if (test_dir_is_parent (src, dest)) {
4209 if (job->skip_all_error) {
4210 goto out;
4211 }
4212
4213 /* the run_warning() frees all strings passed in automatically */
4214 primary = copy_job->is_move ? g_strdup (_("You cannot move a file over itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a file over itself."
, 5))
4215 : g_strdup (_("You cannot copy a file over itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a file over itself."
, 5))
;
4216 secondary = g_strdup (_("The source file would be overwritten by the destination."))g_strdup_inline (dcgettext (((void*)0), "The source file would be overwritten by the destination."
, 5))
;
4217
4218 response = run_warning (job,
4219 primary,
4220 secondary,
4221 NULL((void*)0),
4222 (source_info->num_files - transfer_info->num_files) > 1,
4223 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4224 NULL((void*)0));
4225
4226 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4227 abort_job (job);
4228 } else if (response == 1) { /* skip all */
4229 job->skip_all_error = TRUE(!(0));
4230 } else if (response == 2) { /* skip */
4231 /* do nothing */
4232 } else {
4233 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4233, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4234 }
4235
4236 goto out;
4237 }
4238
4239
4240 retry:
4241 error = NULL((void*)0);
4242 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS;
4243 if (overwrite) {
4244 flags |= G_FILE_COPY_OVERWRITE;
4245 }
4246 if (readonly_source_fs) {
4247 flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS;
4248 }
4249
4250 pdata.job = copy_job;
4251 pdata.last_size = 0;
4252 pdata.source_info = source_info;
4253 pdata.transfer_info = transfer_info;
4254
4255 if (!is_dir(src) && last_item)
4256 /* this is the last file for this operation, cannot pause anymore */
4257 caja_progress_info_disable_pause (job->progress);
4258
4259 if (copy_job->is_move) {
4260 res = g_file_move (src, dest,
4261 flags,
4262 job->cancellable,
4263 copy_file_progress_callback,
4264 &pdata,
4265 &error);
4266 } else {
4267 res = g_file_copy (src, dest,
4268 flags,
4269 job->cancellable,
4270 copy_file_progress_callback,
4271 &pdata,
4272 &error);
4273 }
4274
4275 if (res) {
4276 if (!copy_job->is_move) {
4277 /* Ignore errors here. Failure to copy metadata is not a hard error */
4278 g_file_copy_attributes (src, dest,
4279 flags | G_FILE_COPY_ALL_METADATA,
4280 job->cancellable, NULL((void*)0));
4281 }
4282
4283 transfer_info->num_files ++;
4284 report_copy_progress (copy_job, source_info, transfer_info);
4285
4286 if (debuting_files) {
4287 if (position) {
4288 caja_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4289 } else {
4290 caja_file_changes_queue_schedule_position_remove (dest);
4291 }
4292
4293 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4294 }
4295 if (copy_job->is_move) {
4296 caja_file_changes_queue_file_moved (src, dest);
4297 } else {
4298 caja_file_changes_queue_file_added (dest);
4299 }
4300
4301 /* If copying a trusted desktop file to the desktop,
4302 mark it as trusted. */
4303 if (copy_job->desktop_location != NULL((void*)0) &&
4304 g_file_equal (copy_job->desktop_location, dest_dir) &&
4305 is_trusted_desktop_file (src, job->cancellable)) {
4306 mark_desktop_file_trusted (job,
4307 job->cancellable,
4308 dest,
4309 FALSE(0));
4310 }
4311
4312 // Start UNDO-REDO
4313 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, dest);
4314 // End UNDO-REDO
4315
4316 g_object_unref (dest);
4317 return;
4318 }
4319
4320 if (!handled_invalid_filename &&
4321 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
) {
4322 handled_invalid_filename = TRUE(!(0));
4323
4324 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_63
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_63 = 1; else
_g_boolean_var_63 = 0; _g_boolean_var_63; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4324, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4325 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4326
4327 if (unique_names) {
4328 new_dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr);
4329 } else {
4330 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4331 }
4332
4333 if (!g_file_equal (dest, new_dest)) {
4334 g_object_unref (dest);
4335 dest = new_dest;
4336
4337 g_error_free (error);
4338 goto retry;
4339 } else {
4340 g_object_unref (new_dest);
4341 }
4342 }
4343
4344 /* Conflict */
4345 if (!overwrite &&
4346 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4347 gboolean is_merge;
4348 ConflictResponseData *response;
4349
4350 g_error_free (error);
4351
4352 if (unique_names) {
4353 g_object_unref (dest);
4354 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4355 goto retry;
4356 }
4357
4358 is_merge = FALSE(0);
4359
4360 if (is_dir (dest) && is_dir (src)) {
4361 is_merge = TRUE(!(0));
4362 }
4363
4364 if ((is_merge && job->merge_all) ||
4365 (!is_merge && job->replace_all)) {
4366 overwrite = TRUE(!(0));
4367 goto retry;
4368 }
4369
4370 if (job->skip_all_conflict) {
4371 goto out;
4372 }
4373
4374 response = run_conflict_dialog (job, src, dest, dest_dir);
4375
4376 if (response->id == GTK_RESPONSE_CANCEL ||
4377 response->id == GTK_RESPONSE_DELETE_EVENT) {
4378 conflict_response_data_free (response);
4379 abort_job (job);
4380 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4381 if (response->apply_to_all) {
4382 job->skip_all_conflict = TRUE(!(0));
4383 }
4384 conflict_response_data_free (response);
4385 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4386 if (response->apply_to_all) {
4387 if (is_merge) {
4388 job->merge_all = TRUE(!(0));
4389 } else {
4390 job->replace_all = TRUE(!(0));
4391 }
4392 }
4393 overwrite = TRUE(!(0));
4394 conflict_response_data_free (response);
4395 goto retry;
4396 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4397 g_object_unref (dest);
4398 dest = get_target_file_for_display_name (dest_dir,
4399 response->new_name);
4400 conflict_response_data_free (response);
4401 goto retry;
4402 } else {
4403 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4403, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4404 }
4405 }
4406
4407 else if (overwrite &&
4408 IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
) {
4409
4410 g_error_free (error);
4411
4412 if (remove_target_recursively (job, src, dest, dest)) {
4413 goto retry;
4414 }
4415 }
4416
4417 /* Needs to recurse */
4418 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
4419 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
) {
4420 is_merge = error->code == G_IO_ERROR_WOULD_MERGE;
4421 would_recurse = error->code == G_IO_ERROR_WOULD_RECURSE;
4422 g_error_free (error);
4423
4424 if (overwrite && would_recurse) {
4425 error = NULL((void*)0);
4426
4427 /* Copying a dir onto file, first remove the file */
4428 if (!g_file_delete (dest, job->cancellable, &error) &&
4429 !IS_IO_ERROR (error, NOT_FOUND)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_FOUND))
) {
4430 if (job->skip_all_error) {
4431 g_error_free (error);
4432 goto out;
4433 }
4434 if (copy_job->is_move) {
4435 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
4436 } else {
4437 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
4438 }
4439 secondary = f (_("Could not remove the already existing file with the same name in %F.")dcgettext (((void*)0), "Could not remove the already existing file with the same name in %F."
, 5)
, dest_dir);
4440 details = error->message;
4441
4442 /* setting TRUE on show_all here, as we could have
4443 * another error on the same file later.
4444 */
4445 response = run_warning (job,
4446 primary,
4447 secondary,
4448 details,
4449 TRUE(!(0)),
4450 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4451 NULL((void*)0));
4452
4453 g_error_free (error);
4454
4455 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4456 abort_job (job);
4457 } else if (response == 1) { /* skip all */
4458 job->skip_all_error = TRUE(!(0));
4459 } else if (response == 2) { /* skip */
4460 /* do nothing */
4461 } else {
4462 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4462, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4463 }
4464 goto out;
4465
4466 }
4467 if (error) {
4468 g_error_free (error);
4469 error = NULL((void*)0);
4470 }
4471 caja_file_changes_queue_file_removed (dest);
4472 }
4473
4474 if (is_merge) {
4475 /* On merge we now write in the target directory, which may not
4476 be in the same directory as the source, even if the parent is
4477 (if the merged directory is a mountpoint). This could cause
4478 problems as we then don't transcode filenames.
4479 We just set same_fs to FALSE which is safe but a bit slower. */
4480 same_fs = FALSE(0);
4481 }
4482
4483 if (!copy_move_directory (copy_job, src, &dest, same_fs,
4484 would_recurse, dest_fs_type,
4485 source_info, transfer_info,
4486 debuting_files, skipped_file,
4487 readonly_source_fs,
4488 last_item)) {
4489 /* destination changed, since it was an invalid file name */
4490 g_assert (*dest_fs_type != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_64
; if (*dest_fs_type != ((void*)0)) _g_boolean_var_64 = 1; else
_g_boolean_var_64 = 0; _g_boolean_var_64; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4490, ((const char*
) (__func__)), "*dest_fs_type != NULL"); } while (0)
;
4491 handled_invalid_filename = TRUE(!(0));
4492 goto retry;
4493 }
4494
4495 g_object_unref (dest);
4496 return;
4497 }
4498
4499 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
4500 g_error_free (error);
4501 }
4502
4503 /* Other error */
4504 else {
4505 if (job->skip_all_error) {
4506 g_error_free (error);
4507 goto out;
4508 }
4509 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
4510 secondary = f (_("There was an error copying the file into %F.")dcgettext (((void*)0), "There was an error copying the file into %F."
, 5)
, dest_dir);
4511 details = error->message;
4512
4513 response = run_warning (job,
4514 primary,
4515 secondary,
4516 details,
4517 (source_info->num_files - transfer_info->num_files) > 1,
4518 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4519 NULL((void*)0));
4520
4521 g_error_free (error);
4522
4523 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4524 abort_job (job);
4525 } else if (response == 1) { /* skip all */
4526 job->skip_all_error = TRUE(!(0));
4527 } else if (response == 2) { /* skip */
4528 /* do nothing */
4529 } else {
4530 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4530, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4531 }
4532 }
4533 out:
4534 *skipped_file = TRUE(!(0)); /* Or aborted, but same-same */
4535 g_object_unref (dest);
4536}
4537
4538static void
4539copy_files (CopyMoveJob *job,
4540 const char *dest_fs_id,
4541 SourceInfo *source_info,
4542 TransferInfo *transfer_info)
4543{
4544 CommonJob *common;
4545 GList *l;
4546 gboolean same_fs;
4547 int i;
4548 GdkPoint *point;
4549 gboolean skipped_file;
4550 gboolean unique_names;
4551 GFile *dest;
4552 GFile *source_dir;
4553 char *dest_fs_type;
4554 gboolean readonly_source_fs;
4555 GFile *src = NULL((void*)0);
4556
4557 dest_fs_type = NULL((void*)0);
4558 readonly_source_fs = FALSE(0);
4559
4560 common = &job->common;
4561
4562 report_copy_progress (job, source_info, transfer_info);
4563
4564 /* Query the source dir, not the file because if its a symlink we'll follow it */
4565 source_dir = g_file_get_parent ((GFile *) job->files->data);
4566 if (source_dir) {
4567 GFileInfo *inf;
4568
4569 inf = g_file_query_filesystem_info (source_dir, "filesystem::readonly", NULL((void*)0), NULL((void*)0));
4570 if (inf != NULL((void*)0)) {
4571 readonly_source_fs = g_file_info_get_attribute_boolean (inf, "filesystem::readonly");
4572 g_object_unref (inf);
4573 }
4574 g_object_unref (source_dir);
4575 }
4576
4577 unique_names = (job->destination == NULL((void*)0));
4578 i = 0;
4579 for (l = job->files;
4580 l != NULL((void*)0) && !job_aborted (common);
4581 l = l->next) {
4582 caja_progress_info_get_ready (common->progress);
4583
4584 src = l->data;
4585
4586 if (i < job->n_icon_positions) {
4587 point = &job->icon_positions[i];
4588 } else {
4589 point = NULL((void*)0);
4590 }
4591
4592
4593 same_fs = FALSE(0);
4594 if (dest_fs_id) {
4595 same_fs = has_fs_id (src, dest_fs_id);
4596 }
4597
4598 if (job->destination) {
4599 dest = g_object_ref (job->destination)((__typeof__ (job->destination)) (g_object_ref) (job->destination
))
;
4600 } else {
4601 dest = g_file_get_parent (src);
4602
4603 }
4604 if (dest) {
4605 skipped_file = FALSE(0);
4606
4607 copy_move_file (job, src, dest,
4608 same_fs, unique_names,
4609 &dest_fs_type,
4610 source_info, transfer_info,
4611 job->debuting_files,
4612 point, FALSE(0), &skipped_file,
4613 readonly_source_fs,
4614 !l->next);
4615 g_object_unref (dest);
4616 }
4617 i++;
4618 }
4619
4620 g_free (dest_fs_type);
4621}
4622
4623static gboolean
4624copy_job_done (gpointer user_data)
4625{
4626 CopyMoveJob *job;
4627
4628 job = user_data;
4629 if (job->done_callback) {
4630 job->done_callback (job->debuting_files, job->done_callback_data);
4631 }
4632
4633 g_list_free_full (job->files, g_object_unref);
4634 if (job->destination) {
4635 g_object_unref (job->destination);
4636 }
4637 if (job->desktop_location) {
4638 g_object_unref (job->desktop_location);
4639 }
4640 g_hash_table_unref (job->debuting_files);
4641 g_free (job->icon_positions);
4642
4643 finalize_common ((CommonJob *)job);
4644
4645 caja_file_changes_consume_changes (TRUE(!(0)));
4646 return FALSE(0);
4647}
4648
4649static gboolean
4650copy_job (GIOSchedulerJob *io_job,
4651 GCancellable *cancellable,
4652 gpointer user_data)
4653{
4654 CopyMoveJob *job;
4655 CommonJob *common;
4656 SourceInfo source_info;
4657 TransferInfo transfer_info;
4658 char *dest_fs_id;
4659 GFile *dest;
4660
4661 job = user_data;
4662 common = &job->common;
4663 common->io_job = io_job;
4664
4665 dest_fs_id = NULL((void*)0);
4666
4667 caja_progress_info_start (job->common.progress);
4668
4669 scan_sources (job->files,
4670 &source_info,
4671 common,
4672 OP_KIND_COPY);
4673 if (job_aborted (common)) {
4674 goto aborted;
4675 }
4676
4677 if (job->destination) {
4678 dest = g_object_ref (job->destination)((__typeof__ (job->destination)) (g_object_ref) (job->destination
))
;
4679 } else {
4680 /* Duplication, no dest,
4681 * use source for free size, etc
4682 */
4683 dest = g_file_get_parent (job->files->data);
4684 }
4685
4686 verify_destination (&job->common,
4687 dest,
4688 &dest_fs_id,
4689 source_info.num_bytes);
4690 g_object_unref (dest);
4691 if (job_aborted (common)) {
4692 goto aborted;
4693 }
4694
4695 g_timer_start (job->common.time);
4696
4697 memset (&transfer_info, 0, sizeof (transfer_info));
4698 copy_files (job,
4699 dest_fs_id,
4700 &source_info, &transfer_info);
4701
4702 aborted:
4703
4704 g_free (dest_fs_id);
4705
4706 g_io_scheduler_job_send_to_mainloop_async (io_job,
4707 copy_job_done,
4708 job,
4709 NULL((void*)0));
4710
4711 return FALSE(0);
4712}
4713
4714static gboolean
4715contains_multiple_items (GList *files)
4716{
4717 GFile *first;
4718
4719 if (g_list_length (files) > 1) {
4720 return TRUE(!(0));
4721 } else {
4722 if (files) {
4723 first = files->data;
4724 if (is_dir (first))
4725 return TRUE(!(0));
4726 }
4727 }
4728
4729 return FALSE(0);
4730}
4731
4732void
4733caja_file_operations_copy (GList *files,
4734 GArray *relative_item_points,
4735 GFile *target_dir,
4736 GtkWindow *parent_window,
4737 CajaCopyCallback done_callback,
4738 gpointer done_callback_data)
4739{
4740 CopyMoveJob *job;
4741
4742 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
4743 job->desktop_location = caja_get_desktop_location ();
4744 job->done_callback = done_callback;
4745 job->done_callback_data = done_callback_data;
4746 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
4747 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
4748 if (relative_item_points != NULL((void*)0) &&
4749 relative_item_points->len > 0) {
4750 job->icon_positions =
4751 g_memdup (relative_item_points->data,
4752 sizeof (GdkPoint) * relative_item_points->len);
4753 job->n_icon_positions = relative_item_points->len;
4754 }
4755 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
4756
4757 inhibit_power_manager ((CommonJob *)job, _("Copying Files")dcgettext (((void*)0), "Copying Files", 5));
4758
4759 // Start UNDO-REDO
4760 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
4761 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_COPY, g_list_length(files));
4762 GFile* src_dir = g_file_get_parent (files->data);
4763 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
4764 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
4765 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
4766 }
4767 // End UNDO-REDO
4768
4769 g_io_scheduler_push_job (copy_job,
4770 job,
4771 NULL((void*)0), /* destroy notify */
4772 0,
4773 job->common.cancellable);
4774}
4775
4776static void
4777report_move_progress (CopyMoveJob *move_job, int total, int left)
4778{
4779 CommonJob *job;
4780
4781 job = (CommonJob *)move_job;
4782
4783 caja_progress_info_take_status (job->progress,
4784 f (_("Preparing to Move to \"%B\"")dcgettext (((void*)0), "Preparing to Move to \"%B\"", 5),
4785 move_job->destination));
4786
4787 caja_progress_info_take_details (job->progress,
4788 f (ngettext ("Preparing to move %'d file",dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
4789 "Preparing to move %'d files",dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
4790 left)dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
, left));
4791
4792 caja_progress_info_pulse_progress (job->progress);
4793}
4794
4795typedef struct {
4796 GFile *file;
4797 gboolean overwrite;
4798 gboolean has_position;
4799 GdkPoint position;
4800} MoveFileCopyFallback;
4801
4802static MoveFileCopyFallback *
4803move_copy_file_callback_new (GFile *file,
4804 gboolean overwrite,
4805 GdkPoint *position)
4806{
4807 MoveFileCopyFallback *fallback;
4808
4809 fallback = g_new (MoveFileCopyFallback, 1)(MoveFileCopyFallback *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (MoveFileCopyFallback); 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; }))
;
4810 fallback->file = file;
4811 fallback->overwrite = overwrite;
4812 if (position) {
4813 fallback->has_position = TRUE(!(0));
4814 fallback->position = *position;
4815 } else {
4816 fallback->has_position = FALSE(0);
4817 }
4818
4819 return fallback;
4820}
4821
4822static GList *
4823get_files_from_fallbacks (GList *fallbacks)
4824{
4825 GList *res, *l;
4826 MoveFileCopyFallback *fallback = NULL((void*)0);
4827
4828 res = NULL((void*)0);
4829 for (l = fallbacks; l != NULL((void*)0); l = l->next) {
4830 fallback = l->data;
4831 res = g_list_prepend (res, fallback->file);
4832 }
4833 return g_list_reverse (res);
4834}
4835
4836static void
4837move_file_prepare (CopyMoveJob *move_job,
4838 GFile *src,
4839 GFile *dest_dir,
4840 gboolean same_fs,
4841 char **dest_fs_type,
4842 GHashTable *debuting_files,
4843 GdkPoint *position,
4844 GList **fallback_files,
4845 int files_left)
4846{
4847 GFile *dest, *new_dest;
4848 GError *error;
4849 CommonJob *job;
4850 gboolean overwrite;
4851 char *primary, *secondary, *details;
4852 int response;
4853 GFileCopyFlags flags;
4854 MoveFileCopyFallback *fallback;
4855 gboolean handled_invalid_filename;
4856
4857 overwrite = FALSE(0);
4858 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4859
4860 job = (CommonJob *)move_job;
4861
4862 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4863
4864
4865 /* Don't allow recursive move/copy into itself.
4866 * (We would get a file system error if we proceeded but it is nicer to
4867 * detect and report it at this level) */
4868 if (test_dir_is_parent (dest_dir, src)) {
4869 if (job->skip_all_error) {
4870 goto out;
4871 }
4872
4873 /* the run_warning() frees all strings passed in automatically */
4874 primary = move_job->is_move ? g_strdup (_("You cannot move a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a folder into itself."
, 5))
4875 : g_strdup (_("You cannot copy a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a folder into itself."
, 5))
;
4876 secondary = g_strdup (_("The destination folder is inside the source folder."))g_strdup_inline (dcgettext (((void*)0), "The destination folder is inside the source folder."
, 5))
;
4877
4878 response = run_warning (job,
4879 primary,
4880 secondary,
4881 NULL((void*)0),
4882 files_left > 1,
4883 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4884 NULL((void*)0));
4885
4886 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4887 abort_job (job);
4888 } else if (response == 1) { /* skip all */
4889 job->skip_all_error = TRUE(!(0));
4890 } else if (response == 2) { /* skip */
4891 /* do nothing */
4892 } else {
4893 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4893, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4894 }
4895
4896 goto out;
4897 }
4898
4899 retry:
4900 caja_progress_info_get_ready (job->progress);
4901
4902 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_NO_FALLBACK_FOR_MOVE;
4903 if (overwrite) {
4904 flags |= G_FILE_COPY_OVERWRITE;
4905 }
4906
4907 error = NULL((void*)0);
4908 if (g_file_move (src, dest,
4909 flags,
4910 job->cancellable,
4911 NULL((void*)0),
4912 NULL((void*)0),
4913 &error)) {
4914
4915 if (debuting_files) {
4916 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4917 }
4918
4919 caja_file_changes_queue_file_moved (src, dest);
4920
4921 if (position) {
4922 caja_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4923 } else {
4924 caja_file_changes_queue_schedule_position_remove (dest);
4925 }
4926
4927 // Start UNDO-REDO
4928 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, dest);
4929 // End UNDO-REDO
4930
4931 return;
4932 }
4933
4934 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
4935 !handled_invalid_filename) {
4936 handled_invalid_filename = TRUE(!(0));
4937
4938 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_65
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_65 = 1; else
_g_boolean_var_65 = 0; _g_boolean_var_65; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4938, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4939 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4940
4941 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4942 if (!g_file_equal (dest, new_dest)) {
4943 g_object_unref (dest);
4944 dest = new_dest;
4945 goto retry;
4946 } else {
4947 g_object_unref (new_dest);
4948 }
4949 }
4950
4951 /* Conflict */
4952 else if (!overwrite &&
4953 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4954 gboolean is_merge;
4955 ConflictResponseData *response;
4956
4957 g_error_free (error);
4958
4959 is_merge = FALSE(0);
4960 if (is_dir (dest) && is_dir (src)) {
4961 is_merge = TRUE(!(0));
4962 }
4963
4964 if ((is_merge && job->merge_all) ||
4965 (!is_merge && job->replace_all)) {
4966 overwrite = TRUE(!(0));
4967 goto retry;
4968 }
4969
4970 if (job->skip_all_conflict) {
4971 goto out;
4972 }
4973
4974 response = run_conflict_dialog (job, src, dest, dest_dir);
4975
4976 if (response->id == GTK_RESPONSE_CANCEL ||
4977 response->id == GTK_RESPONSE_DELETE_EVENT) {
4978 conflict_response_data_free (response);
4979 abort_job (job);
4980 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4981 if (response->apply_to_all) {
4982 job->skip_all_conflict = TRUE(!(0));
4983 }
4984 conflict_response_data_free (response);
4985 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4986 if (response->apply_to_all) {
4987 if (is_merge) {
4988 job->merge_all = TRUE(!(0));
4989 } else {
4990 job->replace_all = TRUE(!(0));
4991 }
4992 }
4993 overwrite = TRUE(!(0));
4994 conflict_response_data_free (response);
4995 goto retry;
4996 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4997 g_object_unref (dest);
4998 dest = get_target_file_for_display_name (dest_dir,
4999 response->new_name);
5000 conflict_response_data_free (response);
5001 goto retry;
5002 } else {
5003 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5003, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5004 }
5005 }
5006
5007 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
5008 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
||
5009 IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
||
5010 (overwrite && IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
)) {
5011 g_error_free (error);
5012
5013 fallback = move_copy_file_callback_new (src,
5014 overwrite,
5015 position);
5016 *fallback_files = g_list_prepend (*fallback_files, fallback);
5017 }
5018
5019 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
5020 g_error_free (error);
5021 }
5022
5023 /* Other error */
5024 else {
5025 if (job->skip_all_error) {
5026 goto out;
5027 }
5028 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
5029 secondary = f (_("There was an error moving the file into %F.")dcgettext (((void*)0), "There was an error moving the file into %F."
, 5)
, dest_dir);
5030 details = error->message;
5031
5032 response = run_warning (job,
5033 primary,
5034 secondary,
5035 details,
5036 files_left > 1,
5037 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
5038 NULL((void*)0));
5039
5040 g_error_free (error);
5041
5042 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5043 abort_job (job);
5044 } else if (response == 1) { /* skip all */
5045 job->skip_all_error = TRUE(!(0));
5046 } else if (response == 2) { /* skip */
5047 /* do nothing */
5048 } else {
5049 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5049, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5050 }
5051 }
5052
5053 out:
5054 g_object_unref (dest);
5055}
5056
5057static void
5058move_files_prepare (CopyMoveJob *job,
5059 const char *dest_fs_id,
5060 char **dest_fs_type,
5061 GList **fallbacks)
5062{
5063 CommonJob *common;
5064 GList *l;
5065 gboolean same_fs;
5066 gboolean last_item;
5067 int i;
5068 GdkPoint *point;
5069 int total, left;
5070 GFile *src = NULL((void*)0);
5071
5072 common = &job->common;
5073
5074 total = left = g_list_length (job->files);
5075
5076 caja_progress_info_get_ready (common->progress);
5077 report_move_progress (job, total, left);
5078
5079 i = 0;
5080 for (l = job->files;
5081 l != NULL((void*)0) && !job_aborted (common);
5082 l = l->next) {
5083 src = l->data;
5084
5085 last_item = (!l->next) && (!is_dir(src)) && (!(*fallbacks));
5086 if (last_item)
5087 /* this is the last file and there are no fallbacks to process, cannot pause anymore */
5088 caja_progress_info_disable_pause (common->progress);
5089
5090 if (i < job->n_icon_positions) {
5091 point = &job->icon_positions[i];
5092 } else {
5093 point = NULL((void*)0);
5094 }
5095
5096
5097 same_fs = FALSE(0);
5098 if (dest_fs_id) {
5099 same_fs = has_fs_id (src, dest_fs_id);
5100 }
5101
5102 move_file_prepare (job, src, job->destination,
5103 same_fs, dest_fs_type,
5104 job->debuting_files,
5105 point,
5106 fallbacks,
5107 left);
5108 report_move_progress (job, total, --left);
5109 i++;
5110 }
5111
5112 *fallbacks = g_list_reverse (*fallbacks);
5113
5114
5115}
5116
5117static void
5118move_files (CopyMoveJob *job,
5119 GList *fallbacks,
5120 const char *dest_fs_id,
5121 char **dest_fs_type,
5122 SourceInfo *source_info,
5123 TransferInfo *transfer_info)
5124{
5125 CommonJob *common;
5126 GList *l;
5127 gboolean same_fs;
5128 int i;
5129 GdkPoint *point;
5130 gboolean skipped_file;
5131 MoveFileCopyFallback *fallback;
5132 GFile *src = NULL((void*)0);
5133
5134 common = &job->common;
5135
5136 report_copy_progress (job, source_info, transfer_info);
5137
5138 i = 0;
5139 for (l = fallbacks;
5140 l != NULL((void*)0) && !job_aborted (common);
5141 l = l->next) {
5142 caja_progress_info_get_ready (common->progress);
5143
5144 fallback = l->data;
5145 src = fallback->file;
5146
5147 if (fallback->has_position) {
5148 point = &fallback->position;
5149 } else {
5150 point = NULL((void*)0);
5151 }
5152
5153 same_fs = FALSE(0);
5154 if (dest_fs_id) {
5155 same_fs = has_fs_id (src, dest_fs_id);
5156 }
5157
5158 /* Set overwrite to true, as the user has
5159 selected overwrite on all toplevel items */
5160 skipped_file = FALSE(0);
5161 copy_move_file (job, src, job->destination,
5162 same_fs, FALSE(0), dest_fs_type,
5163 source_info, transfer_info,
5164 job->debuting_files,
5165 point, fallback->overwrite, &skipped_file, FALSE(0),
5166 !l->next);
5167 i++;
5168 }
5169}
5170
5171
5172static gboolean
5173move_job_done (gpointer user_data)
5174{
5175 CopyMoveJob *job;
5176
5177 job = user_data;
5178 if (job->done_callback) {
5179 job->done_callback (job->debuting_files, job->done_callback_data);
5180 }
5181
5182 g_list_free_full (job->files, g_object_unref);
5183 g_object_unref (job->destination);
5184 g_hash_table_unref (job->debuting_files);
5185 g_free (job->icon_positions);
5186
5187 finalize_common ((CommonJob *)job);
5188
5189 caja_file_changes_consume_changes (TRUE(!(0)));
5190 return FALSE(0);
5191}
5192
5193static gboolean
5194move_job (GIOSchedulerJob *io_job,
5195 GCancellable *cancellable,
5196 gpointer user_data)
5197{
5198 CopyMoveJob *job;
5199 CommonJob *common;
5200 GList *fallbacks;
5201 SourceInfo source_info;
5202 TransferInfo transfer_info;
5203 char *dest_fs_id;
5204 char *dest_fs_type;
5205 GList *fallback_files;
5206
5207 job = user_data;
5208 common = &job->common;
5209 common->io_job = io_job;
5210
5211 dest_fs_id = NULL((void*)0);
5212 dest_fs_type = NULL((void*)0);
5213
5214 fallbacks = NULL((void*)0);
5215
5216 caja_progress_info_start (job->common.progress);
5217
5218 verify_destination (&job->common,
5219 job->destination,
5220 &dest_fs_id,
5221 -1);
5222 if (job_aborted (common)) {
5223 goto aborted;
5224 }
5225
5226 /* This moves all files that we can do without copy + delete */
5227 move_files_prepare (job, dest_fs_id, &dest_fs_type, &fallbacks);
5228 if (job_aborted (common)) {
5229 goto aborted;
5230 }
5231
5232 /* The rest we need to do deep copy + delete behind on,
5233 so scan for size */
5234
5235 fallback_files = get_files_from_fallbacks (fallbacks);
5236 scan_sources (fallback_files,
5237 &source_info,
5238 common,
5239 OP_KIND_MOVE);
5240
5241 g_list_free (fallback_files);
5242
5243 if (job_aborted (common)) {
5244 goto aborted;
5245 }
5246
5247 verify_destination (&job->common,
5248 job->destination,
5249 NULL((void*)0),
5250 source_info.num_bytes);
5251 if (job_aborted (common)) {
5252 goto aborted;
5253 }
5254
5255 memset (&transfer_info, 0, sizeof (transfer_info));
5256 move_files (job,
5257 fallbacks,
5258 dest_fs_id, &dest_fs_type,
5259 &source_info, &transfer_info);
5260
5261 aborted:
5262 g_list_free_full (fallbacks, g_free);
5263
5264 g_free (dest_fs_id);
5265 g_free (dest_fs_type);
5266
5267 g_io_scheduler_job_send_to_mainloop (io_job,
5268 move_job_done,
5269 job,
5270 NULL((void*)0));
5271
5272 return FALSE(0);
5273}
5274
5275void
5276caja_file_operations_move (GList *files,
5277 GArray *relative_item_points,
5278 GFile *target_dir,
5279 GtkWindow *parent_window,
5280 CajaCopyCallback done_callback,
5281 gpointer done_callback_data)
5282{
5283 CopyMoveJob *job;
5284
5285 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
5286 job->is_move = TRUE(!(0));
5287 job->done_callback = done_callback;
5288 job->done_callback_data = done_callback_data;
5289 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5290 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5291 if (relative_item_points != NULL((void*)0) &&
5292 relative_item_points->len > 0) {
5293 job->icon_positions =
5294 g_memdup (relative_item_points->data,
5295 sizeof (GdkPoint) * relative_item_points->len);
5296 job->n_icon_positions = relative_item_points->len;
5297 }
5298 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5299
5300 inhibit_power_manager ((CommonJob *)job, _("Moving Files")dcgettext (((void*)0), "Moving Files", 5));
5301
5302 // Start UNDO-REDO
5303 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5304 if (g_file_has_uri_scheme (g_list_first(files)->data, "trash")) {
5305 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RESTOREFROMTRASH, g_list_length(files));
5306 } else {
5307 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_MOVE, g_list_length(files));
5308 }
5309 GFile* src_dir = g_file_get_parent (files->data);
5310 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5311 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5312 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
5313 }
5314 // End UNDO-REDO
5315
5316 g_io_scheduler_push_job (move_job,
5317 job,
5318 NULL((void*)0), /* destroy notify */
5319 0,
5320 job->common.cancellable);
5321}
5322
5323static void
5324report_link_progress (CopyMoveJob *link_job, int total, int left)
5325{
5326 CommonJob *job;
5327
5328 job = (CommonJob *)link_job;
5329
5330 caja_progress_info_take_status (job->progress,
5331 f (_("Creating links in \"%B\"")dcgettext (((void*)0), "Creating links in \"%B\"", 5),
5332 link_job->destination));
5333
5334 caja_progress_info_take_details (job->progress,
5335 f (ngettext ("Making link to %'d file",dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
5336 "Making links to %'d files",dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
5337 left)dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
, left));
5338
5339 caja_progress_info_set_progress (job->progress, left, total);
5340}
5341
5342static char *
5343get_abs_path_for_symlink (GFile *file)
5344{
5345 GFile *root, *parent;
5346 char *relative, *abs;
5347
5348 if (g_file_is_native (file)) {
5349 return g_file_get_path (file);
5350 }
5351
5352 root = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
5353 while ((parent = g_file_get_parent (root)) != NULL((void*)0)) {
5354 g_object_unref (root);
5355 root = parent;
5356 }
5357
5358 relative = g_file_get_relative_path (root, file);
5359 g_object_unref (root);
5360 abs = g_strconcat ("/", relative, NULL((void*)0));
5361 g_free (relative);
5362 return abs;
5363}
5364
5365
5366static void
5367link_file (CopyMoveJob *job,
5368 GFile *src, GFile *dest_dir,
5369 char **dest_fs_type,
5370 GHashTable *debuting_files,
5371 GdkPoint *position,
5372 int files_left)
5373{
5374 GFile *src_dir, *dest, *new_dest;
5375 int count;
5376 char *path;
5377 gboolean not_local;
5378 GError *error;
5379 CommonJob *common;
5380 char *primary, *secondary, *details;
5381 int response;
5382 gboolean handled_invalid_filename;
5383
5384 common = (CommonJob *)job;
5385
5386 count = 0;
5387
5388 src_dir = g_file_get_parent (src);
5389 if (g_file_equal (src_dir, dest_dir)) {
5390 count = 1;
5391 }
5392 g_object_unref (src_dir);
5393
5394 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
5395
5396 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5397
5398 retry:
5399 error = NULL((void*)0);
5400 not_local = FALSE(0);
5401
5402 path = get_abs_path_for_symlink (src);
5403 if (path == NULL((void*)0)) {
5404 not_local = TRUE(!(0));
5405 } else if (g_file_make_symbolic_link (dest,
5406 path,
5407 common->cancellable,
5408 &error)) {
5409 // Start UNDO-REDO
5410 caja_undostack_manager_data_add_origin_target_pair (common->undo_redo_data, src, dest);
5411 // End UNDO-REDO
5412 g_free (path);
5413 if (debuting_files) {
5414 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
5415 }
5416
5417 caja_file_changes_queue_file_added (dest);
5418 if (position) {
5419 caja_file_changes_queue_schedule_position_set (dest, *position, common->screen_num);
5420 } else {
5421 caja_file_changes_queue_schedule_position_remove (dest);
5422 }
5423
5424 g_object_unref (dest);
5425
5426 return;
5427 }
5428 g_free (path);
5429
5430 if (error != NULL((void*)0) &&
5431 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
5432 !handled_invalid_filename) {
5433 handled_invalid_filename = TRUE(!(0));
5434
5435 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_66
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_66 = 1; else
_g_boolean_var_66 = 0; _g_boolean_var_66; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 5435, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
5436 *dest_fs_type = query_fs_type (dest_dir, common->cancellable);
5437
5438 new_dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5439
5440 if (!g_file_equal (dest, new_dest)) {
5441 g_object_unref (dest);
5442 dest = new_dest;
5443 g_error_free (error);
5444
5445 goto retry;
5446 } else {
5447 g_object_unref (new_dest);
5448 }
5449 }
5450 /* Conflict */
5451 if (error != NULL((void*)0) && IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
5452 g_object_unref (dest);
5453 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count++);
5454 g_error_free (error);
5455 goto retry;
5456 }
5457
5458 else if (error != NULL((void*)0) && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
5459 g_error_free (error);
5460 }
5461
5462 /* Other error */
5463 else {
5464 if (common->skip_all_error) {
5465 goto out;
5466 }
5467 primary = f (_("Error while creating link to %B.")dcgettext (((void*)0), "Error while creating link to %B.", 5), src);
5468 if (not_local) {
5469 secondary = f (_("Symbolic links only supported for local files")dcgettext (((void*)0), "Symbolic links only supported for local files"
, 5)
);
5470 details = NULL((void*)0);
5471 } else if (error != NULL((void*)0) && IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
5472 secondary = f (_("The target doesn't support symbolic links.")dcgettext (((void*)0), "The target doesn't support symbolic links."
, 5)
);
5473 details = NULL((void*)0);
5474 } else {
5475 secondary = f (_("There was an error creating the symlink in %F.")dcgettext (((void*)0), "There was an error creating the symlink in %F."
, 5)
, dest_dir);
5476 details = error ? error->message : NULL((void*)0);
5477 }
5478
5479 response = run_warning (common,
5480 primary,
5481 secondary,
5482 details,
5483 files_left > 1,
5484 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
5485 NULL((void*)0));
5486
5487 if (error) {
5488 g_error_free (error);
5489 }
5490
5491 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5492 abort_job (common);
5493 } else if (response == 1) { /* skip all */
5494 common->skip_all_error = TRUE(!(0));
5495 } else if (response == 2) { /* skip */
5496 /* do nothing */
5497 } else {
5498 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5498, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5499 }
5500 }
5501
5502 out:
5503 g_object_unref (dest);
5504}
5505
5506static gboolean
5507link_job_done (gpointer user_data)
5508{
5509 CopyMoveJob *job;
5510
5511 job = user_data;
5512 if (job->done_callback) {
5513 job->done_callback (job->debuting_files, job->done_callback_data);
5514 }
5515
5516 g_list_free_full (job->files, g_object_unref);
5517 g_object_unref (job->destination);
5518 g_hash_table_unref (job->debuting_files);
5519 g_free (job->icon_positions);
5520
5521 finalize_common ((CommonJob *)job);
5522
5523 caja_file_changes_consume_changes (TRUE(!(0)));
5524 return FALSE(0);
5525}
5526
5527static gboolean
5528link_job (GIOSchedulerJob *io_job,
5529 GCancellable *cancellable,
5530 gpointer user_data)
5531{
5532 CopyMoveJob *job;
5533 CommonJob *common;
5534 GFile *src;
5535 GdkPoint *point;
5536 char *dest_fs_type;
5537 int total, left;
5538 int i;
5539 GList *l;
5540
5541 job = user_data;
5542 common = &job->common;
5543 common->io_job = io_job;
5544
5545 dest_fs_type = NULL((void*)0);
5546
5547 caja_progress_info_start (job->common.progress);
5548
5549 verify_destination (&job->common,
5550 job->destination,
5551 NULL((void*)0),
5552 -1);
5553 if (job_aborted (common)) {
5554 goto aborted;
5555 }
5556
5557 total = left = g_list_length (job->files);
5558
5559 report_link_progress (job, total, left);
5560
5561 i = 0;
5562 for (l = job->files;
5563 l != NULL((void*)0) && !job_aborted (common);
5564 l = l->next) {
5565 caja_progress_info_get_ready (common->progress);
5566
5567 src = l->data;
5568
5569 if (i < job->n_icon_positions) {
5570 point = &job->icon_positions[i];
5571 } else {
5572 point = NULL((void*)0);
5573 }
5574
5575
5576 link_file (job, src, job->destination,
5577 &dest_fs_type, job->debuting_files,
5578 point, left);
5579 report_link_progress (job, total, --left);
5580 i++;
5581
5582 }
5583
5584 aborted:
5585 g_free (dest_fs_type);
5586
5587 g_io_scheduler_job_send_to_mainloop (io_job,
5588 link_job_done,
5589 job,
5590 NULL((void*)0));
5591
5592 return FALSE(0);
5593}
5594
5595void
5596caja_file_operations_link (GList *files,
5597 GArray *relative_item_points,
5598 GFile *target_dir,
5599 GtkWindow *parent_window,
5600 CajaCopyCallback done_callback,
5601 gpointer done_callback_data)
5602{
5603 CopyMoveJob *job;
5604
5605 job = op_job_new (CopyMoveJob, parent_window, TRUE, FALSE)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (!(0)), (0))))
;
5606 job->done_callback = done_callback;
5607 job->done_callback_data = done_callback_data;
5608 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5609 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5610 if (relative_item_points != NULL((void*)0) &&
5611 relative_item_points->len > 0) {
5612 job->icon_positions =
5613 g_memdup (relative_item_points->data,
5614 sizeof (GdkPoint) * relative_item_points->len);
5615 job->n_icon_positions = relative_item_points->len;
5616 }
5617 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5618
5619 // Start UNDO-REDO
5620 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5621 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATELINK, g_list_length(files));
5622 GFile* src_dir = g_file_get_parent (files->data);
5623 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5624 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5625 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
5626 }
5627 // End UNDO-REDO
5628
5629 g_io_scheduler_push_job (link_job,
5630 job,
5631 NULL((void*)0), /* destroy notify */
5632 0,
5633 job->common.cancellable);
5634}
5635
5636
5637void
5638caja_file_operations_duplicate (GList *files,
5639 GArray *relative_item_points,
5640 GtkWindow *parent_window,
5641 CajaCopyCallback done_callback,
5642 gpointer done_callback_data)
5643{
5644 CopyMoveJob *job;
5645
5646 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
5647 job->done_callback = done_callback;
5648 job->done_callback_data = done_callback_data;
5649 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5650 job->destination = NULL((void*)0);
5651 if (relative_item_points != NULL((void*)0) &&
5652 relative_item_points->len > 0) {
5653 job->icon_positions =
5654 g_memdup (relative_item_points->data,
5655 sizeof (GdkPoint) * relative_item_points->len);
5656 job->n_icon_positions = relative_item_points->len;
5657 }
5658 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5659
5660 // Start UNDO-REDO
5661 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5662 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_DUPLICATE, g_list_length(files));
5663 GFile* src_dir = g_file_get_parent (files->data);
5664 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5665 g_object_ref (src_dir)((__typeof__ (src_dir)) (g_object_ref) (src_dir));
5666 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, src_dir);
5667 }
5668 // End UNDO-REDO
5669
5670 g_io_scheduler_push_job (copy_job,
5671 job,
5672 NULL((void*)0), /* destroy notify */
5673 0,
5674 job->common.cancellable);
5675}
5676
5677static gboolean
5678set_permissions_job_done (gpointer user_data)
5679{
5680 SetPermissionsJob *job;
5681
5682 job = user_data;
5683
5684 g_object_unref (job->file);
5685
5686 if (job->done_callback) {
5687 job->done_callback (job->done_callback_data);
5688 }
5689
5690 finalize_common ((CommonJob *)job);
5691 return FALSE(0);
5692}
5693
5694static void
5695set_permissions_file (SetPermissionsJob *job,
5696 GFile *file,
5697 GFileInfo *info)
5698{
5699 CommonJob *common;
5700 gboolean free_info;
5701 guint32 current;
5702 guint32 value;
5703 guint32 mask;
5704
5705 common = (CommonJob *)job;
5706
5707 caja_progress_info_pulse_progress (common->progress);
5708
5709 caja_progress_info_get_ready (common->progress);
5710
5711 free_info = FALSE(0);
5712 if (info == NULL((void*)0)) {
5713 free_info = TRUE(!(0));
5714 info = g_file_query_info (file,
5715 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5716 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5717 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5718 common->cancellable,
5719 NULL((void*)0));
5720 /* Ignore errors */
5721 if (info == NULL((void*)0)) {
5722 return;
5723 }
5724 }
5725
5726 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5727 value = job->dir_permissions;
5728 mask = job->dir_mask;
5729 } else {
5730 value = job->file_permissions;
5731 mask = job->file_mask;
5732 }
5733
5734
5735 if (!job_aborted (common) &&
5736 g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
5737 current = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
5738 // Start UNDO-REDO
5739 caja_undostack_manager_data_add_file_permissions(common->undo_redo_data, file, current);
5740 // End UNDO-REDO
5741 current = (current & ~mask) | value;
5742
5743 g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5744 current, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5745 common->cancellable, NULL((void*)0));
5746 }
5747
5748 if (!job_aborted (common) && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5749 GFileEnumerator *enumerator;
5750
5751 enumerator = g_file_enumerate_children (file,
5752 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
5753 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5754 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5755 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5756 common->cancellable,
5757 NULL((void*)0));
5758 if (enumerator) {
5759 GFile *child = NULL((void*)0);
5760 GFileInfo *child_info = NULL((void*)0);
5761
5762 while (!job_aborted (common) &&
5763 (child_info = g_file_enumerator_next_file (enumerator, common->cancellable, NULL((void*)0))) != NULL((void*)0)) {
5764 child = g_file_get_child (file,
5765 g_file_info_get_name (child_info));
5766 set_permissions_file (job, child, child_info);
5767 g_object_unref (child);
5768 g_object_unref (child_info);
5769 }
5770 g_file_enumerator_close (enumerator, common->cancellable, NULL((void*)0));
5771 g_object_unref (enumerator);
5772 }
5773 }
5774 if (free_info) {
5775 g_object_unref (info);
5776 }
5777}
5778
5779
5780static gboolean
5781set_permissions_job (GIOSchedulerJob *io_job,
5782 GCancellable *cancellable,
5783 gpointer user_data)
5784{
5785 SetPermissionsJob *job = user_data;
5786 CommonJob *common;
5787
5788 common = (CommonJob *)job;
5789 common->io_job = io_job;
5790
5791 caja_progress_info_set_status (common->progress,
5792 _("Setting permissions")dcgettext (((void*)0), "Setting permissions", 5));
5793
5794 caja_progress_info_start (job->common.progress);
5795
5796 set_permissions_file (job, job->file, NULL((void*)0));
5797
5798 g_io_scheduler_job_send_to_mainloop_async (io_job,
5799 set_permissions_job_done,
5800 job,
5801 NULL((void*)0));
5802
5803 return FALSE(0);
5804}
5805
5806
5807
5808void
5809caja_file_set_permissions_recursive (const char *directory,
5810 guint32 file_permissions,
5811 guint32 file_mask,
5812 guint32 dir_permissions,
5813 guint32 dir_mask,
5814 CajaOpCallback callback,
5815 gpointer callback_data)
5816{
5817 SetPermissionsJob *job;
5818
5819 job = op_job_new (SetPermissionsJob, NULL, TRUE, FALSE)((SetPermissionsJob *)(init_common (sizeof(SetPermissionsJob)
, ((void*)0), (!(0)), (0))))
;
5820 job->file = g_file_new_for_uri (directory);
5821 job->file_permissions = file_permissions;
5822 job->file_mask = file_mask;
5823 job->dir_permissions = dir_permissions;
5824 job->dir_mask = dir_mask;
5825 job->done_callback = callback;
5826 job->done_callback_data = callback_data;
5827
5828 // Start UNDO-REDO
5829 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5830 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RECURSIVESETPERMISSIONS, 1);
5831 g_object_ref (job->file)((__typeof__ (job->file)) (g_object_ref) (job->file));
5832 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, job->file);
5833 caja_undostack_manager_data_set_recursive_permissions(job->common.undo_redo_data, file_permissions, file_mask, dir_permissions, dir_mask);
5834 }
5835 // End UNDO-REDO
5836
5837 g_io_scheduler_push_job (set_permissions_job,
5838 job,
5839 NULL((void*)0),
5840 0,
5841 NULL((void*)0));
5842}
5843
5844static GList *
5845location_list_from_uri_list (const GList *uris)
5846{
5847 const GList *l;
5848 GList *files;
5849 GFile *f = NULL((void*)0);
5850
5851 files = NULL((void*)0);
5852 for (l = uris; l != NULL((void*)0); l = l->next) {
5853 f = g_file_new_for_uri (l->data);
5854 files = g_list_prepend (files, f);
5855 }
5856
5857 return g_list_reverse (files);
5858}
5859
5860typedef struct {
5861 CajaCopyCallback real_callback;
5862 gpointer real_data;
5863} MoveTrashCBData;
5864
5865static void
5866callback_for_move_to_trash (GHashTable *debuting_uris,
5867 gboolean user_cancelled,
5868 MoveTrashCBData *data)
5869{
5870 if (data->real_callback)
5871 data->real_callback (debuting_uris, data->real_data);
5872 g_slice_free (MoveTrashCBData, data)do { if (1) g_slice_free1 (sizeof (MoveTrashCBData), (data));
else (void) ((MoveTrashCBData*) 0 == (data)); } while (0)
;
5873}
5874
5875void
5876caja_file_operations_copy_move (const GList *item_uris,
5877 GArray *relative_item_points,
5878 const char *target_dir,
5879 GdkDragAction copy_action,
5880 GtkWidget *parent_view,
5881 CajaCopyCallback done_callback,
5882 gpointer done_callback_data)
5883{
5884 GList *locations;
5885 GList *p;
5886 GFile *src_dir;
5887 GFile *dest;
5888 GtkWindow *parent_window;
5889 gboolean target_is_mapping;
5890 gboolean have_nonmapping_source;
5891
5892 dest = NULL((void*)0);
5893 target_is_mapping = FALSE(0);
5894 have_nonmapping_source = FALSE(0);
5895
5896 if (target_dir) {
5897 dest = g_file_new_for_uri (target_dir);
5898 if (g_file_has_uri_scheme (dest, "burn")) {
5899 target_is_mapping = TRUE(!(0));
5900 }
5901 }
5902
5903 locations = location_list_from_uri_list (item_uris);
5904
5905 for (p = location_list_from_uri_list (item_uris); p != NULL((void*)0); p = p->next) {
5906 if (!g_file_has_uri_scheme ((GFile* )p->data, "burn")) {
5907 have_nonmapping_source = TRUE(!(0));
5908 }
5909 }
5910
5911 if (target_is_mapping && have_nonmapping_source && copy_action == GDK_ACTION_MOVE) {
5912 /* never move to "burn:///", but fall back to copy.
5913 * This is a workaround, because otherwise the source files would be removed.
5914 */
5915 copy_action = GDK_ACTION_COPY;
5916 }
5917
5918 parent_window = NULL((void*)0);
5919 if (parent_view) {
5920 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
5921 }
5922
5923 src_dir = g_file_get_parent (locations->data);
5924
5925 if (copy_action == GDK_ACTION_COPY) {
5926 if (target_dir == NULL((void*)0) ||
5927 (src_dir != NULL((void*)0) &&
5928 g_file_equal (src_dir, dest))) {
5929 caja_file_operations_duplicate (locations,
5930 relative_item_points,
5931 parent_window,
5932 done_callback, done_callback_data);
5933 } else {
5934 caja_file_operations_copy (locations,
5935 relative_item_points,
5936 dest,
5937 parent_window,
5938 done_callback, done_callback_data);
5939 }
5940 } else if (copy_action == GDK_ACTION_MOVE) {
5941 if (g_file_has_uri_scheme (dest, "trash")) {
5942 MoveTrashCBData *cb_data;
5943
5944 cb_data = g_slice_new0 (MoveTrashCBData)(MoveTrashCBData *) (__extension__ ({ gsize __s = sizeof (MoveTrashCBData
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
5945 cb_data->real_callback = done_callback;
5946 cb_data->real_data = done_callback_data;
5947 caja_file_operations_trash_or_delete (locations,
5948 parent_window,
5949 (CajaDeleteCallback) callback_for_move_to_trash,
5950 cb_data);
5951 } else if (src_dir == NULL((void*)0) || !g_file_equal (src_dir, dest)) {
5952 caja_file_operations_move (locations,
5953 relative_item_points,
5954 dest,
5955 parent_window,
5956 done_callback, done_callback_data);
5957 }
5958 } else {
5959 caja_file_operations_link (locations,
5960 relative_item_points,
5961 dest,
5962 parent_window,
5963 done_callback, done_callback_data);
5964 }
5965
5966 g_list_free_full (locations, g_object_unref);
5967 if (dest) {
5968 g_object_unref (dest);
5969 }
5970
5971 if (src_dir) {
5972 g_object_unref (src_dir);
5973 }
5974}
5975
5976static gboolean
5977create_job_done (gpointer user_data)
5978{
5979 CreateJob *job;
5980
5981 job = user_data;
5982 if (job->done_callback) {
5983 job->done_callback (job->created_file, job->done_callback_data);
5984 }
5985
5986 g_object_unref (job->dest_dir);
5987 if (job->src) {
5988 g_object_unref (job->src);
5989 }
5990 g_free (job->src_data);
5991 g_free (job->filename);
5992 if (job->created_file) {
5993 g_object_unref (job->created_file);
5994 }
5995
5996 finalize_common ((CommonJob *)job);
5997
5998 caja_file_changes_consume_changes (TRUE(!(0)));
5999 return FALSE(0);
6000}
6001
6002static gboolean
6003create_job (GIOSchedulerJob *io_job,
6004 GCancellable *cancellable,
6005 gpointer user_data)
6006{
6007 CreateJob *job;
6008 CommonJob *common;
6009 int count;
6010 GFile *dest;
6011 char *filename, *filename2, *new_filename;
6012 char *dest_fs_type;
6013 GError *error;
6014 gboolean res;
6015 gboolean filename_is_utf8;
6016 char *primary, *secondary, *details;
6017 int response;
6018 char *data;
6019 int length;
6020 GFileOutputStream *out;
6021 gboolean handled_invalid_filename;
6022 int max_length;
6023
6024 job = user_data;
6025 common = &job->common;
6026 common->io_job = io_job;
6027
6028 caja_progress_info_start (job->common.progress);
6029
6030 handled_invalid_filename = FALSE(0);
6031
6032 dest_fs_type = NULL((void*)0);
6033 filename = NULL((void*)0);
6034 dest = NULL((void*)0);
6035
6036 max_length = get_max_name_length (job->dest_dir);
6037
6038 verify_destination (common,
6039 job->dest_dir,
6040 NULL((void*)0), -1);
6041 if (job_aborted (common)) {
6042 goto aborted;
6043 }
6044
6045 filename = g_strdup (job->filename)g_strdup_inline (job->filename);
6046 filename_is_utf8 = FALSE(0);
6047 if (filename) {
6048 filename_is_utf8 = g_utf8_validate (filename, -1, NULL((void*)0));
6049 }
6050 if (filename == NULL((void*)0)) {
6051 if (job->make_dir) {
6052 /* Translators: the initial name of a new folder */
6053 filename = g_strdup (_("untitled folder"))g_strdup_inline (dcgettext (((void*)0), "untitled folder", 5)
)
;
6054 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6055 } else {
6056 if (job->src != NULL((void*)0)) {
6057 filename = g_file_get_basename (job->src);
6058 }
6059 if (filename == NULL((void*)0)) {
6060 /* Translators: the initial name of a new empty file */
6061 filename = g_strdup (_("new file"))g_strdup_inline (dcgettext (((void*)0), "new file", 5));
6062 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6063 }
6064 }
6065 }
6066
6067 make_file_name_valid_for_dest_fs (filename, dest_fs_type);
6068 if (filename_is_utf8) {
6069 dest = g_file_get_child_for_display_name (job->dest_dir, filename, NULL((void*)0));
6070 }
6071 if (dest == NULL((void*)0)) {
6072 dest = g_file_get_child (job->dest_dir, filename);
6073 }
6074 count = 1;
6075
6076 retry:
6077 caja_progress_info_get_ready (common->progress);
6078
6079 error = NULL((void*)0);
6080 if (job->make_dir) {
6081 res = g_file_make_directory (dest,
6082 common->cancellable,
6083 &error);
6084 // Start UNDO-REDO
6085 if (res) {
6086 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6087 g_file_get_uri(dest),
6088 NULL((void*)0));
6089 }
6090 // End UNDO-REDO
6091 } else {
6092 if (job->src) {
6093 res = g_file_copy (job->src,
6094 dest,
6095 G_FILE_COPY_NONE,
6096 common->cancellable,
6097 NULL((void*)0), NULL((void*)0),
6098 &error);
6099 // Start UNDO-REDO
6100 if (res) {
6101 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6102 g_file_get_uri(dest),
6103 g_file_get_uri(job->src));
6104 }
6105 // End UNDO-REDO
6106 } else {
6107 data = "";
6108 length = 0;
6109 if (job->src_data) {
6110 data = job->src_data;
6111 length = job->length;
6112 }
6113
6114 out = g_file_create (dest,
6115 G_FILE_CREATE_NONE,
6116 common->cancellable,
6117 &error);
6118 if (out) {
6119 res = g_output_stream_write_all (G_OUTPUT_STREAM (out)((((GOutputStream*) (void *) ((out))))),
6120 data, length,
6121 NULL((void*)0),
6122 common->cancellable,
6123 &error);
6124 if (res) {
6125 res = g_output_stream_close (G_OUTPUT_STREAM (out)((((GOutputStream*) (void *) ((out))))),
6126 common->cancellable,
6127 &error);
6128 // Start UNDO-REDO
6129 if (res) {
6130 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6131 g_file_get_uri(dest),
6132 g_strdup(data)g_strdup_inline (data));
6133 }
6134 // End UNDO-REDO
6135 }
6136
6137 /* This will close if the write failed and we didn't close */
6138 g_object_unref (out);
6139 } else {
6140 res = FALSE(0);
6141 }
6142 }
6143 }
6144
6145 if (res) {
6146 job->created_file = g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest));
6147 caja_file_changes_queue_file_added (dest);
6148 if (job->has_position) {
6149 caja_file_changes_queue_schedule_position_set (dest, job->position, common->screen_num);
6150 } else {
6151 caja_file_changes_queue_schedule_position_remove (dest);
6152 }
6153 } else {
6154 g_assert (error != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_67
; if (error != ((void*)0)) _g_boolean_var_67 = 1; else _g_boolean_var_67
= 0; _g_boolean_var_67; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 6154, ((const char*
) (__func__)), "error != NULL"); } while (0)
;
6155
6156 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
6157 !handled_invalid_filename) {
6158 handled_invalid_filename = TRUE(!(0));
6159
6160 g_assert (dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_68
; if (dest_fs_type == ((void*)0)) _g_boolean_var_68 = 1; else
_g_boolean_var_68 = 0; _g_boolean_var_68; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 6160, ((const char*
) (__func__)), "dest_fs_type == NULL"); } while (0)
;
6161 dest_fs_type = query_fs_type (job->dest_dir, common->cancellable);
6162
6163 g_object_unref (dest);
6164
6165 if (count == 1) {
6166 new_filename = g_strdup (filename)g_strdup_inline (filename);
6167 } else if (job->make_dir) {
6168 filename2 = g_strdup_printf ("%s %d", filename, count);
6169
6170 new_filename = NULL((void*)0);
6171 if (max_length > 0 && strlen (filename2) > max_length) {
6172 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6173 }
6174
6175 if (new_filename == NULL((void*)0)) {
6176 new_filename = g_strdup (filename2)g_strdup_inline (filename2);
6177 }
6178
6179 g_free (filename2);
6180 } else {
6181 new_filename = get_duplicate_name (filename, count, max_length);
6182 }
6183
6184 if (make_file_name_valid_for_dest_fs (new_filename, dest_fs_type)) {
6185 g_object_unref (dest);
6186
6187 if (filename_is_utf8) {
6188 dest = g_file_get_child_for_display_name (job->dest_dir, new_filename, NULL((void*)0));
6189 }
6190 if (dest == NULL((void*)0)) {
6191 dest = g_file_get_child (job->dest_dir, new_filename);
6192 }
6193
6194 g_free (new_filename);
6195 g_error_free (error);
6196 goto retry;
6197 }
6198 g_free (new_filename);
6199 } else if (IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
6200 g_object_unref (dest);
6201 dest = NULL((void*)0);
6202 if (job->make_dir) {
6203 filename2 = g_strdup_printf ("%s %d", filename, ++count);
6204 if (max_length > 0 && strlen (filename2) > max_length) {
6205 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6206 if (new_filename != NULL((void*)0)) {
6207 g_free (filename2);
6208 filename2 = new_filename;
6209 }
6210 }
6211 } else {
6212 filename2 = get_duplicate_name (filename, count++, max_length);
6213 }
6214 make_file_name_valid_for_dest_fs (filename2, dest_fs_type);
6215 if (filename_is_utf8) {
6216 dest = g_file_get_child_for_display_name (job->dest_dir, filename2, NULL((void*)0));
6217 }
6218 if (dest == NULL((void*)0)) {
6219 dest = g_file_get_child (job->dest_dir, filename2);
6220 }
6221 g_free (filename2);
6222 g_error_free (error);
6223 goto retry;
6224 }
6225
6226 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
6227 g_error_free (error);
6228 }
6229
6230 /* Other error */
6231 else {
6232 if (job->make_dir) {
6233 primary = f (_("Error while creating directory %B.")dcgettext (((void*)0), "Error while creating directory %B.", 5
)
, dest);
6234 } else {
6235 primary = f (_("Error while creating file %B.")dcgettext (((void*)0), "Error while creating file %B.", 5), dest);
6236 }
6237 secondary = f (_("There was an error creating the directory in %F.")dcgettext (((void*)0), "There was an error creating the directory in %F."
, 5)
, job->dest_dir);
6238 details = error->message;
6239
6240 response = run_warning (common,
6241 primary,
6242 secondary,
6243 details,
6244 FALSE(0),
6245 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
6246 NULL((void*)0));
6247
6248 g_error_free (error);
6249
6250 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6251 abort_job (common);
6252 } else if (response == 1) { /* skip */
6253 /* do nothing */
6254 } else {
6255 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6255, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6256 }
6257 }
6258 }
6259
6260 aborted:
6261 if (dest) {
6262 g_object_unref (dest);
6263 }
6264 g_free (filename);
6265 g_free (dest_fs_type);
6266 g_io_scheduler_job_send_to_mainloop_async (io_job,
6267 create_job_done,
6268 job,
6269 NULL((void*)0));
6270
6271 return FALSE(0);
6272}
6273
6274void
6275caja_file_operations_new_folder (GtkWidget *parent_view,
6276 GdkPoint *target_point,
6277 const char *parent_dir,
6278 CajaCreateCallback done_callback,
6279 gpointer done_callback_data)
6280{
6281 CreateJob *job;
6282 GtkWindow *parent_window;
6283
6284 parent_window = NULL((void*)0);
6285 if (parent_view) {
6286 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6287 }
6288
6289 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6290 job->done_callback = done_callback;
6291 job->done_callback_data = done_callback_data;
6292 job->dest_dir = g_file_new_for_uri (parent_dir);
6293 job->make_dir = TRUE(!(0));
6294 if (target_point != NULL((void*)0)) {
6295 job->position = *target_point;
6296 job->has_position = TRUE(!(0));
6297 }
6298
6299 // Start UNDO-REDO
6300 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6301 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEFOLDER, 1);
6302 }
6303 // End UNDO-REDO
6304
6305 g_io_scheduler_push_job (create_job,
6306 job,
6307 NULL((void*)0), /* destroy notify */
6308 0,
6309 job->common.cancellable);
6310}
6311
6312void
6313caja_file_operations_new_file_from_template (GtkWidget *parent_view,
6314 GdkPoint *target_point,
6315 const char *parent_dir,
6316 const char *target_filename,
6317 const char *template_uri,
6318 CajaCreateCallback done_callback,
6319 gpointer done_callback_data)
6320{
6321 CreateJob *job;
6322 GtkWindow *parent_window;
6323
6324 parent_window = NULL((void*)0);
6325 if (parent_view) {
6326 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6327 }
6328
6329 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6330 job->done_callback = done_callback;
6331 job->done_callback_data = done_callback_data;
6332 job->dest_dir = g_file_new_for_uri (parent_dir);
6333 if (target_point != NULL((void*)0)) {
6334 job->position = *target_point;
6335 job->has_position = TRUE(!(0));
6336 }
6337 job->filename = g_strdup (target_filename)g_strdup_inline (target_filename);
6338
6339 if (template_uri) {
6340 job->src = g_file_new_for_uri (template_uri);
6341 }
6342
6343 // Start UNDO-REDO
6344 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6345 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEFILEFROMTEMPLATE, 1);
6346 }
6347 // End UNDO-REDO
6348
6349 g_io_scheduler_push_job (create_job,
6350 job,
6351 NULL((void*)0), /* destroy notify */
6352 0,
6353 job->common.cancellable);
6354}
6355
6356void
6357caja_file_operations_new_file (GtkWidget *parent_view,
6358 GdkPoint *target_point,
6359 const char *parent_dir,
6360 const char *target_filename,
6361 const char *initial_contents,
6362 int length,
6363 CajaCreateCallback done_callback,
6364 gpointer done_callback_data)
6365{
6366 CreateJob *job;
6367 GtkWindow *parent_window;
6368
6369 parent_window = NULL((void*)0);
6370 if (parent_view) {
6371 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6372 }
6373
6374 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6375 job->done_callback = done_callback;
6376 job->done_callback_data = done_callback_data;
6377 job->dest_dir = g_file_new_for_uri (parent_dir);
6378 if (target_point != NULL((void*)0)) {
6379 job->position = *target_point;
6380 job->has_position = TRUE(!(0));
6381 }
6382 job->src_data = g_memdup (initial_contents, length);
6383 job->length = length;
6384 job->filename = g_strdup (target_filename)g_strdup_inline (target_filename);
6385
6386 // Start UNDO-REDO
6387 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6388 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEEMPTYFILE, 1);
6389 }
6390 // End UNDO-REDO
6391
6392 g_io_scheduler_push_job (create_job,
6393 job,
6394 NULL((void*)0), /* destroy notify */
6395 0,
6396 job->common.cancellable);
6397}
6398
6399
6400
6401static void
6402delete_trash_file (CommonJob *job,
6403 GFile *file,
6404 gboolean del_file,
6405 gboolean del_children)
6406{
6407 caja_progress_info_get_ready (job->progress);
6408
6409 if (job_aborted (job)) {
6410 return;
6411 }
6412
6413 if (del_children) {
6414 GFileEnumerator *enumerator;
6415
6416 enumerator = g_file_enumerate_children (file,
6417 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" ","
6418 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
6419 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6420 job->cancellable,
6421 NULL((void*)0));
6422 if (enumerator) {
6423 GFileInfo *info = NULL((void*)0);
6424 GFile *child = NULL((void*)0);
6425
6426 while (!job_aborted (job) &&
6427 (info = g_file_enumerator_next_file (enumerator, job->cancellable, NULL((void*)0))) != NULL((void*)0)) {
6428 child = g_file_get_child (file,
6429 g_file_info_get_name (info));
6430 delete_trash_file (job, child, TRUE(!(0)),
6431 g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY);
6432 g_object_unref (child);
6433 g_object_unref (info);
6434 }
6435 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
6436 g_object_unref (enumerator);
6437 }
6438 }
6439
6440 if (!job_aborted (job) && del_file) {
6441 g_file_delete (file, job->cancellable, NULL((void*)0));
6442 }
6443}
6444
6445static gboolean
6446empty_trash_job_done (gpointer user_data)
6447{
6448 EmptyTrashJob *job;
6449
6450 job = user_data;
6451
6452 g_list_free_full (job->trash_dirs, g_object_unref);
6453
6454 if (job->done_callback) {
6455 job->done_callback (job->done_callback_data);
6456 }
6457
6458 caja_undostack_manager_trash_has_emptied(caja_undostack_manager_instance());
6459
6460 finalize_common ((CommonJob *)job);
6461 return FALSE(0);
6462}
6463
6464static gboolean
6465empty_trash_job (GIOSchedulerJob *io_job,
6466 GCancellable *cancellable,
6467 gpointer user_data)
6468{
6469 EmptyTrashJob *job = user_data;
6470 CommonJob *common;
6471 GList *l;
6472 gboolean confirmed;
6473
6474 common = (CommonJob *)job;
6475 common->io_job = io_job;
6476
6477 caja_progress_info_start (job->common.progress);
6478
6479 if (job->should_confirm) {
6480 confirmed = confirm_empty_trash (common);
6481 } else {
6482 confirmed = TRUE(!(0));
6483 }
6484 if (confirmed) {
6485 for (l = job->trash_dirs;
6486 l != NULL((void*)0) && !job_aborted (common);
6487 l = l->next) {
6488 delete_trash_file (common, l->data, FALSE(0), TRUE(!(0)));
6489 }
6490 }
6491
6492 g_io_scheduler_job_send_to_mainloop_async (io_job,
6493 empty_trash_job_done,
6494 job,
6495 NULL((void*)0));
6496
6497 return FALSE(0);
6498}
6499
6500void
6501caja_file_operations_empty_trash (GtkWidget *parent_view)
6502{
6503 EmptyTrashJob *job;
6504 GtkWindow *parent_window;
6505
6506 parent_window = NULL((void*)0);
6507 if (parent_view) {
6508 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6509 }
6510
6511 job = op_job_new (EmptyTrashJob, parent_window, TRUE, FALSE)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
, (!(0)), (0))))
;
6512 job->trash_dirs = g_list_prepend (job->trash_dirs,
6513 g_file_new_for_uri ("trash:"));
6514 job->should_confirm = TRUE(!(0));
6515
6516 inhibit_power_manager ((CommonJob *)job, _("Emptying Trash")dcgettext (((void*)0), "Emptying Trash", 5));
6517
6518 g_io_scheduler_push_job (empty_trash_job,
6519 job,
6520 NULL((void*)0),
6521 0,
6522 NULL((void*)0));
6523}
6524
6525static gboolean
6526mark_trusted_job_done (gpointer user_data)
6527{
6528 MarkTrustedJob *job = user_data;
6529
6530 g_object_unref (job->file);
6531
6532 if (job->done_callback) {
6533 job->done_callback (job->done_callback_data);
6534 }
6535
6536 finalize_common ((CommonJob *)job);
6537 return FALSE(0);
6538}
6539
6540#define TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
6541
6542static void
6543mark_desktop_file_trusted (CommonJob *common,
6544 GCancellable *cancellable,
6545 GFile *file,
6546 gboolean interactive)
6547{
6548 char *contents, *new_contents;
6549 gsize length, new_length;
6550 GError *error;
6551 guint32 current_perms, new_perms;
6552 int response;
6553 GFileInfo *info;
6554
6555 retry:
6556 caja_progress_info_get_ready (common->progress);
6557
6558 error = NULL((void*)0);
6559 if (!g_file_load_contents (file,
6560 cancellable,
6561 &contents, &length,
6562 NULL((void*)0), &error)) {
6563 if (interactive) {
6564 response = run_error (common,
6565 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6566 error->message,
6567 NULL((void*)0),
6568 FALSE(0),
6569 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6570 NULL((void*)0));
6571 } else {
6572 response = 0;
6573 }
6574
6575
6576 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6577 abort_job (common);
6578 } else if (response == 1) {
6579 goto retry;
6580 } else {
6581 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6581, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6582 }
6583
6584 goto out;
6585 }
6586
6587 if (!g_str_has_prefix (contents, "#!")(__builtin_constant_p ("#!")? __extension__ ({ const char * const
__str = (contents); const char * const __prefix = ("#!"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_69
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_69
= 1; else _g_boolean_var_69 = 0; _g_boolean_var_69; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
contents, "#!") )
) {
6588 new_length = length + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n") + 1;
6589 new_contents = g_malloc0 (new_length);
6590
6591 g_strlcpy (new_contents, TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n", new_length);
6592 memcpy (new_contents + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n"),
6593 contents, length);
6594
6595 if (!g_file_replace_contents (file,
6596 new_contents,
6597 new_length,
6598 NULL((void*)0),
6599 FALSE(0), 0,
6600 NULL((void*)0), cancellable, &error)) {
6601 g_free (contents);
6602 g_free (new_contents);
6603
6604 if (interactive) {
6605 response = run_error (common,
6606 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6607 error->message,
6608 NULL((void*)0),
6609 FALSE(0),
6610 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6611 NULL((void*)0));
6612 } else {
6613 response = 0;
6614 }
6615
6616 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6617 abort_job (common);
6618 } else if (response == 1) {
6619 goto retry;
6620 } else {
6621 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6621, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6622 }
6623
6624 goto out;
6625 }
6626 g_free (new_contents);
6627
6628 }
6629 g_free (contents);
6630
6631 info = g_file_query_info (file,
6632 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
6633 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6634 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6635 common->cancellable,
6636 &error);
6637
6638 if (info == NULL((void*)0)) {
6639 if (interactive) {
6640 response = run_error (common,
6641 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6642 error->message,
6643 NULL((void*)0),
6644 FALSE(0),
6645 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6646 NULL((void*)0));
6647 } else {
6648 response = 0;
6649 }
6650
6651 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6652 abort_job (common);
6653 } else if (response == 1) {
6654 goto retry;
6655 } else {
6656 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6656, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6657 }
6658
6659 goto out;
6660 }
6661
6662
6663 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
6664 current_perms = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
6665 new_perms = current_perms | S_IXGRP(0100 >> 3) | S_IXUSR0100 | S_IXOTH((0100 >> 3) >> 3);
6666
6667 if ((current_perms != new_perms) &&
6668 !g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6669 new_perms, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6670 common->cancellable, &error))
6671 {
6672 g_object_unref (info);
6673
6674 if (interactive) {
6675 response = run_error (common,
6676 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6677 error->message,
6678 NULL((void*)0),
6679 FALSE(0),
6680 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6681 NULL((void*)0));
6682 } else {
6683 response = 0;
6684 }
6685
6686 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6687 abort_job (common);
6688 } else if (response == 1) {
6689 goto retry;
6690 } else {
6691 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6691, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6692 }
6693
6694 goto out;
6695 }
6696 }
6697 g_object_unref (info);
6698
6699 g_file_set_attribute_string (file,
6700 "metadata::" CAJA_METADATA_KEY_TRUSTED_LAUNCHER"caja-trusted-launcher", "true",
6701 G_FILE_QUERY_INFO_NONE,
6702 cancellable,
6703 NULL((void*)0));
6704 out:
6705 ;
6706}
6707
6708static gboolean
6709mark_trusted_job (GIOSchedulerJob *io_job,
6710 GCancellable *cancellable,
6711 gpointer user_data)
6712{
6713 MarkTrustedJob *job = user_data;
6714 CommonJob *common;
6715
6716 common = (CommonJob *)job;
6717 common->io_job = io_job;
6718
6719 caja_progress_info_start (job->common.progress);
6720
6721 mark_desktop_file_trusted (common,
6722 cancellable,
6723 job->file,
6724 job->interactive);
6725
6726 g_io_scheduler_job_send_to_mainloop_async (io_job,
6727 mark_trusted_job_done,
6728 job,
6729 NULL((void*)0));
6730
6731 return FALSE(0);
6732}
6733
6734void
6735caja_file_mark_desktop_file_trusted (GFile *file,
6736 GtkWindow *parent_window,
6737 gboolean interactive,
6738 CajaOpCallback done_callback,
6739 gpointer done_callback_data)
6740{
6741 MarkTrustedJob *job;
6742
6743 job = op_job_new (MarkTrustedJob, parent_window, TRUE, FALSE)((MarkTrustedJob *)(init_common (sizeof(MarkTrustedJob), parent_window
, (!(0)), (0))))
;
6744 job->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
6745 job->interactive = interactive;
6746 job->done_callback = done_callback;
6747 job->done_callback_data = done_callback_data;
6748
6749 g_io_scheduler_push_job (mark_trusted_job,
6750 job,
6751 NULL((void*)0),
6752 0,
6753 NULL((void*)0));
6754}
6755
6756#if !defined (CAJA_OMIT_SELF_CHECK)
6757
6758void
6759caja_self_check_file_operations (void)
6760{
6761 setlocale (LC_MESSAGES5, "C");
6762
6763
6764 /* test the next duplicate name generator */
6765 EEL_CHECK_STRING_RESULT (get_duplicate_name (" (copy)", 1, -1), " (another copy)")do { eel_before_check ("get_duplicate_name (\" (copy)\", 1, -1)"
, "caja-file-operations.c", 6765); eel_check_string_result (get_duplicate_name
(" (copy)", 1, -1), " (another copy)"); } while (0)
;
6766 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo", 1, -1), "foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo\", 1, -1)",
"caja-file-operations.c", 6766); eel_check_string_result (get_duplicate_name
("foo", 1, -1), "foo (copy)"); } while (0)
;
6767 EEL_CHECK_STRING_RESULT (get_duplicate_name (".bashrc", 1, -1), ".bashrc (copy)")do { eel_before_check ("get_duplicate_name (\".bashrc\", 1, -1)"
, "caja-file-operations.c", 6767); eel_check_string_result (get_duplicate_name
(".bashrc", 1, -1), ".bashrc (copy)"); } while (0)
;
6768 EEL_CHECK_STRING_RESULT (get_duplicate_name (".foo.txt", 1, -1), ".foo (copy).txt")do { eel_before_check ("get_duplicate_name (\".foo.txt\", 1, -1)"
, "caja-file-operations.c", 6768); eel_check_string_result (get_duplicate_name
(".foo.txt", 1, -1), ".foo (copy).txt"); } while (0)
;
6769 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo", 1, -1), "foo foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo foo\", 1, -1)"
, "caja-file-operations.c", 6769); eel_check_string_result (get_duplicate_name
("foo foo", 1, -1), "foo foo (copy)"); } while (0)
;
6770 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo.txt", 1, -1), "foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo.txt\", 1, -1)"
, "caja-file-operations.c", 6770); eel_check_string_result (get_duplicate_name
("foo.txt", 1, -1), "foo (copy).txt"); } while (0)
;
6771 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt\", 1, -1)"
, "caja-file-operations.c", 6771); eel_check_string_result (get_duplicate_name
("foo foo.txt", 1, -1), "foo foo (copy).txt"); } while (0)
;
6772 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt txt\", 1, -1)"
, "caja-file-operations.c", 6772); eel_check_string_result (get_duplicate_name
("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt"); } while
(0)
;
6773 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...txt", 1, -1), "foo (copy)...txt")do { eel_before_check ("get_duplicate_name (\"foo...txt\", 1, -1)"
, "caja-file-operations.c", 6773); eel_check_string_result (get_duplicate_name
("foo...txt", 1, -1), "foo (copy)...txt"); } while (0)
;
6774 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...", 1, -1), "foo (copy)...")do { eel_before_check ("get_duplicate_name (\"foo...\", 1, -1)"
, "caja-file-operations.c", 6774); eel_check_string_result (get_duplicate_name
("foo...", 1, -1), "foo (copy)..."); } while (0)
;
6775 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo. (copy)", 1, -1), "foo. (another copy)")do { eel_before_check ("get_duplicate_name (\"foo. (copy)\", 1, -1)"
, "caja-file-operations.c", 6775); eel_check_string_result (get_duplicate_name
("foo. (copy)", 1, -1), "foo. (another copy)"); } while (0)
;
6776 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy)", 1, -1), "foo (another copy)")do { eel_before_check ("get_duplicate_name (\"foo (copy)\", 1, -1)"
, "caja-file-operations.c", 6776); eel_check_string_result (get_duplicate_name
("foo (copy)", 1, -1), "foo (another copy)"); } while (0)
;
6777 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy).txt", 1, -1), "foo (another copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (copy).txt\", 1, -1)"
, "caja-file-operations.c", 6777); eel_check_string_result (get_duplicate_name
("foo (copy).txt", 1, -1), "foo (another copy).txt"); } while
(0)
;
6778 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy)", 1, -1), "foo (3rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (another copy)\", 1, -1)"
, "caja-file-operations.c", 6778); eel_check_string_result (get_duplicate_name
("foo (another copy)", 1, -1), "foo (3rd copy)"); } while (0
)
;
6779 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy).txt", 1, -1), "foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (another copy).txt\", 1, -1)"
, "caja-file-operations.c", 6779); eel_check_string_result (get_duplicate_name
("foo (another copy).txt", 1, -1), "foo (3rd copy).txt"); } while
(0)
;
6780 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (another copy).txt\", 1, -1)"
, "caja-file-operations.c", 6780); eel_check_string_result (get_duplicate_name
("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt"
); } while (0)
;
6781 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy)", 1, -1), "foo (14th copy)")do { eel_before_check ("get_duplicate_name (\"foo (13th copy)\", 1, -1)"
, "caja-file-operations.c", 6781); eel_check_string_result (get_duplicate_name
("foo (13th copy)", 1, -1), "foo (14th copy)"); } while (0)
;
6782 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy).txt", 1, -1), "foo (14th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (13th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6782); eel_check_string_result (get_duplicate_name
("foo (13th copy).txt", 1, -1), "foo (14th copy).txt"); } while
(0)
;
6783 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy)", 1, -1), "foo (22nd copy)")do { eel_before_check ("get_duplicate_name (\"foo (21st copy)\", 1, -1)"
, "caja-file-operations.c", 6783); eel_check_string_result (get_duplicate_name
("foo (21st copy)", 1, -1), "foo (22nd copy)"); } while (0)
;
6784 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (21st copy).txt\", 1, -1)"
, "caja-file-operations.c", 6784); eel_check_string_result (get_duplicate_name
("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt"); } while
(0)
;
6785 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy)", 1, -1), "foo (23rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy)\", 1, -1)"
, "caja-file-operations.c", 6785); eel_check_string_result (get_duplicate_name
("foo (22nd copy)", 1, -1), "foo (23rd copy)"); } while (0)
;
6786 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6786); eel_check_string_result (get_duplicate_name
("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt"); } while
(0)
;
6787 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy)", 1, -1), "foo (24th copy)")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy)\", 1, -1)"
, "caja-file-operations.c", 6787); eel_check_string_result (get_duplicate_name
("foo (23rd copy)", 1, -1), "foo (24th copy)"); } while (0)
;
6788 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6788); eel_check_string_result (get_duplicate_name
("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt"); } while
(0)
;
6789 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy)", 1, -1), "foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo (24th copy)\", 1, -1)"
, "caja-file-operations.c", 6789); eel_check_string_result (get_duplicate_name
("foo (24th copy)", 1, -1), "foo (25th copy)"); } while (0)
;
6790 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy).txt", 1, -1), "foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (24th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6790); eel_check_string_result (get_duplicate_name
("foo (24th copy).txt", 1, -1), "foo (25th copy).txt"); } while
(0)
;
6791 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy)", 1, -1), "foo foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy)\", 1, -1)"
, "caja-file-operations.c", 6791); eel_check_string_result (get_duplicate_name
("foo foo (24th copy)", 1, -1), "foo foo (25th copy)"); } while
(0)
;
6792 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6792); eel_check_string_result (get_duplicate_name
("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt"
); } while (0)
;
6793 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (100000000000000th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6793); eel_check_string_result (get_duplicate_name
("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt"
); } while (0)
;
6794 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy)", 1, -1), "foo (11th copy)")do { eel_before_check ("get_duplicate_name (\"foo (10th copy)\", 1, -1)"
, "caja-file-operations.c", 6794); eel_check_string_result (get_duplicate_name
("foo (10th copy)", 1, -1), "foo (11th copy)"); } while (0)
;
6795 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy).txt", 1, -1), "foo (11th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (10th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6795); eel_check_string_result (get_duplicate_name
("foo (10th copy).txt", 1, -1), "foo (11th copy).txt"); } while
(0)
;
6796 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy)", 1, -1), "foo (12th copy)")do { eel_before_check ("get_duplicate_name (\"foo (11th copy)\", 1, -1)"
, "caja-file-operations.c", 6796); eel_check_string_result (get_duplicate_name
("foo (11th copy)", 1, -1), "foo (12th copy)"); } while (0)
;
6797 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy).txt", 1, -1), "foo (12th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (11th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6797); eel_check_string_result (get_duplicate_name
("foo (11th copy).txt", 1, -1), "foo (12th copy).txt"); } while
(0)
;
6798 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy)", 1, -1), "foo (13th copy)")do { eel_before_check ("get_duplicate_name (\"foo (12th copy)\", 1, -1)"
, "caja-file-operations.c", 6798); eel_check_string_result (get_duplicate_name
("foo (12th copy)", 1, -1), "foo (13th copy)"); } while (0)
;
6799 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy).txt", 1, -1), "foo (13th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (12th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6799); eel_check_string_result (get_duplicate_name
("foo (12th copy).txt", 1, -1), "foo (13th copy).txt"); } while
(0)
;
6800 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy)", 1, -1), "foo (111th copy)")do { eel_before_check ("get_duplicate_name (\"foo (110th copy)\", 1, -1)"
, "caja-file-operations.c", 6800); eel_check_string_result (get_duplicate_name
("foo (110th copy)", 1, -1), "foo (111th copy)"); } while (0
)
;
6801 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy).txt", 1, -1), "foo (111th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (110th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6801); eel_check_string_result (get_duplicate_name
("foo (110th copy).txt", 1, -1), "foo (111th copy).txt"); } while
(0)
;
6802 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy)", 1, -1), "foo (123rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy)\", 1, -1)"
, "caja-file-operations.c", 6802); eel_check_string_result (get_duplicate_name
("foo (122nd copy)", 1, -1), "foo (123rd copy)"); } while (0
)
;
6803 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6803); eel_check_string_result (get_duplicate_name
("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt"); } while
(0)
;
6804 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy)", 1, -1), "foo (124th copy)")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy)\", 1, -1)"
, "caja-file-operations.c", 6804); eel_check_string_result (get_duplicate_name
("foo (123rd copy)", 1, -1), "foo (124th copy)"); } while (0
)
;
6805 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6805); eel_check_string_result (get_duplicate_name
("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt"); } while
(0)
;
6806
6807 setlocale (LC_MESSAGES5, "");
6808}
6809
6810#endif
diff --git a/2024-07-29-023715-6438-1/report-bedbd9.html b/2024-07-29-023715-6438-1/report-bedbd9.html new file mode 100644 index 000000000..50e6a7cf6 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-bedbd9.html @@ -0,0 +1,9582 @@ + + + +caja-file.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file.c
Warning:line 2792, column 2
Value stored to 'time' 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 caja-file.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-file.c: Caja file model.
4
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <grp.h>
27#include <gtk/gtk.h>
28#include <glib/gi18n.h>
29#include <glib/gstdio.h>
30#include <gio/gio.h>
31#include <glib.h>
32#include <libxml/parser.h>
33#include <pwd.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <sys/time.h>
37#include <time.h>
38#include <unistd.h>
39#include <sys/stat.h>
40
41#include <eel/eel-debug.h>
42#include <eel/eel-glib-extensions.h>
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-vfs-extensions.h>
45#include <eel/eel-gtk-macros.h>
46#include <eel/eel-string.h>
47
48#include <libcaja-extension/caja-file-info.h>
49#include <libcaja-extension/caja-extension-private.h>
50#include <libcaja-private/caja-extensions.h>
51
52#include "caja-file.h"
53#include "caja-directory-notify.h"
54#include "caja-directory-private.h"
55#include "caja-signaller.h"
56#include "caja-desktop-directory.h"
57#include "caja-desktop-directory-file.h"
58#include "caja-desktop-icon-file.h"
59#include "caja-file-attributes.h"
60#include "caja-file-private.h"
61#include "caja-file-operations.h"
62#include "caja-file-utilities.h"
63#include "caja-global-preferences.h"
64#include "caja-lib-self-check-functions.h"
65#include "caja-link.h"
66#include "caja-metadata.h"
67#include "caja-module.h"
68#include "caja-search-directory.h"
69#include "caja-search-directory-file.h"
70#include "caja-thumbnails.h"
71#include "caja-ui-utilities.h"
72#include "caja-vfs-file.h"
73#include "caja-saved-search-file.h"
74
75#ifdef HAVE_SELINUX1
76#include <selinux/selinux.h>
77#endif
78
79#define ICON_NAME_THUMBNAIL_LOADING"image-loading" "image-loading"
80
81#undef CAJA_FILE_DEBUG_REF
82#undef CAJA_FILE_DEBUG_REF_VALGRIND
83
84#ifdef CAJA_FILE_DEBUG_REF_VALGRIND
85#include <valgrind/valgrind.h>
86#define DEBUG_REF_PRINTFprintf VALGRIND_PRINTF_BACKTRACE
87#else
88#define DEBUG_REF_PRINTFprintf printf
89#endif
90
91/* Files that start with these characters sort after files that don't. */
92#define SORT_LAST_CHAR1'.' '.'
93#define SORT_LAST_CHAR2'#' '#'
94
95#define METADATA_ID_IS_LIST_MASK(1U<<31) (1U<<31)
96
97#define SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3 3
98#define SORT_BY_EXTENSION_MAX_SEGMENTS3 3
99
100typedef enum {
101 SHOW_HIDDEN = 1 << 0,
102 SHOW_BACKUP = 1 << 1,
103} FilterOptions;
104
105typedef void (* ModifyListFunction) (GList **list, CajaFile *file);
106
107enum {
108 CHANGED,
109 UPDATED_DEEP_COUNT_IN_PROGRESS,
110 LAST_SIGNAL
111};
112
113static int date_format_pref;
114
115static guint signals[LAST_SIGNAL] = { 0 };
116
117static GHashTable *symbolic_links;
118
119static GQuark attribute_name_q,
120 attribute_size_q,
121 attribute_size_on_disk_q,
122 attribute_type_q,
123 attribute_creation_date_q,
124 attribute_date_created_q,
125 attribute_modification_date_q,
126 attribute_date_modified_q,
127 attribute_accessed_date_q,
128 attribute_date_accessed_q,
129 attribute_emblems_q,
130 attribute_extension_q,
131 attribute_mime_type_q,
132 attribute_size_detail_q,
133 attribute_size_on_disk_detail_q,
134 attribute_deep_size_q,
135 attribute_deep_size_on_disk_q,
136 attribute_deep_file_count_q,
137 attribute_deep_directory_count_q,
138 attribute_deep_total_count_q,
139 attribute_date_changed_q,
140 attribute_trashed_on_q,
141 attribute_trash_orig_path_q,
142 attribute_date_permissions_q,
143 attribute_permissions_q,
144 attribute_selinux_context_q,
145 attribute_octal_permissions_q,
146 attribute_owner_q,
147 attribute_group_q,
148 attribute_uri_q,
149 attribute_where_q,
150 attribute_link_target_q,
151 attribute_volume_q,
152 attribute_free_space_q;
153
154static void caja_file_info_iface_init (CajaFileInfoIface *iface);
155static char * caja_file_get_owner_as_string (CajaFile *file,
156 gboolean include_real_name);
157static char * caja_file_get_type_as_string (CajaFile *file);
158static gboolean update_info_and_name (CajaFile *file,
159 GFileInfo *info);
160static const char * caja_file_peek_display_name (CajaFile *file);
161static const char * caja_file_peek_display_name_collation_key (CajaFile *file);
162static void file_mount_unmounted (GMount *mount, gpointer data);
163static void metadata_hash_free (GHashTable *hash);
164
165G_DEFINE_TYPE_WITH_CODE (CajaFile, caja_file, G_TYPE_OBJECT,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
166 G_ADD_PRIVATE (CajaFile)static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
167 G_IMPLEMENT_INTERFACE (CAJA_TYPE_FILE_INFO,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
168 caja_file_info_iface_init))static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
169
170static void
171caja_file_init (CajaFile *file)
172{
173 file->details = caja_file_get_instance_private (file);
174
175 caja_file_clear_info (file);
176 caja_file_invalidate_extension_info_internal (file);
177}
178
179static GObject*
180caja_file_constructor (GType type,
181 guint n_construct_properties,
182 GObjectConstructParam *construct_params)
183{
184 GObject *object;
185 CajaFile *file;
186
187 object = (* G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->constructor) (type,
188 n_construct_properties,
189 construct_params);
190
191 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
192
193 /* Set to default type after full construction */
194 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type != G_FILE_TYPE_UNKNOWN) {
195 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
196 }
197
198 return object;
199}
200
201gboolean
202caja_file_set_display_name (CajaFile *file,
203 const char *display_name,
204 const char *edit_name,
205 gboolean custom)
206{
207 gboolean changed;
208
209 if (custom && display_name == NULL((void*)0)) {
210 /* We're re-setting a custom display name, invalidate it if
211 we already set it so that the old one is re-read */
212 if (file->details->got_custom_display_name) {
213 file->details->got_custom_display_name = FALSE(0);
214 caja_file_invalidate_attributes (file,
215 CAJA_FILE_ATTRIBUTE_INFO);
216 }
217 return FALSE(0);
218 }
219
220 if (display_name == NULL((void*)0) || *display_name == 0) {
221 return FALSE(0);
222 }
223
224 if (!custom && file->details->got_custom_display_name) {
225 return FALSE(0);
226 }
227
228 if (edit_name == NULL((void*)0)) {
229 edit_name = display_name;
230 }
231
232 changed = FALSE(0);
233
234 if (eel_strcmp (file->details->display_name, display_name) != 0) {
235 changed = TRUE(!(0));
236
237 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
238
239 if (eel_strcmp (file->details->name, display_name) == 0) {
240 file->details->display_name = g_ref_string_acquire (file->details->name);
241 } else {
242 file->details->display_name = g_ref_string_new (display_name);
243 }
244
245 g_free (file->details->display_name_collation_key);
246 file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
247 }
248
249 if (eel_strcmp (file->details->edit_name, edit_name) != 0) {
250 changed = TRUE(!(0));
251
252 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
253 if (eel_strcmp (file->details->display_name, edit_name) == 0) {
254 file->details->edit_name = g_ref_string_acquire (file->details->display_name);
255 } else {
256 file->details->edit_name = g_ref_string_new (edit_name);
257 }
258 }
259
260 file->details->got_custom_display_name = custom;
261 return changed;
262}
263
264static void
265caja_file_clear_display_name (CajaFile *file)
266{
267 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
268 file->details->display_name = NULL((void*)0);
269 g_free (file->details->display_name_collation_key);
270 file->details->display_name_collation_key = NULL((void*)0);
271 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
272 file->details->edit_name = NULL((void*)0);
273}
274
275static gboolean
276foreach_metadata_free (gpointer key,
277 gpointer value,
278 gpointer user_data)
279{
280 guint id;
281
282 id = GPOINTER_TO_UINT (key)((guint) (gulong) (key));
283
284 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
285 g_strfreev ((char **)value);
286 } else {
287 g_free ((char *)value);
288 }
289 return TRUE(!(0));
290}
291
292
293static void
294metadata_hash_free (GHashTable *hash)
295{
296 g_hash_table_foreach_remove (hash,
297 foreach_metadata_free,
298 NULL((void*)0));
299 g_hash_table_destroy (hash);
300}
301
302static gboolean
303metadata_hash_equal (GHashTable *hash1,
304 GHashTable *hash2)
305{
306 GHashTableIter iter;
307 gpointer key1, value1, value2;
308 guint id;
309
310 if (hash1 == NULL((void*)0) && hash2 == NULL((void*)0)) {
311 return TRUE(!(0));
312 }
313
314 if (hash1 == NULL((void*)0) || hash2 == NULL((void*)0)) {
315 return FALSE(0);
316 }
317
318 if (g_hash_table_size (hash1) !=
319 g_hash_table_size (hash2)) {
320 return FALSE(0);
321 }
322
323 g_hash_table_iter_init (&iter, hash1);
324 while (g_hash_table_iter_next (&iter, &key1, &value1)) {
325 value2 = g_hash_table_lookup (hash2, key1);
326 if (value2 == NULL((void*)0)) {
327 return FALSE(0);
328 }
329 id = GPOINTER_TO_UINT (key1)((guint) (gulong) (key1));
330 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
331 if (!eel_g_strv_equal ((char **)value1, (char **)value2)) {
332 return FALSE(0);
333 }
334 } else {
335 if (strcmp ((char *)value1, (char *)value2) != 0) {
336 return FALSE(0);
337 }
338 }
339 }
340
341 return TRUE(!(0));
342}
343
344static void
345clear_metadata (CajaFile *file)
346{
347 if (file->details->metadata) {
348 metadata_hash_free (file->details->metadata);
349 file->details->metadata = NULL((void*)0);
350 }
351}
352
353static GHashTable *
354get_metadata_from_info (GFileInfo *info)
355{
356 GHashTable *metadata;
357 char **attrs;
358 guint id;
359 int i;
360 GFileAttributeType type;
361 gpointer value;
362
363 attrs = g_file_info_list_attributes (info, "metadata");
364
365 metadata = g_hash_table_new (NULL((void*)0), NULL((void*)0));
366
367 for (i = 0; attrs[i] != NULL((void*)0); i++) {
368 id = caja_metadata_get_id (attrs[i] + strlen ("metadata::"));
369 if (id == 0) {
370 continue;
371 }
372
373 if (!g_file_info_get_attribute_data (info, attrs[i],
374 &type, &value, NULL((void*)0))) {
375 continue;
376 }
377
378 if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
379 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
380 g_strdup ((char *)value)g_strdup_inline ((char *)value));
381 } else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) {
382 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
383 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
384 g_strdupv ((char **)value));
385 }
386 }
387
388 g_strfreev (attrs);
389
390 return metadata;
391}
392
393gboolean
394caja_file_update_metadata_from_info (CajaFile *file,
395 GFileInfo *info)
396{
397 gboolean changed = FALSE(0);
398
399 if (g_file_info_has_namespace (info, "metadata")) {
400 GHashTable *metadata;
401
402 metadata = get_metadata_from_info (info);
403 if (!metadata_hash_equal (metadata,
404 file->details->metadata)) {
405 changed = TRUE(!(0));
406 clear_metadata (file);
407 file->details->metadata = metadata;
408 } else {
409 metadata_hash_free (metadata);
410 }
411 } else if (file->details->metadata) {
412 changed = TRUE(!(0));
413 clear_metadata (file);
414 }
415 return changed;
416}
417
418void
419caja_file_clear_info (CajaFile *file)
420{
421 file->details->got_file_info = FALSE(0);
422 if (file->details->get_info_error) {
423 g_error_free (file->details->get_info_error);
424 file->details->get_info_error = NULL((void*)0);
425 }
426 /* Reset to default type, which might be other than unknown for
427 special kinds of files like the desktop or a search directory */
428 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
429
430 if (!file->details->got_custom_display_name) {
431 caja_file_clear_display_name (file);
432 }
433
434 if (!file->details->got_custom_activation_uri &&
435 file->details->activation_uri != NULL((void*)0)) {
436 g_free (file->details->activation_uri);
437 file->details->activation_uri = NULL((void*)0);
438 }
439
440 if (file->details->icon != NULL((void*)0)) {
441 g_object_unref (file->details->icon);
442 file->details->icon = NULL((void*)0);
443 }
444
445 g_free (file->details->thumbnail_path);
446 file->details->thumbnail_path = NULL((void*)0);
447 file->details->thumbnailing_failed = FALSE(0);
448
449 file->details->is_launcher = FALSE(0);
450 file->details->is_foreign_link = FALSE(0);
451 file->details->is_trusted_link = FALSE(0);
452 file->details->is_symlink = FALSE(0);
453 file->details->is_hidden = FALSE(0);
454 file->details->is_backup = FALSE(0);
455 file->details->is_mountpoint = FALSE(0);
456 file->details->uid = -1;
457 file->details->gid = -1;
458 file->details->can_read = TRUE(!(0));
459 file->details->can_write = TRUE(!(0));
460 file->details->can_execute = TRUE(!(0));
461 file->details->can_delete = TRUE(!(0));
462 file->details->can_trash = TRUE(!(0));
463 file->details->can_rename = TRUE(!(0));
464 file->details->can_mount = FALSE(0);
465 file->details->can_unmount = FALSE(0);
466 file->details->can_eject = FALSE(0);
467 file->details->can_start = FALSE(0);
468 file->details->can_start_degraded = FALSE(0);
469 file->details->can_stop = FALSE(0);
470 file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
471 file->details->can_poll_for_media = FALSE(0);
472 file->details->is_media_check_automatic = FALSE(0);
473 file->details->has_permissions = FALSE(0);
474 file->details->permissions = 0;
475 file->details->size = -1;
476 file->details->size_on_disk = -1;
477 file->details->sort_order = 0;
478 file->details->mtime = 0;
479 file->details->atime = 0;
480 file->details->ctime = 0;
481 file->details->btime = 0;
482 file->details->trash_time = 0;
483 g_free (file->details->symlink_name);
484 file->details->symlink_name = NULL((void*)0);
485 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
486 file->details->mime_type = NULL((void*)0);
487 g_free (file->details->selinux_context);
488 file->details->selinux_context = NULL((void*)0);
489 g_free (file->details->description);
490 file->details->description = NULL((void*)0);
491 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
492 file->details->owner = NULL((void*)0);
493 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
494 file->details->owner_real = NULL((void*)0);
495 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
496 file->details->group = NULL((void*)0);
497
498 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
499 file->details->filesystem_id = NULL((void*)0);
500
501 clear_metadata (file);
502}
503
504static CajaFile *
505caja_file_new_from_filename (CajaDirectory *directory,
506 const char *filename,
507 gboolean self_owned)
508{
509 CajaFile *file;
510
511 g_assert (CAJA_IS_DIRECTORY (directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_284
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_284
= 1; else _g_boolean_var_284 = 0; _g_boolean_var_284; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 511, ((const char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"
); } while (0)
;
512 g_assert (filename != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_285
; if (filename != ((void*)0)) _g_boolean_var_285 = 1; else _g_boolean_var_285
= 0; _g_boolean_var_285; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 512, ((const char*) (__func__)
), "filename != NULL"); } while (0)
;
513 g_assert (filename[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_286
; if (filename[0] != '\0') _g_boolean_var_286 = 1; else _g_boolean_var_286
= 0; _g_boolean_var_286; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 513, ((const char*) (__func__)
), "filename[0] != '\\0'"); } while (0)
;
514
515 if (CAJA_IS_DESKTOP_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_desktop_directory_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; }
))))
) {
516 if (self_owned) {
517 file = CAJA_FILE (g_object_new (CAJA_TYPE_DESKTOP_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_desktop_directory_file_get_type
(), ((void*)0)))))))
;
518 } else {
519 /* This doesn't normally happen, unless the user somehow types in a uri
520 * that references a file like this. (See #349840) */
521 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
522 }
523 } else if (CAJA_IS_SEARCH_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_search_directory_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; }
))))
) {
524 if (self_owned) {
525 file = CAJA_FILE (g_object_new (CAJA_TYPE_SEARCH_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_search_directory_file_get_type
(), ((void*)0)))))))
;
526 } else {
527 /* This doesn't normally happen, unless the user somehow types in a uri
528 * that references a file like this. (See #349840) */
529 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
530 }
531 } else if (g_str_has_suffix (filename, CAJA_SAVED_SEARCH_EXTENSION)(__builtin_constant_p (".savedSearch")? __extension__ ({ const
char * const __str = (filename); const char * const __suffix
= (".savedSearch"); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_287; if (__str == ((void
*)0) || __suffix == ((void*)0)) _g_boolean_var_287 = 1; else _g_boolean_var_287
= 0; _g_boolean_var_287; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".savedSearch") )
) {
532 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
533 } else {
534 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
535 }
536
537 file->details->directory = caja_directory_ref (directory);
538
539 file->details->name = g_ref_string_new (filename);
540
541#ifdef CAJA_FILE_DEBUG_REF
542 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
543#endif
544
545 return file;
546}
547
548static void
549modify_link_hash_table (CajaFile *file,
550 ModifyListFunction modify_function)
551{
552 char *target_uri;
553 gboolean found;
554 gpointer original_key;
555 GList **list_ptr;
556
557 /* Check if there is a symlink name. If none, we are OK. */
558 if (file->details->symlink_name == NULL((void*)0) || !caja_file_is_symbolic_link (file)) {
559 return;
560 }
561
562 /* Create the hash table first time through. */
563 if (symbolic_links == NULL((void*)0)) {
564 symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
565 }
566
567 target_uri = caja_file_get_symbolic_link_target_uri (file);
568
569 /* Find the old contents of the hash table. */
570 found = g_hash_table_lookup_extended
571 (symbolic_links, target_uri,
572 &original_key, (gpointer *)&list_ptr);
573 if (!found) {
574 list_ptr = g_new0 (GList *, 1)(GList * *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (GList *); 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
; }))
;
575 original_key = g_strdup (target_uri)g_strdup_inline (target_uri);
576 g_hash_table_insert (symbolic_links, original_key, list_ptr);
577 }
578 (* modify_function) (list_ptr, file);
579 if (*list_ptr == NULL((void*)0)) {
580 g_hash_table_remove (symbolic_links, target_uri);
581 g_free (list_ptr);
582 g_free (original_key);
583 }
584 g_free (target_uri);
585}
586
587static void
588symbolic_link_weak_notify (gpointer data,
589 GObject *where_the_object_was)
590{
591 GList **list = data;
592 /* This really shouldn't happen, but we're seeing some strange things in
593 bug #358172 where the symlink hashtable isn't correctly updated. */
594 *list = g_list_remove (*list, where_the_object_was);
595}
596
597static void
598add_to_link_hash_table_list (GList **list, CajaFile *file)
599{
600 if (g_list_find (*list, file) != NULL((void*)0)) {
601 g_warning ("Adding file to symlink_table multiple times. "
602 "Please add feedback of what you were doing at https://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
603 return;
604 }
605 g_object_weak_ref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
606 *list = g_list_prepend (*list, file);
607}
608
609static void
610add_to_link_hash_table (CajaFile *file)
611{
612 modify_link_hash_table (file, add_to_link_hash_table_list);
613}
614
615static void
616remove_from_link_hash_table_list (GList **list, CajaFile *file)
617{
618 if (g_list_find (*list, file) != NULL((void*)0)) {
619 g_object_weak_unref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
620 *list = g_list_remove (*list, file);
621 }
622}
623
624static void
625remove_from_link_hash_table (CajaFile *file)
626{
627 modify_link_hash_table (file, remove_from_link_hash_table_list);
628}
629
630CajaFile *
631caja_file_new_from_info (CajaDirectory *directory,
632 GFileInfo *info)
633{
634 CajaFile *file;
635 const char *mime_type;
636
637 g_return_val_if_fail (CAJA_IS_DIRECTORY (directory), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_288
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_288
= 1; else _g_boolean_var_288 = 0; _g_boolean_var_288; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"); return
(((void*)0)); } } while (0)
;
638 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_289
; if (info != ((void*)0)) _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__)), "info != NULL"); return
(((void*)0)); } } while (0)
;
639
640 mime_type = g_file_info_get_content_type (info);
641 if (mime_type &&
642 strcmp (mime_type, CAJA_SAVED_SEARCH_MIMETYPE"application/x-mate-saved-search") == 0) {
643 g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
644 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
645 } else {
646 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
647 }
648
649 file->details->directory = caja_directory_ref (directory);
650
651 update_info_and_name (file, info);
652
653#ifdef CAJA_FILE_DEBUG_REF
654 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
655#endif
656
657 return file;
658}
659
660static CajaFile *
661caja_file_get_internal (GFile *location, gboolean create)
662{
663 gboolean self_owned;
664 CajaDirectory *directory;
665 CajaFile *file;
666 GFile *parent;
667 char *basename;
668
669 g_assert (location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_290
; if (location != ((void*)0)) _g_boolean_var_290 = 1; else _g_boolean_var_290
= 0; _g_boolean_var_290; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 669, ((const char*) (__func__)
), "location != NULL"); } while (0)
;
670
671 parent = g_file_get_parent (location);
672
673 self_owned = FALSE(0);
674 if (parent == NULL((void*)0)) {
675 self_owned = TRUE(!(0));
676 parent = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
677 }
678
679 /* Get object that represents the directory. */
680 directory = caja_directory_get_internal (parent, create);
681
682 g_object_unref (parent);
683
684 /* Get the name for the file. */
685 if (self_owned && directory != NULL((void*)0)) {
686 basename = caja_directory_get_name_for_self_as_new_file (directory);
687 } else {
688 basename = g_file_get_basename (location);
689 }
690 /* Check to see if it's a file that's already known. */
691 if (directory == NULL((void*)0)) {
692 file = NULL((void*)0);
693 } else if (self_owned) {
694 file = directory->details->as_file;
695 } else {
696 file = caja_directory_find_file_by_name (directory, basename);
697 }
698
699 /* Ref or create the file. */
700 if (file != NULL((void*)0)) {
701 caja_file_ref (file);
702 } else if (create && directory != NULL((void*)0)) {
703 file = caja_file_new_from_filename (directory, basename, self_owned);
704 if (self_owned) {
705 g_assert (directory->details->as_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_291
; if (directory->details->as_file == ((void*)0)) _g_boolean_var_291
= 1; else _g_boolean_var_291 = 0; _g_boolean_var_291; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 705, ((const char*) (__func__)), "directory->details->as_file == NULL"
); } while (0)
;
706 directory->details->as_file = file;
707 } else {
708 caja_directory_add_file (directory, file);
709 }
710 }
711
712 g_free (basename);
713 caja_directory_unref (directory);
714
715 return file;
716}
717
718CajaFile *
719caja_file_get (GFile *location)
720{
721 return caja_file_get_internal (location, TRUE(!(0)));
722}
723
724CajaFile *
725caja_file_get_existing (GFile *location)
726{
727 return caja_file_get_internal (location, FALSE(0));
728}
729
730CajaFile *
731caja_file_get_existing_by_uri (const char *uri)
732{
733 GFile *location;
734 CajaFile *file;
735
736 location = g_file_new_for_uri (uri);
737 file = caja_file_get_internal (location, FALSE(0));
738 g_object_unref (location);
739
740 return file;
741}
742
743CajaFile *
744caja_file_get_by_uri (const char *uri)
745{
746 GFile *location;
747 CajaFile *file;
748
749 location = g_file_new_for_uri (uri);
750 file = caja_file_get_internal (location, TRUE(!(0)));
751 g_object_unref (location);
752
753 return file;
754}
755
756gboolean
757caja_file_is_self_owned (CajaFile *file)
758{
759 return file->details->directory->details->as_file == file;
760}
761
762static void
763finalize (GObject *object)
764{
765 CajaDirectory *directory;
766 CajaFile *file;
767
768 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
769
770 g_assert (file->details->operations_in_progress == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_292
; if (file->details->operations_in_progress == ((void*)
0)) _g_boolean_var_292 = 1; else _g_boolean_var_292 = 0; _g_boolean_var_292
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 770, ((const char*) (__func__)), "file->details->operations_in_progress == NULL"
); } while (0)
;
771
772 if (file->details->is_thumbnailing) {
773 char *uri;
774
775 uri = caja_file_get_uri (file);
776 caja_thumbnail_remove_from_queue (uri);
777 g_free (uri);
778 }
779
780 caja_async_destroying_file (file);
781
782 remove_from_link_hash_table (file);
783
784 directory = file->details->directory;
785
786 if (caja_file_is_self_owned (file)) {
787 directory->details->as_file = NULL((void*)0);
788 } else {
789 if (!file->details->is_gone) {
790 caja_directory_remove_file (directory, file);
791 }
792 }
793
794 if (file->details->get_info_error) {
795 g_error_free (file->details->get_info_error);
796 }
797
798 caja_directory_unref (directory);
799 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
800 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
801 g_free (file->details->display_name_collation_key);
802 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
803 if (file->details->icon) {
804 g_object_unref (file->details->icon);
805 }
806 g_free (file->details->thumbnail_path);
807 g_free (file->details->symlink_name);
808 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
809 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
810 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
811 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
812 g_free (file->details->selinux_context);
813 g_free (file->details->description);
814 g_free (file->details->top_left_text);
815 g_free (file->details->custom_icon);
816 g_free (file->details->activation_uri);
817 g_free (file->details->compare_by_emblem_cache);
818
819 if (file->details->thumbnail) {
820 g_object_unref (file->details->thumbnail);
821 }
822 if (file->details->mount) {
823 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
824 g_object_unref (file->details->mount);
825 }
826
827 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
828
829 g_list_free_full (file->details->mime_list, g_free);
830 g_list_free_full (file->details->pending_extension_emblems, g_free);
831 g_list_free_full (file->details->extension_emblems, g_free);
832 g_list_free_full (file->details->pending_info_providers, g_object_unref);
833
834 if (file->details->pending_extension_attributes) {
835 g_hash_table_destroy (file->details->pending_extension_attributes);
836 }
837
838 if (file->details->extension_attributes) {
839 g_hash_table_destroy (file->details->extension_attributes);
840 }
841
842 if (file->details->metadata) {
843 metadata_hash_free (file->details->metadata);
844 }
845
846 G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->finalize (object);
847}
848
849CajaFile *
850caja_file_ref (CajaFile *file)
851{
852 if (file == NULL((void*)0)) {
853 return NULL((void*)0);
854 }
855 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_293
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_293
= 1; else _g_boolean_var_293 = 0; _g_boolean_var_293; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
856
857#ifdef CAJA_FILE_DEBUG_REF
858 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
859#endif
860
861 return g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
862}
863
864void
865caja_file_unref (CajaFile *file)
866{
867 if (file == NULL((void*)0)) {
868 return;
869 }
870
871 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_294
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_294
= 1; else _g_boolean_var_294 = 0; _g_boolean_var_294; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
872
873#ifdef CAJA_FILE_DEBUG_REF
874 DEBUG_REF_PRINTFprintf("%10p unref'd", file);
875#endif
876
877 g_object_unref (file);
878}
879
880/**
881 * caja_file_get_parent_uri_for_display:
882 *
883 * Get the uri for the parent directory.
884 *
885 * @file: The file in question.
886 *
887 * Return value: A string representing the parent's location,
888 * formatted for user display (including stripping "file://").
889 * If the parent is NULL, returns the empty string.
890 */
891char *
892caja_file_get_parent_uri_for_display (CajaFile *file)
893{
894 GFile *parent;
895 char *result;
896
897 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_295
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_295
= 1; else _g_boolean_var_295 = 0; _g_boolean_var_295; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 897, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
898
899 parent = caja_file_get_parent_location (file);
900 if (parent) {
901 result = g_file_get_parse_name (parent);
902 g_object_unref (parent);
903 } else {
904 result = g_strdup ("")g_strdup_inline ("");
905 }
906
907 return result;
908}
909
910/**
911 * caja_file_get_parent_uri:
912 *
913 * Get the uri for the parent directory.
914 *
915 * @file: The file in question.
916 *
917 * Return value: A string for the parent's location, in "raw URI" form.
918 * Use caja_file_get_parent_uri_for_display instead if the
919 * result is to be displayed on-screen.
920 * If the parent is NULL, returns the empty string.
921 */
922char *
923caja_file_get_parent_uri (CajaFile *file)
924{
925 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_296
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_296
= 1; else _g_boolean_var_296 = 0; _g_boolean_var_296; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 925, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
926
927 if (caja_file_is_self_owned (file)) {
928 /* Callers expect an empty string, not a NULL. */
929 return g_strdup ("")g_strdup_inline ("");
930 }
931
932 return caja_directory_get_uri (file->details->directory);
933}
934
935GFile *
936caja_file_get_parent_location (CajaFile *file)
937{
938 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_297
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_297
= 1; else _g_boolean_var_297 = 0; _g_boolean_var_297; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 938, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
939
940 if (caja_file_is_self_owned (file)) {
941 /* Callers expect an empty string, not a NULL. */
942 return NULL((void*)0);
943 }
944
945 return caja_directory_get_location (file->details->directory);
946}
947
948CajaFile *
949caja_file_get_parent (CajaFile *file)
950{
951 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_298
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_298
= 1; else _g_boolean_var_298 = 0; _g_boolean_var_298; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 951, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
952
953 if (caja_file_is_self_owned (file)) {
954 return NULL((void*)0);
955 }
956
957 return caja_directory_get_corresponding_file (file->details->directory);
958}
959
960/**
961 * caja_file_can_read:
962 *
963 * Check whether the user is allowed to read the contents of this file.
964 *
965 * @file: The file to check.
966 *
967 * Return value: FALSE if the user is definitely not allowed to read
968 * the contents of the file. If the user has read permission, or
969 * the code can't tell whether the user has read permission,
970 * returns TRUE (so failures must always be handled).
971 */
972gboolean
973caja_file_can_read (CajaFile *file)
974{
975 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_299
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_299
= 1; else _g_boolean_var_299 = 0; _g_boolean_var_299; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
976
977 return file->details->can_read;
978}
979
980/**
981 * caja_file_can_write:
982 *
983 * Check whether the user is allowed to write to this file.
984 *
985 * @file: The file to check.
986 *
987 * Return value: FALSE if the user is definitely not allowed to write
988 * to the file. If the user has write permission, or
989 * the code can't tell whether the user has write permission,
990 * returns TRUE (so failures must always be handled).
991 */
992gboolean
993caja_file_can_write (CajaFile *file)
994{
995 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_300
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_300
= 1; else _g_boolean_var_300 = 0; _g_boolean_var_300; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
996
997 return file->details->can_write;
998}
999
1000/**
1001 * caja_file_can_execute:
1002 *
1003 * Check whether the user is allowed to execute this file.
1004 *
1005 * @file: The file to check.
1006 *
1007 * Return value: FALSE if the user is definitely not allowed to execute
1008 * the file. If the user has execute permission, or
1009 * the code can't tell whether the user has execute permission,
1010 * returns TRUE (so failures must always be handled).
1011 */
1012gboolean
1013caja_file_can_execute (CajaFile *file)
1014{
1015 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_301
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_301
= 1; else _g_boolean_var_301 = 0; _g_boolean_var_301; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1016
1017 return file->details->can_execute;
1018}
1019
1020gboolean
1021caja_file_can_mount (CajaFile *file)
1022{
1023 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_302
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_302
= 1; else _g_boolean_var_302 = 0; _g_boolean_var_302; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1024
1025 return file->details->can_mount;
1026}
1027
1028gboolean
1029caja_file_can_unmount (CajaFile *file)
1030{
1031 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_303
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_303
= 1; else _g_boolean_var_303 = 0; _g_boolean_var_303; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1032
1033 return file->details->can_unmount ||
1034 (file->details->mount != NULL((void*)0) &&
1035 g_mount_can_unmount (file->details->mount));
1036}
1037
1038gboolean
1039caja_file_can_eject (CajaFile *file)
1040{
1041 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_304
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_304
= 1; else _g_boolean_var_304 = 0; _g_boolean_var_304; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1042
1043 return file->details->can_eject ||
1044 (file->details->mount != NULL((void*)0) &&
1045 g_mount_can_eject (file->details->mount));
1046}
1047
1048gboolean
1049caja_file_can_start (CajaFile *file)
1050{
1051 gboolean ret;
1052 GDrive *drive;
1053
1054 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_305
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_305
= 1; else _g_boolean_var_305 = 0; _g_boolean_var_305; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1055
1056 ret = FALSE(0);
1057
1058 if (file->details->can_start) {
1059 ret = TRUE(!(0));
1060 goto out;
1061 }
1062
1063 if (file->details->mount != NULL((void*)0)) {
1064 drive = g_mount_get_drive (file->details->mount);
1065 if (drive != NULL((void*)0)) {
1066 ret = g_drive_can_start (drive);
1067 g_object_unref (drive);
1068 }
1069 }
1070
1071 out:
1072 return ret;
1073}
1074
1075gboolean
1076caja_file_can_start_degraded (CajaFile *file)
1077{
1078 gboolean ret;
1079 GDrive *drive;
1080
1081 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_306
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_306
= 1; else _g_boolean_var_306 = 0; _g_boolean_var_306; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1082
1083 ret = FALSE(0);
1084
1085 if (file->details->can_start_degraded) {
1086 ret = TRUE(!(0));
1087 goto out;
1088 }
1089
1090 if (file->details->mount != NULL((void*)0)) {
1091 drive = g_mount_get_drive (file->details->mount);
1092 if (drive != NULL((void*)0)) {
1093 ret = g_drive_can_start_degraded (drive);
1094 g_object_unref (drive);
1095 }
1096 }
1097
1098 out:
1099 return ret;
1100}
1101
1102gboolean
1103caja_file_can_poll_for_media (CajaFile *file)
1104{
1105 gboolean ret;
1106 GDrive *drive;
1107
1108 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_307
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_307
= 1; else _g_boolean_var_307 = 0; _g_boolean_var_307; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1109
1110 ret = FALSE(0);
1111
1112 if (file->details->can_poll_for_media) {
1113 ret = TRUE(!(0));
1114 goto out;
1115 }
1116
1117 if (file->details->mount != NULL((void*)0)) {
1118 drive = g_mount_get_drive (file->details->mount);
1119 if (drive != NULL((void*)0)) {
1120 ret = g_drive_can_poll_for_media (drive);
1121 g_object_unref (drive);
1122 }
1123 }
1124
1125 out:
1126 return ret;
1127}
1128
1129gboolean
1130caja_file_is_media_check_automatic (CajaFile *file)
1131{
1132 gboolean ret;
1133 GDrive *drive;
1134
1135 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_308
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_308
= 1; else _g_boolean_var_308 = 0; _g_boolean_var_308; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1136
1137 ret = FALSE(0);
1138
1139 if (file->details->is_media_check_automatic) {
1140 ret = TRUE(!(0));
1141 goto out;
1142 }
1143
1144 if (file->details->mount != NULL((void*)0)) {
1145 drive = g_mount_get_drive (file->details->mount);
1146 if (drive != NULL((void*)0)) {
1147 ret = g_drive_is_media_check_automatic (drive);
1148 g_object_unref (drive);
1149 }
1150 }
1151
1152 out:
1153 return ret;
1154}
1155
1156
1157gboolean
1158caja_file_can_stop (CajaFile *file)
1159{
1160 gboolean ret;
1161 GDrive *drive;
1162
1163 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_309
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_309
= 1; else _g_boolean_var_309 = 0; _g_boolean_var_309; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1164
1165 ret = FALSE(0);
1166
1167 if (file->details->can_stop) {
1168 ret = TRUE(!(0));
1169 goto out;
1170 }
1171
1172 if (file->details->mount != NULL((void*)0)) {
1173 drive = g_mount_get_drive (file->details->mount);
1174 if (drive != NULL((void*)0)) {
1175 ret = g_drive_can_stop (drive);
1176 g_object_unref (drive);
1177 }
1178 }
1179
1180 out:
1181 return ret;
1182}
1183
1184GDriveStartStopType
1185caja_file_get_start_stop_type (CajaFile *file)
1186{
1187 GDriveStartStopType ret;
1188 GDrive *drive;
1189
1190 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_310
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_310
= 1; else _g_boolean_var_310 = 0; _g_boolean_var_310; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1191
1192 ret = G_DRIVE_START_STOP_TYPE_UNKNOWN;
1193
1194 ret = file->details->start_stop_type;
1195 if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1196 goto out;
1197
1198 if (file->details->mount != NULL((void*)0)) {
1199 drive = g_mount_get_drive (file->details->mount);
1200 if (drive != NULL((void*)0)) {
1201 ret = g_drive_get_start_stop_type (drive);
1202 g_object_unref (drive);
1203 }
1204 }
1205
1206 out:
1207 return ret;
1208}
1209
1210void
1211caja_file_mount (CajaFile *file,
1212 GMountOperation *mount_op,
1213 GCancellable *cancellable,
1214 CajaFileOperationCallback callback,
1215 gpointer callback_data)
1216{
1217 GError *error;
1218
1219 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount == NULL((void*)0)) {
1220 if (callback) {
1221 error = NULL((void*)0);
1222 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1223 _("This file cannot be mounted")dcgettext (((void*)0), "This file cannot be mounted", 5));
1224 callback (file, NULL((void*)0), error, callback_data);
1225 g_error_free (error);
1226 }
1227 } else {
1228 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount (file, mount_op, cancellable, callback, callback_data);
1229 }
1230}
1231
1232typedef struct {
1233 CajaFile *file;
1234 CajaFileOperationCallback callback;
1235 gpointer callback_data;
1236} UnmountData;
1237
1238static void
1239unmount_done (void *callback_data)
1240{
1241 UnmountData *data;
1242
1243 data = (UnmountData *)callback_data;
1244 if (data->callback) {
1245 data->callback (data->file, NULL((void*)0), NULL((void*)0), data->callback_data);
1246 }
1247 caja_file_unref (data->file);
1248 g_free (data);
1249}
1250
1251void
1252caja_file_unmount (CajaFile *file,
1253 GMountOperation *mount_op,
1254 GCancellable *cancellable,
1255 CajaFileOperationCallback callback,
1256 gpointer callback_data)
1257{
1258 GError *error;
1259 UnmountData *data;
1260
1261 if (file->details->can_unmount) {
1262 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount != NULL((void*)0)) {
1263 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount (file, mount_op, cancellable, callback, callback_data);
1264 } else {
1265 if (callback) {
1266 error = NULL((void*)0);
1267 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1268 _("This file cannot be unmounted")dcgettext (((void*)0), "This file cannot be unmounted", 5));
1269 callback (file, NULL((void*)0), error, callback_data);
1270 g_error_free (error);
1271 }
1272 }
1273 } else if (file->details->mount != NULL((void*)0) &&
1274 g_mount_can_unmount (file->details->mount)) {
1275 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1276 data->file = caja_file_ref (file);
1277 data->callback = callback;
1278 data->callback_data = callback_data;
1279 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, FALSE(0), TRUE(!(0)), unmount_done, data);
1280 } else if (callback) {
1281 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1282 }
1283}
1284
1285void
1286caja_file_eject (CajaFile *file,
1287 GMountOperation *mount_op,
1288 GCancellable *cancellable,
1289 CajaFileOperationCallback callback,
1290 gpointer callback_data)
1291{
1292 GError *error;
1293 UnmountData *data;
1294
1295 if (file->details->can_eject) {
1296 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject != NULL((void*)0)) {
1297 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject (file, mount_op, cancellable, callback, callback_data);
1298 } else {
1299 if (callback) {
1300 error = NULL((void*)0);
1301 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1302 _("This file cannot be ejected")dcgettext (((void*)0), "This file cannot be ejected", 5));
1303 callback (file, NULL((void*)0), error, callback_data);
1304 g_error_free (error);
1305 }
1306 }
1307 } else if (file->details->mount != NULL((void*)0) &&
1308 g_mount_can_eject (file->details->mount)) {
1309 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1310 data->file = caja_file_ref (file);
1311 data->callback = callback;
1312 data->callback_data = callback_data;
1313 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, TRUE(!(0)), TRUE(!(0)), unmount_done, data);
1314 } else if (callback) {
1315 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1316 }
1317}
1318
1319void
1320caja_file_start (CajaFile *file,
1321 GMountOperation *start_op,
1322 GCancellable *cancellable,
1323 CajaFileOperationCallback callback,
1324 gpointer callback_data)
1325{
1326 GError *error;
1327
1328 if ((file->details->can_start || file->details->can_start_degraded) &&
1329 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start != NULL((void*)0)) {
1330 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start (file, start_op, cancellable, callback, callback_data);
1331 } else {
1332 if (callback) {
1333 error = NULL((void*)0);
1334 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1335 _("This file cannot be started")dcgettext (((void*)0), "This file cannot be started", 5));
1336 callback (file, NULL((void*)0), error, callback_data);
1337 g_error_free (error);
1338 }
1339 }
1340}
1341
1342static void
1343file_stop_callback (GObject *source_object,
1344 GAsyncResult *res,
1345 gpointer callback_data)
1346{
1347 CajaFileOperation *op;
1348 gboolean stopped;
1349 GError *error;
1350
1351 op = callback_data;
1352
1353 error = NULL((void*)0);
1354 stopped = g_drive_stop_finish (G_DRIVE (source_object)((((GDrive*) (void *) ((source_object))))),
1355 res, &error);
1356
1357 if (!stopped &&
1358 error->domain == G_IO_ERRORg_io_error_quark() &&
1359 (error->code == G_IO_ERROR_FAILED_HANDLED ||
1360 error->code == G_IO_ERROR_CANCELLED)) {
1361 g_error_free (error);
1362 error = NULL((void*)0);
1363 }
1364
1365 caja_file_operation_complete (op, NULL((void*)0), error);
1366 if (error) {
1367 g_error_free (error);
1368 }
1369}
1370
1371void
1372caja_file_stop (CajaFile *file,
1373 GMountOperation *mount_op,
1374 GCancellable *cancellable,
1375 CajaFileOperationCallback callback,
1376 gpointer callback_data)
1377{
1378 GError *error;
1379
1380 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1381 if (file->details->can_stop) {
1382 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop (file, mount_op, cancellable, callback, callback_data);
1383 } else {
1384 if (callback) {
1385 error = NULL((void*)0);
1386 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1387 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1388 callback (file, NULL((void*)0), error, callback_data);
1389 g_error_free (error);
1390 }
1391 }
1392 } else {
1393 GDrive *drive;
1394
1395 drive = NULL((void*)0);
1396 if (file->details->mount != NULL((void*)0))
1397 drive = g_mount_get_drive (file->details->mount);
1398
1399 if (drive != NULL((void*)0) && g_drive_can_stop (drive)) {
1400 CajaFileOperation *op;
1401
1402 op = caja_file_operation_new (file, callback, callback_data);
1403 if (cancellable) {
1404 g_object_unref (op->cancellable);
1405 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
1406 }
1407
1408 g_drive_stop (drive,
1409 G_MOUNT_UNMOUNT_NONE,
1410 mount_op,
1411 op->cancellable,
1412 file_stop_callback,
1413 op);
1414 } else {
1415 if (callback) {
1416 error = NULL((void*)0);
1417 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1418 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1419 callback (file, NULL((void*)0), error, callback_data);
1420 g_error_free (error);
1421 }
1422 }
1423
1424 if (drive != NULL((void*)0)) {
1425 g_object_unref (drive);
1426 }
1427 }
1428}
1429
1430void
1431caja_file_poll_for_media (CajaFile *file)
1432{
1433 if (file->details->can_poll_for_media) {
1434 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1435 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->poll_for_media (file);
1436 }
1437 } else if (file->details->mount != NULL((void*)0)) {
1438 GDrive *drive;
1439 drive = g_mount_get_drive (file->details->mount);
1440 if (drive != NULL((void*)0)) {
1441 g_drive_poll_for_media (drive,
1442 NULL((void*)0), /* cancellable */
1443 NULL((void*)0), /* GAsyncReadyCallback */
1444 NULL((void*)0)); /* user_data */
1445 g_object_unref (drive);
1446 }
1447 }
1448}
1449
1450/**
1451 * caja_file_is_desktop_directory:
1452 *
1453 * Check whether this file is the desktop directory.
1454 *
1455 * @file: The file to check.
1456 *
1457 * Return value: TRUE if this is the physical desktop directory.
1458 */
1459gboolean
1460caja_file_is_desktop_directory (CajaFile *file)
1461{
1462 GFile *dir;
1463
1464 dir = file->details->directory->details->location;
1465
1466 if (dir == NULL((void*)0)) {
1467 return FALSE(0);
1468 }
1469
1470 return caja_is_desktop_directory_file (dir, file->details->name);
1471}
1472
1473static gboolean
1474is_desktop_file (CajaFile *file)
1475{
1476 return caja_file_is_mime_type (file, "application/x-desktop");
1477}
1478
1479static gboolean
1480can_rename_desktop_file (CajaFile *file)
1481{
1482 GFile *location;
1483 gboolean res;
1484
1485 location = caja_file_get_location (file);
1486 res = g_file_is_native (location);
1487 g_object_unref (location);
1488 return res;
1489}
1490
1491/**
1492 * caja_file_can_rename:
1493 *
1494 * Check whether the user is allowed to change the name of the file.
1495 *
1496 * @file: The file to check.
1497 *
1498 * Return value: FALSE if the user is definitely not allowed to change
1499 * the name of the file. If the user is allowed to change the name, or
1500 * the code can't tell whether the user is allowed to change the name,
1501 * returns TRUE (so rename failures must always be handled).
1502 */
1503gboolean
1504caja_file_can_rename (CajaFile *file)
1505{
1506 gboolean can_rename;
1507
1508 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_311
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_311
= 1; else _g_boolean_var_311 = 0; _g_boolean_var_311; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1509
1510 /* Nonexistent files can't be renamed. */
1511 if (caja_file_is_gone (file)) {
1512 return FALSE(0);
1513 }
1514
1515 /* Self-owned files can't be renamed */
1516 if (caja_file_is_self_owned (file)) {
1517 return FALSE(0);
1518 }
1519
1520 if ((is_desktop_file (file) && !can_rename_desktop_file (file)) ||
1521 caja_file_is_home (file)) {
1522 return FALSE(0);
1523 }
1524
1525 can_rename = TRUE(!(0));
1526
1527 /* Certain types of links can't be renamed */
1528 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1529 CajaDesktopLink *link;
1530
1531 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1532
1533 if (link != NULL((void*)0)) {
1534 can_rename = caja_desktop_link_can_rename (link);
1535 g_object_unref (link);
1536 }
1537 }
1538
1539 if (!can_rename) {
1540 return FALSE(0);
1541 }
1542
1543 return file->details->can_rename;
1544}
1545
1546gboolean
1547caja_file_can_delete (CajaFile *file)
1548{
1549 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_312
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_312
= 1; else _g_boolean_var_312 = 0; _g_boolean_var_312; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1550
1551 /* Nonexistent files can't be deleted. */
1552 if (caja_file_is_gone (file)) {
1553 return FALSE(0);
1554 }
1555
1556 /* Self-owned files can't be deleted */
1557 if (caja_file_is_self_owned (file)) {
1558 return FALSE(0);
1559 }
1560
1561 return file->details->can_delete;
1562}
1563
1564gboolean
1565caja_file_can_trash (CajaFile *file)
1566{
1567 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_313
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_313
= 1; else _g_boolean_var_313 = 0; _g_boolean_var_313; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1568
1569 /* Nonexistent files can't be deleted. */
1570 if (caja_file_is_gone (file)) {
1571 return FALSE(0);
1572 }
1573
1574 /* Self-owned files can't be deleted */
1575 if (caja_file_is_self_owned (file)) {
1576 return FALSE(0);
1577 }
1578
1579 return file->details->can_trash;
1580}
1581
1582GFile *
1583caja_file_get_location (CajaFile *file)
1584{
1585 GFile *dir;
1586
1587 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_314
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_314
= 1; else _g_boolean_var_314 = 0; _g_boolean_var_314; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1588
1589 dir = file->details->directory->details->location;
1590
1591 if (caja_file_is_self_owned (file)) {
1592 return g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir));
1593 }
1594
1595 return g_file_get_child (dir, file->details->name);
1596}
1597
1598/* Return the actual uri associated with the passed-in file. */
1599char *
1600caja_file_get_uri (CajaFile *file)
1601{
1602 char *uri;
1603 GFile *loc;
1604
1605 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_315
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_315
= 1; else _g_boolean_var_315 = 0; _g_boolean_var_315; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1606
1607 loc = caja_file_get_location (file);
1608 uri = g_file_get_uri (loc);
1609 g_object_unref (loc);
1610
1611 return uri;
1612}
1613
1614char *
1615caja_file_get_uri_scheme (CajaFile *file)
1616{
1617 GFile *loc;
1618 char *scheme;
1619
1620 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_316
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_316
= 1; else _g_boolean_var_316 = 0; _g_boolean_var_316; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1621
1622 if (file->details->directory == NULL((void*)0) ||
1623 file->details->directory->details->location == NULL((void*)0)) {
1624 return NULL((void*)0);
1625 }
1626
1627 loc = caja_directory_get_location (file->details->directory);
1628 scheme = g_file_get_uri_scheme (loc);
1629 g_object_unref (loc);
1630
1631 return scheme;
1632}
1633
1634CajaFileOperation *
1635caja_file_operation_new (CajaFile *file,
1636 CajaFileOperationCallback callback,
1637 gpointer callback_data)
1638{
1639 CajaFileOperation *op;
1640
1641 op = g_new0 (CajaFileOperation, 1)(CajaFileOperation *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (CajaFileOperation); 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; }))
;
1642 op->file = caja_file_ref (file);
1643 op->callback = callback;
1644 op->callback_data = callback_data;
1645 op->cancellable = g_cancellable_new ();
1646
1647 op->file->details->operations_in_progress = g_list_prepend
1648 (op->file->details->operations_in_progress, op);
1649
1650 return op;
1651}
1652
1653static void
1654caja_file_operation_remove (CajaFileOperation *op)
1655{
1656 op->file->details->operations_in_progress = g_list_remove
1657 (op->file->details->operations_in_progress, op);
1658}
1659
1660void
1661caja_file_operation_free (CajaFileOperation *op)
1662{
1663 caja_file_operation_remove (op);
1664 caja_file_unref (op->file);
1665 g_object_unref (op->cancellable);
1666 if (op->free_data) {
1667 op->free_data (op->data);
1668 }
1669 // Start UNDO-REDO
1670 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1671 op->undo_redo_data);
1672 // End UNDO-REDO
1673 g_free (op);
1674}
1675
1676void
1677caja_file_operation_complete (CajaFileOperation *op, GFile *result_file, GError *error)
1678{
1679 /* Claim that something changed even if the operation failed.
1680 * This makes it easier for some clients who see the "reverting"
1681 * as "changing back".
1682 */
1683 caja_file_operation_remove (op);
1684 caja_file_changed (op->file);
1685 if (op->callback) {
1686 (* op->callback) (op->file, result_file, error, op->callback_data);
1687 }
1688 caja_file_operation_free (op);
1689}
1690
1691void
1692caja_file_operation_cancel (CajaFileOperation *op)
1693{
1694 /* Cancel the operation if it's still in progress. */
1695 g_cancellable_cancel (op->cancellable);
1696}
1697
1698static void
1699rename_get_info_callback (GObject *source_object,
1700 GAsyncResult *res,
1701 gpointer callback_data)
1702{
1703 CajaFileOperation *op;
1704 GFileInfo *new_info;
1705 GError *error;
1706
1707 op = callback_data;
1708
1709 error = NULL((void*)0);
1710 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
1711 if (new_info != NULL((void*)0)) {
1712 CajaDirectory *directory;
1713 CajaFile *existing_file;
1714 char *old_name;
1715 char *old_uri;
1716 char *new_uri;
1717 const char *new_name;
1718
1719 directory = op->file->details->directory;
1720
1721 new_name = g_file_info_get_name (new_info);
1722
1723 /* If there was another file by the same name in this
1724 * directory, mark it gone.
1725 */
1726 existing_file = caja_directory_find_file_by_name (directory, new_name);
1727 if (existing_file != NULL((void*)0)) {
1728 caja_file_mark_gone (existing_file);
1729 caja_file_changed (existing_file);
1730 }
1731
1732 old_uri = caja_file_get_uri (op->file);
1733 old_name = g_strdup (op->file->details->name)g_strdup_inline (op->file->details->name);
1734
1735 update_info_and_name (op->file, new_info);
1736
1737 g_free (old_name);
1738
1739 new_uri = caja_file_get_uri (op->file);
1740 caja_directory_moved (old_uri, new_uri);
1741 g_free (new_uri);
1742 g_free (old_uri);
1743
1744 /* the rename could have affected the display name if e.g.
1745 * we're in a vfolder where the name comes from a desktop file
1746 * and a rename affects the contents of the desktop file.
1747 */
1748 if (op->file->details->got_custom_display_name) {
1749 caja_file_invalidate_attributes (op->file,
1750 CAJA_FILE_ATTRIBUTE_INFO |
1751 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1752 }
1753
1754 g_object_unref (new_info);
1755 }
1756 caja_file_operation_complete (op, NULL((void*)0), error);
1757 if (error) {
1758 g_error_free (error);
1759 }
1760}
1761
1762static void
1763rename_callback (GObject *source_object,
1764 GAsyncResult *res,
1765 gpointer callback_data)
1766{
1767 CajaFileOperation *op;
1768 GFile *new_file;
1769 GError *error;
1770
1771 op = callback_data;
1772
1773 error = NULL((void*)0);
1774 new_file = g_file_set_display_name_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
1775 res, &error);
1776
1777 if (new_file != NULL((void*)0)) {
1778 // Start UNDO-REDO
1779 caja_undostack_manager_data_set_rename_information(op->undo_redo_data, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), new_file);
1780 // End UNDO-REDO
1781 g_file_query_info_async (new_file,
1782 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
1783 0,
1784 G_PRIORITY_DEFAULT0,
1785 op->cancellable,
1786 rename_get_info_callback, op);
1787 } else {
1788 caja_file_operation_complete (op, NULL((void*)0), error);
1789 g_error_free (error);
1790 }
1791}
1792
1793static gboolean
1794name_is (CajaFile *file, const char *new_name)
1795{
1796 const char *old_name;
1797 old_name = file->details->name;
1798 return strcmp (new_name, old_name) == 0;
1799}
1800
1801void
1802caja_file_rename (CajaFile *file,
1803 const char *new_name,
1804 CajaFileOperationCallback callback,
1805 gpointer callback_data)
1806{
1807 CajaFileOperation *op;
1808 char *old_name;
1809 char *new_file_name;
1810 gboolean success, name_changed;
1811 gboolean is_renameable_desktop_file;
1812 GFile *location;
1813 GError *error;
1814
1815 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_317
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_317
= 1; else _g_boolean_var_317 = 0; _g_boolean_var_317; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
1816 g_return_if_fail (new_name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_318
; if (new_name != ((void*)0)) _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__)), "new_name != NULL"
); return; } } while (0)
;
1817 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_319
; if (callback != ((void*)0)) _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__)), "callback != NULL"
); return; } } while (0)
;
1818
1819 is_renameable_desktop_file =
1820 is_desktop_file (file) && can_rename_desktop_file (file);
1821
1822 /* Return an error for incoming names containing path separators.
1823 * But not for .desktop files as '/' are allowed for them */
1824 if (strstr (new_name, "/") != NULL((void*)0) && !is_renameable_desktop_file) {
1825 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
1826 _("Slashes are not allowed in filenames")dcgettext (((void*)0), "Slashes are not allowed in filenames"
, 5)
);
1827 (* callback) (file, NULL((void*)0), error, callback_data);
1828 g_error_free (error);
1829 return;
1830 }
1831
1832 /* Can't rename a file that's already gone.
1833 * We need to check this here because there may be a new
1834 * file with the same name.
1835 */
1836 if (caja_file_is_gone (file)) {
1837 /* Claim that something changed even if the rename
1838 * failed. This makes it easier for some clients who
1839 * see the "reverting" to the old name as "changing
1840 * back".
1841 */
1842 caja_file_changed (file);
1843 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_FOUND,
1844 _("File not found")dcgettext (((void*)0), "File not found", 5));
1845 (* callback) (file, NULL((void*)0), error, callback_data);
1846 g_error_free (error);
1847 return;
1848 }
1849
1850 /* Test the name-hasn't-changed case explicitly, for two reasons.
1851 * (1) rename returns an error if new & old are same.
1852 * (2) We don't want to send file-changed signal if nothing changed.
1853 */
1854 if (!CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
&&
1855 !is_renameable_desktop_file &&
1856 name_is (file, new_name)) {
1857 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1858 return;
1859 }
1860
1861 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1862 * case before this case.
1863 */
1864 if (caja_file_is_self_owned (file)) {
1865 /* Claim that something changed even if the rename
1866 * failed. This makes it easier for some clients who
1867 * see the "reverting" to the old name as "changing
1868 * back".
1869 */
1870 caja_file_changed (file);
1871 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1872 _("Toplevel files cannot be renamed")dcgettext (((void*)0), "Toplevel files cannot be renamed", 5));
1873
1874 (* callback) (file, NULL((void*)0), error, callback_data);
1875 g_error_free (error);
1876 return;
1877 }
1878
1879 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1880 CajaDesktopLink *link;
1881
1882 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1883 old_name = caja_file_get_display_name (file);
1884
1885 if ((old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0)) {
1886 success = TRUE(!(0));
1887 } else {
1888 success = (link != NULL((void*)0) && caja_desktop_link_rename (link, new_name));
1889 }
1890
1891 if (success) {
1892 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1893 } else {
1894 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1895 _("Unable to rename desktop icon")dcgettext (((void*)0), "Unable to rename desktop icon", 5));
1896 (* callback) (file, NULL((void*)0), error, callback_data);
1897 g_error_free (error);
1898 }
1899
1900 g_free (old_name);
1901 g_object_unref (link);
1902 return;
1903 }
1904
1905 if (is_renameable_desktop_file) {
1906 char *uri;
1907
1908 /* Don't actually change the name if the new name is the same.
1909 * This helps for the vfolder method where this can happen and
1910 * we want to minimize actual changes
1911 */
1912 uri = caja_file_get_uri (file);
1913 old_name = caja_link_local_get_text (uri);
1914 if (old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0) {
1915 success = TRUE(!(0));
1916 name_changed = FALSE(0);
1917 } else {
1918 success = caja_link_local_set_text (uri, new_name);
1919 name_changed = TRUE(!(0));
1920 }
1921 g_free (old_name);
1922 g_free (uri);
1923
1924 if (!success) {
1925 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1926 _("Unable to rename desktop file")dcgettext (((void*)0), "Unable to rename desktop file", 5));
1927 (* callback) (file, NULL((void*)0), error, callback_data);
1928 g_error_free (error);
1929 return;
1930 }
1931 if (!g_str_has_suffix(new_name, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (new_name); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_320; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_320 = 1; else _g_boolean_var_320
= 0; _g_boolean_var_320; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (new_name, ".desktop") )
)
1932 new_file_name = g_strdup_printf ("%s.desktop", new_name);
1933 else
1934 new_file_name = g_strdup_printf("%s", new_name);
1935 new_file_name = g_strdelimit (new_file_name, "/", '-');
1936
1937 if (name_is (file, new_file_name)) {
1938 if (name_changed) {
1939 caja_file_invalidate_attributes (file,
1940 CAJA_FILE_ATTRIBUTE_INFO |
1941 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1942 }
1943
1944 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1945 g_free (new_file_name);
1946 return;
1947 }
1948 } else {
1949 new_file_name = g_strdup (new_name)g_strdup_inline (new_name);
1950 }
1951
1952 /* Set up a renaming operation. */
1953 op = caja_file_operation_new (file, callback, callback_data);
1954 op->is_rename = TRUE(!(0));
1955
1956 /* Do the renaming. */
1957
1958 location = caja_file_get_location (file);
1959
1960 // Start UNDO-REDO
1961 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
1962 op->undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RENAME, 1);
1963 }
1964 // End UNDO-REDO
1965
1966 g_file_set_display_name_async (location,
1967 new_file_name,
1968 G_PRIORITY_DEFAULT0,
1969 op->cancellable,
1970 rename_callback,
1971 op);
1972 g_free (new_file_name);
1973 g_object_unref (location);
1974}
1975
1976gboolean
1977caja_file_rename_in_progress (CajaFile *file)
1978{
1979 GList *node;
1980 CajaFileOperation *op = NULL((void*)0);
1981
1982 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = node->next) {
1983 op = node->data;
1984 if (op->is_rename) {
1985 return TRUE(!(0));
1986 }
1987 }
1988 return FALSE(0);
1989}
1990
1991void
1992caja_file_cancel (CajaFile *file,
1993 CajaFileOperationCallback callback,
1994 gpointer callback_data)
1995{
1996 GList *node, *next;
1997 CajaFileOperation *op = NULL((void*)0);
1998
1999 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = next) {
2000 next = node->next;
2001 op = node->data;
2002
2003 g_assert (op->file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_321
; if (op->file == file) _g_boolean_var_321 = 1; else _g_boolean_var_321
= 0; _g_boolean_var_321; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2003, ((const char*) (__func__
)), "op->file == file"); } while (0)
;
2004 if (op->callback == callback && op->callback_data == callback_data) {
2005 caja_file_operation_cancel (op);
2006 }
2007 }
2008}
2009
2010gboolean
2011caja_file_matches_uri (CajaFile *file, const char *match_uri)
2012{
2013 GFile *match_file, *location;
2014 gboolean result;
2015
2016 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_322
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_322
= 1; else _g_boolean_var_322 = 0; _g_boolean_var_322; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2017 g_return_val_if_fail (match_uri != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_323
; if (match_uri != ((void*)0)) _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__)), "match_uri != NULL"
); return ((0)); } } while (0)
;
2018
2019 location = caja_file_get_location (file);
2020 match_file = g_file_new_for_uri (match_uri);
2021 result = g_file_equal (location, match_file);
2022 g_object_unref (location);
2023 g_object_unref (match_file);
2024
2025 return result;
2026}
2027
2028int
2029caja_file_compare_location (CajaFile *file_1,
2030 CajaFile *file_2)
2031{
2032 GFile *loc_a, *loc_b;
2033 gboolean res;
2034
2035 loc_a = caja_file_get_location (file_1);
2036 loc_b = caja_file_get_location (file_2);
2037
2038 res = !g_file_equal (loc_a, loc_b);
2039
2040 g_object_unref (loc_a);
2041 g_object_unref (loc_b);
2042
2043 return (gint) res;
2044}
2045
2046gboolean
2047caja_file_is_local (CajaFile *file)
2048{
2049 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_324
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_324
= 1; else _g_boolean_var_324 = 0; _g_boolean_var_324; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2050
2051 return caja_directory_is_local (file->details->directory);
2052}
2053
2054static void
2055update_link (CajaFile *link_file, CajaFile *target_file)
2056{
2057 g_assert (CAJA_IS_FILE (link_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_325
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((link_file)); GType __t = (caja_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_325
= 1; else _g_boolean_var_325 = 0; _g_boolean_var_325; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2057, ((const char*) (__func__)), "CAJA_IS_FILE (link_file)"
); } while (0)
;
2058 g_assert (CAJA_IS_FILE (target_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_326
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_file)); GType __t = (caja_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_326
= 1; else _g_boolean_var_326 = 0; _g_boolean_var_326; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2058, ((const char*) (__func__)), "CAJA_IS_FILE (target_file)"
); } while (0)
;
2059
2060 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
2061 * here then the hash table is a waste of time.
2062 */
2063}
2064
2065static GList *
2066get_link_files (CajaFile *target_file)
2067{
2068 GList **link_files;
2069
2070 if (symbolic_links == NULL((void*)0)) {
2071 link_files = NULL((void*)0);
2072 } else {
2073 char *uri;
2074
2075 uri = caja_file_get_uri (target_file);
2076 link_files = g_hash_table_lookup (symbolic_links, uri);
2077 g_free (uri);
2078 }
2079 if (link_files) {
2080 return caja_file_list_copy (*link_files);
2081 }
2082 return NULL((void*)0);
2083}
2084
2085static void
2086update_links_if_target (CajaFile *target_file)
2087{
2088 GList *link_files, *p;
2089
2090 link_files = get_link_files (target_file);
2091 for (p = link_files; p != NULL((void*)0); p = p->next) {
2092 update_link (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))), target_file);
2093 }
2094 caja_file_list_free (link_files);
2095}
2096
2097static gboolean
2098update_info_internal (CajaFile *file,
2099 GFileInfo *info,
2100 gboolean update_name)
2101{
2102 gboolean changed;
2103 gboolean is_symlink, is_hidden, is_backup, is_mountpoint;
2104 gboolean has_permissions;
2105 guint32 permissions;
2106 gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2107 gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2108 GDriveStartStopType start_stop_type;
2109 gboolean thumbnailing_failed;
2110 int uid, gid;
2111 goffset size;
2112 goffset size_on_disk;
2113 int sort_order;
2114 time_t atime, mtime, ctime, btime;
2115 time_t trash_time;
2116 const char * time_string;
2117 const char *symlink_name, *mime_type, *selinux_context, *thumbnail_path;
2118 GFileType file_type;
2119 GIcon *icon;
2120 const char *description;
2121 const char *filesystem_id;
2122 const char *trash_orig_path;
2123 const char *group, *owner, *owner_real;
2124 gboolean free_owner, free_group;
2125
2126 if (file->details->is_gone) {
2127 return FALSE(0);
2128 }
2129
2130 if (info == NULL((void*)0)) {
2131 caja_file_mark_gone (file);
2132 return TRUE(!(0));
2133 }
2134
2135 file->details->file_info_is_up_to_date = TRUE(!(0));
2136
2137 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2138 * point to the old name know that the file has been renamed.
2139 */
2140
2141 remove_from_link_hash_table (file);
2142
2143 changed = FALSE(0);
2144
2145 if (!file->details->got_file_info) {
2146 changed = TRUE(!(0));
2147 }
2148 file->details->got_file_info = TRUE(!(0));
2149
2150 changed |= caja_file_set_display_name (file,
2151 g_file_info_get_display_name (info),
2152 g_file_info_get_edit_name (info),
2153 FALSE(0));
2154
2155 file_type = g_file_info_get_file_type (info);
2156 if (file->details->type != file_type) {
2157 changed = TRUE(!(0));
2158 }
2159 file->details->type = file_type;
2160
2161 if (!file->details->got_custom_activation_uri) {
2162 const char *activation_uri;
2163
2164 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri");
2165 if (activation_uri == NULL((void*)0)) {
2166 if (file->details->activation_uri) {
2167 g_free (file->details->activation_uri);
2168 file->details->activation_uri = NULL((void*)0);
2169 changed = TRUE(!(0));
2170 }
2171 } else {
2172 char *old_activation_uri;
2173
2174 old_activation_uri = file->details->activation_uri;
2175 file->details->activation_uri = g_strdup (activation_uri)g_strdup_inline (activation_uri);
2176
2177 if (old_activation_uri) {
2178 if (strcmp (old_activation_uri,
2179 file->details->activation_uri) != 0) {
2180 changed = TRUE(!(0));
2181 }
2182 g_free (old_activation_uri);
2183 } else {
2184 changed = TRUE(!(0));
2185 }
2186 }
2187 }
2188
2189 is_symlink = g_file_info_get_is_symlink (info);
2190 if (file->details->is_symlink != is_symlink) {
2191 changed = TRUE(!(0));
2192 }
2193 file->details->is_symlink = is_symlink;
2194
2195 is_hidden = g_file_info_get_is_hidden (info);
2196 is_backup = g_file_info_get_is_backup (info);
2197 if (file->details->is_hidden != is_hidden ||
2198 file->details->is_backup != is_backup) {
2199 changed = TRUE(!(0));
2200 }
2201 file->details->is_hidden = is_hidden;
2202 file->details->is_backup = is_backup;
2203
2204 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT"unix::is-mountpoint");
2205 if (file->details->is_mountpoint != is_mountpoint) {
2206 changed = TRUE(!(0));
2207 }
2208 file->details->is_mountpoint = is_mountpoint;
2209
2210 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
2211 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");;
2212 if (file->details->has_permissions != has_permissions ||
2213 file->details->permissions != permissions) {
2214 changed = TRUE(!(0));
2215 }
2216 file->details->has_permissions = has_permissions;
2217 file->details->permissions = permissions;
2218
2219 /* We default to TRUE for this if we can't know */
2220 can_read = TRUE(!(0));
2221 can_write = TRUE(!(0));
2222 can_execute = TRUE(!(0));
2223 can_delete = TRUE(!(0));
2224 can_trash = TRUE(!(0));
2225 can_rename = TRUE(!(0));
2226 can_mount = FALSE(0);
2227 can_unmount = FALSE(0);
2228 can_eject = FALSE(0);
2229 can_start = FALSE(0);
2230 can_start_degraded = FALSE(0);
2231 can_stop = FALSE(0);
2232 can_poll_for_media = FALSE(0);
2233 is_media_check_automatic = FALSE(0);
2234 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2235 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read")) {
2236 can_read = g_file_info_get_attribute_boolean (info,
2237 G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read");
2238 }
2239 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write")) {
2240 can_write = g_file_info_get_attribute_boolean (info,
2241 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write");
2242 }
2243 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute")) {
2244 can_execute = g_file_info_get_attribute_boolean (info,
2245 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute");
2246 }
2247 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete")) {
2248 can_delete = g_file_info_get_attribute_boolean (info,
2249 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete");
2250 }
2251 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash")) {
2252 can_trash = g_file_info_get_attribute_boolean (info,
2253 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash");
2254 }
2255 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename")) {
2256 can_rename = g_file_info_get_attribute_boolean (info,
2257 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename");
2258 }
2259 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount")) {
2260 can_mount = g_file_info_get_attribute_boolean (info,
2261 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount");
2262 }
2263 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount")) {
2264 can_unmount = g_file_info_get_attribute_boolean (info,
2265 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount");
2266 }
2267 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject")) {
2268 can_eject = g_file_info_get_attribute_boolean (info,
2269 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject");
2270 }
2271 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start")) {
2272 can_start = g_file_info_get_attribute_boolean (info,
2273 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start");
2274 }
2275 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded")) {
2276 can_start_degraded = g_file_info_get_attribute_boolean (info,
2277 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded");
2278 }
2279 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop")) {
2280 can_stop = g_file_info_get_attribute_boolean (info,
2281 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop");
2282 }
2283 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type")) {
2284 start_stop_type = g_file_info_get_attribute_uint32 (info,
2285 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type");
2286 }
2287 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll")) {
2288 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2289 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll");
2290 }
2291 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic")) {
2292 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2293 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic");
2294 }
2295 if (file->details->can_read != can_read ||
2296 file->details->can_write != can_write ||
2297 file->details->can_execute != can_execute ||
2298 file->details->can_delete != can_delete ||
2299 file->details->can_trash != can_trash ||
2300 file->details->can_rename != can_rename ||
2301 file->details->can_mount != can_mount ||
2302 file->details->can_unmount != can_unmount ||
2303 file->details->can_eject != can_eject ||
2304 file->details->can_start != can_start ||
2305 file->details->can_start_degraded != can_start_degraded ||
2306 file->details->can_stop != can_stop ||
2307 file->details->start_stop_type != start_stop_type ||
2308 file->details->can_poll_for_media != can_poll_for_media ||
2309 file->details->is_media_check_automatic != is_media_check_automatic) {
2310 changed = TRUE(!(0));
2311 }
2312
2313 file->details->can_read = can_read;
2314 file->details->can_write = can_write;
2315 file->details->can_execute = can_execute;
2316 file->details->can_delete = can_delete;
2317 file->details->can_trash = can_trash;
2318 file->details->can_rename = can_rename;
2319 file->details->can_mount = can_mount;
2320 file->details->can_unmount = can_unmount;
2321 file->details->can_eject = can_eject;
2322 file->details->can_start = can_start;
2323 file->details->can_start_degraded = can_start_degraded;
2324 file->details->can_stop = can_stop;
2325 file->details->start_stop_type = start_stop_type;
2326 file->details->can_poll_for_media = can_poll_for_media;
2327 file->details->is_media_check_automatic = is_media_check_automatic;
2328
2329 free_owner = FALSE(0);
2330 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER"owner::user");
2331 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL"owner::user-real");
2332 free_group = FALSE(0);
2333 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
2334
2335 uid = -1;
2336 gid = -1;
2337 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid")) {
2338 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid");
2339 if (owner == NULL((void*)0)) {
2340 free_owner = TRUE(!(0));
2341 owner = g_strdup_printf ("%d", uid);
2342 }
2343 }
2344 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid")) {
2345 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid");
2346 if (group == NULL((void*)0)) {
2347 free_group = TRUE(!(0));
2348 group = g_strdup_printf ("%d", gid);
2349 }
2350 }
2351 if (file->details->uid != uid ||
2352 file->details->gid != gid) {
2353 changed = TRUE(!(0));
2354 }
2355 file->details->uid = uid;
2356 file->details->gid = gid;
2357
2358 if (eel_strcmp (file->details->owner, owner) != 0) {
2359 changed = TRUE(!(0));
2360 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2361 file->details->owner = g_ref_string_new_intern (owner);
2362 }
2363
2364 if (eel_strcmp (file->details->owner_real, owner_real) != 0) {
2365 changed = TRUE(!(0));
2366 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2367 file->details->owner_real = g_ref_string_new_intern (owner_real);
2368 }
2369
2370 if (eel_strcmp (file->details->group, group) != 0) {
2371 changed = TRUE(!(0));
2372 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2373 file->details->group = g_ref_string_new_intern (group);
2374 }
2375
2376 if (free_owner) {
2377 g_free ((char *)owner);
2378 }
2379 if (free_group) {
2380 g_free ((char *)group);
2381 }
2382
2383 size = -1;
2384 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size")) {
2385 size = g_file_info_get_size (info);
2386 }
2387 if (file->details->size != size) {
2388 changed = TRUE(!(0));
2389 }
2390 file->details->size = size;
2391
2392 size_on_disk = -1;
2393 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size")) {
2394 size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size");
2395 }
2396 if (file->details->size_on_disk != size_on_disk) {
2397 changed = TRUE(!(0));
2398 }
2399 file->details->size_on_disk = size_on_disk;
2400
2401 sort_order = g_file_info_get_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER"standard::sort-order");
2402 if (file->details->sort_order != sort_order) {
2403 changed = TRUE(!(0));
2404 }
2405 file->details->sort_order = sort_order;
2406
2407 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS"time::access");
2408 ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED"time::changed");
2409 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
2410 btime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED"time::created");
2411 if (file->details->atime != atime ||
2412 file->details->mtime != mtime ||
2413 file->details->ctime != ctime ||
2414 file->details->btime != btime) {
2415 if (file->details->thumbnail == NULL((void*)0)) {
2416 file->details->thumbnail_is_up_to_date = FALSE(0);
2417 }
2418
2419 changed = TRUE(!(0));
2420 }
2421 file->details->atime = atime;
2422 file->details->ctime = ctime;
2423 file->details->mtime = mtime;
2424 file->details->btime = btime;
2425
2426 if (file->details->thumbnail != NULL((void*)0) &&
2427 file->details->thumbnail_mtime != 0 &&
2428 file->details->thumbnail_mtime != mtime) {
2429 file->details->thumbnail_is_up_to_date = FALSE(0);
2430 changed = TRUE(!(0));
2431 }
2432
2433 icon = g_file_info_get_icon (info);
2434 if (!g_icon_equal (icon, file->details->icon)) {
2435 changed = TRUE(!(0));
2436
2437 if (file->details->icon) {
2438 g_object_unref (file->details->icon);
2439 }
2440 file->details->icon = g_object_ref (icon)((__typeof__ (icon)) (g_object_ref) (icon));
2441 }
2442
2443 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
2444 if (eel_strcmp (file->details->thumbnail_path, thumbnail_path) != 0) {
2445 changed = TRUE(!(0));
2446 g_free (file->details->thumbnail_path);
2447 file->details->thumbnail_path = g_strdup (thumbnail_path)g_strdup_inline (thumbnail_path);
2448 }
2449
2450 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED"thumbnail::failed");
2451 if (file->details->thumbnailing_failed != thumbnailing_failed) {
2452 changed = TRUE(!(0));
2453 file->details->thumbnailing_failed = thumbnailing_failed;
2454 }
2455
2456 symlink_name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET"standard::symlink-target");
2457
2458 if (eel_strcmp (file->details->symlink_name, symlink_name) != 0) {
2459 changed = TRUE(!(0));
2460 g_free (file->details->symlink_name);
2461 file->details->symlink_name = g_strdup (symlink_name)g_strdup_inline (symlink_name);
2462 }
2463
2464 mime_type = g_file_info_get_content_type (info);
2465 if (eel_strcmp (file->details->mime_type, mime_type) != 0) {
2466 changed = TRUE(!(0));
2467 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2468 file->details->mime_type = g_ref_string_new_intern (mime_type);
2469 }
2470
2471 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT"selinux::context");
2472 if (eel_strcmp (file->details->selinux_context, selinux_context) != 0) {
2473 changed = TRUE(!(0));
2474 g_free (file->details->selinux_context);
2475 file->details->selinux_context = g_strdup (selinux_context)g_strdup_inline (selinux_context);
2476 }
2477
2478 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION"standard::description");
2479 if (eel_strcmp (file->details->description, description) != 0) {
2480 changed = TRUE(!(0));
2481 g_free (file->details->description);
2482 file->details->description = g_strdup (description)g_strdup_inline (description);
2483 }
2484
2485 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
2486 if (eel_strcmp (file->details->filesystem_id, filesystem_id) != 0) {
2487 changed = TRUE(!(0));
2488 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
2489 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2490 }
2491
2492 trash_time = 0;
2493 time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"trash::deletion-date");
2494 if (time_string != NULL((void*)0)) {
2495#if GLIB_CHECK_VERSION(2,61,2)(2 > (2) || (2 == (2) && 80 > (61)) || (2 == (2
) && 80 == (61) && 3 >= (2)))
2496 GDateTime *dt;
2497 GTimeZone *tz;
2498 tz = g_time_zone_new_local ();
2499 dt = g_date_time_new_from_iso8601 (time_string, tz);
2500 if (dt) {
2501 trash_time = (time_t) g_date_time_to_unix (dt);
2502 g_date_time_unref (dt);
2503 }
2504 g_time_zone_unref (tz);
2505#else
2506 GTimeVal g_trash_time;
2507 g_time_val_from_iso8601 (time_string, &g_trash_time);
2508 trash_time = g_trash_time.tv_sec;
2509#endif
2510 }
2511 if (file->details->trash_time != trash_time) {
2512 changed = TRUE(!(0));
2513 file->details->trash_time = trash_time;
2514 }
2515
2516 trash_orig_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path");
2517 if (eel_strcmp (file->details->trash_orig_path, trash_orig_path) != 0) {
2518 changed = TRUE(!(0));
2519 g_free (file->details->trash_orig_path);
2520 file->details->trash_orig_path = g_strdup (trash_orig_path)g_strdup_inline (trash_orig_path);
2521 }
2522
2523 changed |=
2524 caja_file_update_metadata_from_info (file, info);
2525
2526 if (update_name) {
2527 const char *name;
2528
2529 name = g_file_info_get_name (info);
2530 if (file->details->name == NULL((void*)0) ||
2531 strcmp (file->details->name, name) != 0) {
2532 GList *node;
2533
2534 changed = TRUE(!(0));
2535
2536 node = caja_directory_begin_file_name_change
2537 (file->details->directory, file);
2538
2539 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2540 if (eel_strcmp (file->details->display_name, name) == 0) {
2541 file->details->name = g_ref_string_acquire (file->details->display_name);
2542 } else {
2543 file->details->name = g_ref_string_new (name);
2544 }
2545
2546 if (!file->details->got_custom_display_name &&
2547 g_file_info_get_display_name (info) == NULL((void*)0)) {
2548 /* If the file info's display name is NULL,
2549 * caja_file_set_display_name() did
2550 * not unset the display name.
2551 */
2552 caja_file_clear_display_name (file);
2553 }
2554
2555 caja_directory_end_file_name_change
2556 (file->details->directory, file, node);
2557 }
2558 }
2559
2560 if (changed) {
2561 add_to_link_hash_table (file);
2562
2563 update_links_if_target (file);
2564 }
2565
2566 return changed;
2567}
2568
2569static gboolean
2570update_info_and_name (CajaFile *file,
2571 GFileInfo *info)
2572{
2573 return update_info_internal (file, info, TRUE(!(0)));
2574}
2575
2576gboolean
2577caja_file_update_info (CajaFile *file,
2578 GFileInfo *info)
2579{
2580 return update_info_internal (file, info, FALSE(0));
2581}
2582
2583void
2584caja_file_refresh_info (CajaFile *file)
2585{
2586 GFile *gfile;
2587 GFileInfo *new_info;
2588
2589 gfile = caja_file_get_location (file);
2590 new_info = g_file_query_info (gfile, CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
2591 G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
2592 if (new_info != NULL((void*)0)) {
2593 if (caja_file_update_info (file, new_info)) {
2594 caja_file_changed (file);
2595 }
2596 g_object_unref (new_info);
2597 }
2598 g_object_unref (gfile);
2599}
2600
2601static gboolean
2602update_name_internal (CajaFile *file,
2603 const char *name,
2604 gboolean in_directory)
2605{
2606 GList *node;
2607
2608 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_327
; if (name != ((void*)0)) _g_boolean_var_327 = 1; else _g_boolean_var_327
= 0; _g_boolean_var_327; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2608, ((const char*) (__func__
)), "name != NULL"); } while (0)
;
2609
2610 if (file->details->is_gone) {
2611 return FALSE(0);
2612 }
2613
2614 if (name_is (file, name)) {
2615 return FALSE(0);
2616 }
2617
2618 node = NULL((void*)0);
2619 if (in_directory) {
2620 node = caja_directory_begin_file_name_change
2621 (file->details->directory, file);
2622 }
2623
2624 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2625 file->details->name = g_ref_string_new (name);
2626
2627 if (!file->details->got_custom_display_name) {
2628 caja_file_clear_display_name (file);
2629 }
2630
2631 if (in_directory) {
2632 caja_directory_end_file_name_change
2633 (file->details->directory, file, node);
2634 }
2635
2636 return TRUE(!(0));
2637}
2638
2639gboolean
2640caja_file_update_name (CajaFile *file, const char *name)
2641{
2642 gboolean ret;
2643
2644 ret = update_name_internal (file, name, TRUE(!(0)));
2645
2646 if (ret) {
2647 update_links_if_target (file);
2648 }
2649
2650 return ret;
2651}
2652
2653gboolean
2654caja_file_update_name_and_directory (CajaFile *file,
2655 const char *name,
2656 CajaDirectory *new_directory)
2657{
2658 CajaDirectory *old_directory;
2659 FileMonitors *monitors;
2660
2661 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_328
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_328
= 1; else _g_boolean_var_328 = 0; _g_boolean_var_328; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2662 g_return_val_if_fail (CAJA_IS_DIRECTORY (file->details->directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_329
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file->details->directory)); GType __t = (caja_directory_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_329 = 1; else _g_boolean_var_329 =
0; _g_boolean_var_329; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_DIRECTORY (file->details->directory)"
); return ((0)); } } while (0)
;
2663 g_return_val_if_fail (!file->details->is_gone, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_330
; if (!file->details->is_gone) _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__
)), "!file->details->is_gone"); return ((0)); } } while
(0)
;
2664 g_return_val_if_fail (!caja_file_is_self_owned (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_331
; if (!caja_file_is_self_owned (file)) _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__)), "!caja_file_is_self_owned (file)"); return ((
0)); } } while (0)
;
2665 g_return_val_if_fail (CAJA_IS_DIRECTORY (new_directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_332
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_directory)); GType __t = (caja_directory_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__)), "CAJA_IS_DIRECTORY (new_directory)"
); return ((0)); } } while (0)
;
2666
2667 old_directory = file->details->directory;
2668 if (old_directory == new_directory) {
2669 if (name) {
2670 return update_name_internal (file, name, TRUE(!(0)));
2671 } else {
2672 return FALSE(0);
2673 }
2674 }
2675
2676 caja_file_ref (file);
2677
2678 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2679 * point to the old name know that the file has been moved.
2680 */
2681
2682 remove_from_link_hash_table (file);
2683
2684 monitors = caja_directory_remove_file_monitors (old_directory, file);
2685 caja_directory_remove_file (old_directory, file);
2686
2687 file->details->directory = caja_directory_ref (new_directory);
2688 caja_directory_unref (old_directory);
2689
2690 if (name) {
2691 update_name_internal (file, name, FALSE(0));
2692 }
2693
2694 caja_directory_add_file (new_directory, file);
2695 caja_directory_add_file_monitors (new_directory, file, monitors);
2696
2697 add_to_link_hash_table (file);
2698
2699 update_links_if_target (file);
2700
2701 caja_file_unref (file);
2702
2703 return TRUE(!(0));
2704}
2705
2706void
2707caja_file_set_directory (CajaFile *file,
2708 CajaDirectory *new_directory)
2709{
2710 caja_file_update_name_and_directory (file, NULL((void*)0), new_directory);
2711}
2712
2713static Knowledge
2714get_item_count (CajaFile *file,
2715 guint *count)
2716{
2717 gboolean known, unreadable;
2718
2719 known = caja_file_get_directory_item_count
2720 (file, count, &unreadable);
2721 if (!known) {
2722 return UNKNOWN;
2723 }
2724 if (unreadable) {
2725 return UNKNOWABLE;
2726 }
2727 return KNOWN;
2728}
2729
2730static Knowledge
2731get_size (CajaFile *file,
2732 goffset *size,
2733 gboolean size_on_disk)
2734{
2735 /* If we tried and failed, then treat it like there is no size
2736 * to know.
2737 */
2738 if (file->details->get_info_failed) {
2739 return UNKNOWABLE;
2740 }
2741
2742 /* If the info is NULL that means we haven't even tried yet,
2743 * so it's just unknown, not unknowable.
2744 */
2745 if (!file->details->got_file_info) {
2746 return UNKNOWN;
2747 }
2748
2749 /* If we got info with no size in it, it means there is no
2750 * such thing as a size as far as mate-vfs is concerned,
2751 * so "unknowable".
2752 */
2753 if (size_on_disk && file->details->size_on_disk == -1) {
2754 return UNKNOWABLE;
2755 }
2756
2757 if (!size_on_disk && file->details->size == -1) {
2758 return UNKNOWABLE;
2759 }
2760
2761 /* We have a size! */
2762 if (size_on_disk) {
2763 *size = file->details->size_on_disk;
2764 } else {
2765 *size = file->details->size;
2766 }
2767
2768 return KNOWN;
2769}
2770
2771static Knowledge
2772get_time (CajaFile *file,
2773 time_t *time_out,
2774 CajaDateType type)
2775{
2776 time_t time;
2777
2778 /* If we tried and failed, then treat it like there is no size
2779 * to know.
2780 */
2781 if (file->details->get_info_failed) {
2782 return UNKNOWABLE;
2783 }
2784
2785 /* If the info is NULL that means we haven't even tried yet,
2786 * so it's just unknown, not unknowable.
2787 */
2788 if (!file->details->got_file_info) {
2789 return UNKNOWN;
2790 }
2791
2792 time = 0;
Value stored to 'time' is never read
2793 switch (type) {
2794 case CAJA_DATE_TYPE_MODIFIED:
2795 time = file->details->mtime;
2796 break;
2797 case CAJA_DATE_TYPE_ACCESSED:
2798 time = file->details->atime;
2799 break;
2800 case CAJA_DATE_TYPE_CREATED:
2801 time = file->details->btime;
2802 break;
2803 case CAJA_DATE_TYPE_TRASHED:
2804 time = file->details->trash_time;
2805 break;
2806 default:
2807 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file.c", 2807
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2808 break;
2809 }
2810
2811 *time_out = time;
2812
2813 /* If we got info with no modification time in it, it means
2814 * there is no such thing as a modification time as far as
2815 * mate-vfs is concerned, so "unknowable".
2816 */
2817 if (time == 0) {
2818 return UNKNOWABLE;
2819 }
2820 return KNOWN;
2821}
2822
2823static int
2824compare_directories_by_count (CajaFile *file_1, CajaFile *file_2)
2825{
2826 /* Sort order:
2827 * Directories with unknown # of items
2828 * Directories with "unknowable" # of items
2829 * Directories with 0 items
2830 * Directories with n items
2831 */
2832
2833 Knowledge count_known_1, count_known_2;
2834 guint count_1, count_2;
2835
2836 count_known_1 = get_item_count (file_1, &count_1);
2837 count_known_2 = get_item_count (file_2, &count_2);
2838
2839 if (count_known_1 > count_known_2) {
2840 return -1;
2841 }
2842 if (count_known_1 < count_known_2) {
2843 return +1;
2844 }
2845
2846 /* count_known_1 and count_known_2 are equal now. Check if count
2847 * details are UNKNOWABLE or UNKNOWN.
2848 */
2849 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2850 return 0;
2851 }
2852
2853 if (count_1 < count_2) {
2854 return -1;
2855 }
2856 if (count_1 > count_2) {
2857 return +1;
2858 }
2859
2860 return 0;
2861}
2862
2863static int
2864compare_files_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2865{
2866 /* Sort order:
2867 * Files with unknown size.
2868 * Files with "unknowable" size.
2869 * Files with smaller sizes.
2870 * Files with large sizes.
2871 */
2872
2873 Knowledge size_known_1, size_known_2;
2874 goffset size_1 = 0, size_2 = 0;
2875
2876 size_known_1 = get_size (file_1, &size_1, size_on_disk);
2877 size_known_2 = get_size (file_2, &size_2, size_on_disk);
2878
2879 if (size_known_1 > size_known_2) {
2880 return -1;
2881 }
2882 if (size_known_1 < size_known_2) {
2883 return +1;
2884 }
2885
2886 /* size_known_1 and size_known_2 are equal now. Check if size
2887 * details are UNKNOWABLE or UNKNOWN
2888 */
2889 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2890 return 0;
2891 }
2892
2893 if (size_1 < size_2) {
2894 return -1;
2895 }
2896 if (size_1 > size_2) {
2897 return +1;
2898 }
2899
2900 return 0;
2901}
2902
2903static int
2904compare_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2905{
2906 /* Sort order:
2907 * Directories with n items
2908 * Directories with 0 items
2909 * Directories with "unknowable" # of items
2910 * Directories with unknown # of items
2911 * Files with large sizes.
2912 * Files with smaller sizes.
2913 * Files with "unknowable" size.
2914 * Files with unknown size.
2915 */
2916
2917 gboolean is_directory_1, is_directory_2;
2918
2919 is_directory_1 = caja_file_is_directory (file_1);
2920 is_directory_2 = caja_file_is_directory (file_2);
2921
2922 if (is_directory_1 && !is_directory_2) {
2923 return -1;
2924 }
2925 if (is_directory_2 && !is_directory_1) {
2926 return +1;
2927 }
2928
2929 if (is_directory_1) {
2930 return compare_directories_by_count (file_1, file_2);
2931 } else {
2932 return compare_files_by_size (file_1, file_2, size_on_disk);
2933 }
2934}
2935
2936static int
2937compare_by_display_name (CajaFile *file_1, CajaFile *file_2)
2938{
2939 const char *name_1, *name_2;
2940 const char *key_1, *key_2;
2941 gboolean sort_last_1, sort_last_2;
2942 int compare;
2943
2944 name_1 = caja_file_peek_display_name (file_1);
2945 name_2 = caja_file_peek_display_name (file_2);
2946
2947 sort_last_1 = name_1[0] == SORT_LAST_CHAR1'.' || name_1[0] == SORT_LAST_CHAR2'#';
2948 sort_last_2 = name_2[0] == SORT_LAST_CHAR1'.' || name_2[0] == SORT_LAST_CHAR2'#';
2949
2950 if (sort_last_1 && !sort_last_2) {
2951 compare = +1;
2952 } else if (!sort_last_1 && sort_last_2) {
2953 compare = -1;
2954 } else {
2955 key_1 = caja_file_peek_display_name_collation_key (file_1);
2956 key_2 = caja_file_peek_display_name_collation_key (file_2);
2957 compare = strcmp (key_1, key_2);
2958 }
2959
2960 return compare;
2961}
2962
2963static int
2964compare_by_directory_name (CajaFile *file_1, CajaFile *file_2)
2965{
2966 char *directory_1, *directory_2;
2967 int compare;
2968
2969 if (file_1->details->directory == file_2->details->directory) {
2970 return 0;
2971 }
2972
2973 directory_1 = caja_file_get_parent_uri_for_display (file_1);
2974 directory_2 = caja_file_get_parent_uri_for_display (file_2);
2975
2976 compare = g_utf8_collate (directory_1, directory_2);
2977
2978 g_free (directory_1);
2979 g_free (directory_2);
2980
2981 return compare;
2982}
2983
2984static gboolean
2985file_has_note (CajaFile *file)
2986{
2987 char *note;
2988 gboolean res;
2989
2990 note = caja_file_get_metadata (file, CAJA_METADATA_KEY_ANNOTATION"annotation", NULL((void*)0));
2991 res = note != NULL((void*)0) && note[0] != 0;
2992 g_free (note);
2993
2994 return res;
2995}
2996
2997static GList *
2998prepend_automatic_keywords (CajaFile *file,
2999 GList *names)
3000{
3001 /* Prepend in reverse order. */
3002 CajaFile *parent;
3003
3004 parent = caja_file_get_parent (file);
3005
3006#ifdef TRASH_IS_FAST_ENOUGH
3007 if (caja_file_is_in_trash (file)) {
3008 names = g_list_prepend
3009 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash"));
3010 }
3011#endif
3012 if (file_has_note (file)) {
3013 names = g_list_prepend
3014 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_NOTE)g_strdup_inline ("note"));
3015 }
3016
3017 /* Trash files are assumed to be read-only,
3018 * so we want to ignore them here. */
3019 if (!caja_file_can_write (file) &&
3020 !caja_file_is_in_trash (file) &&
3021 (parent == NULL((void*)0) || caja_file_can_write (parent))) {
3022 names = g_list_prepend
3023 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite"));
3024 }
3025 if (!caja_file_can_read (file)) {
3026 names = g_list_prepend
3027 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_READ)g_strdup_inline ("noread"));
3028 }
3029 if (caja_file_is_symbolic_link (file)) {
3030 names = g_list_prepend
3031 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_SYMBOLIC_LINK)g_strdup_inline ("symbolic-link"));
3032 }
3033
3034 if (parent) {
3035 caja_file_unref (parent);
3036 }
3037
3038
3039 return names;
3040}
3041
3042static void
3043fill_emblem_cache_if_needed (CajaFile *file)
3044{
3045 GList *node, *keywords;
3046 char *scanner;
3047 size_t length;
3048
3049 if (file->details->compare_by_emblem_cache != NULL((void*)0)) {
3050 /* Got a cache already. */
3051 return;
3052 }
3053
3054 keywords = caja_file_get_keywords (file);
3055
3056 /* Add up the keyword string lengths */
3057 length = 1;
3058 for (node = keywords; node != NULL((void*)0); node = node->next) {
3059 length += strlen ((const char *) node->data) + 1;
3060 }
3061
3062 /* Now that we know how large the cache struct needs to be, allocate it. */
3063 file->details->compare_by_emblem_cache = g_malloc (sizeof(CajaFileSortByEmblemCache) + length);
3064
3065 /* Copy them into the cache. */
3066 scanner = file->details->compare_by_emblem_cache->emblem_keywords;
3067 for (node = keywords; node != NULL((void*)0); node = node->next) {
3068 length = strlen ((const char *) node->data) + 1;
3069 memcpy (scanner, (const char *) node->data, length);
3070 scanner += length;
3071 }
3072
3073 /* Zero-terminate so we can tell where the list ends. */
3074 *scanner = 0;
3075
3076 g_list_free_full (keywords, g_free);
3077}
3078
3079static int
3080compare_by_emblems (CajaFile *file_1, CajaFile *file_2)
3081{
3082 const char *keyword_cache_1, *keyword_cache_2;
3083 int compare_result;
3084
3085 fill_emblem_cache_if_needed (file_1);
3086 fill_emblem_cache_if_needed (file_2);
3087
3088 /* We ignore automatic emblems, and only sort by user-added keywords. */
3089 compare_result = 0;
3090 keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords;
3091 keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords;
3092 for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) {
3093 size_t length;
3094
3095 compare_result = g_utf8_collate (keyword_cache_1, keyword_cache_2);
3096 if (compare_result != 0) {
3097 return compare_result;
3098 }
3099
3100 /* Advance to the next keyword */
3101 length = strlen (keyword_cache_1);
3102 keyword_cache_1 += length + 1;
3103 keyword_cache_2 += length + 1;
3104 }
3105
3106
3107 /* One or both is now NULL. */
3108 if (*keyword_cache_1 != '\0') {
3109 g_assert (*keyword_cache_2 == '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_333
; if (*keyword_cache_2 == '\0') _g_boolean_var_333 = 1; else _g_boolean_var_333
= 0; _g_boolean_var_333; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3109, ((const char*) (__func__
)), "*keyword_cache_2 == '\\0'"); } while (0)
;
3110 return -1;
3111 } else if (*keyword_cache_2 != '\0') {
3112 return +1;
3113 }
3114
3115 return 0;
3116}
3117
3118static int
3119compare_by_type (CajaFile *file_1, CajaFile *file_2)
3120{
3121 gboolean is_directory_1;
3122 gboolean is_directory_2;
3123 char *type_string_1;
3124 char *type_string_2;
3125 int result;
3126
3127 /* Directories go first. Then, if mime types are identical,
3128 * don't bother getting strings (for speed). This assumes
3129 * that the string is dependent entirely on the mime type,
3130 * which is true now but might not be later.
3131 */
3132 is_directory_1 = caja_file_is_directory (file_1);
3133 is_directory_2 = caja_file_is_directory (file_2);
3134
3135 if (is_directory_1 && is_directory_2) {
3136 return 0;
3137 }
3138
3139 if (is_directory_1) {
3140 return -1;
3141 }
3142
3143 if (is_directory_2) {
3144 return +1;
3145 }
3146
3147 if (file_1->details->mime_type != NULL((void*)0) &&
3148 file_2->details->mime_type != NULL((void*)0) &&
3149 strcmp (file_1->details->mime_type,
3150 file_2->details->mime_type) == 0) {
3151 return 0;
3152 }
3153
3154 type_string_1 = caja_file_get_type_as_string (file_1);
3155 type_string_2 = caja_file_get_type_as_string (file_2);
3156
3157 result = g_utf8_collate (type_string_1, type_string_2);
3158
3159 g_free (type_string_1);
3160 g_free (type_string_2);
3161
3162 return result;
3163}
3164
3165static int
3166compare_by_time (CajaFile *file_1, CajaFile *file_2, CajaDateType type)
3167{
3168 /* Sort order:
3169 * Files with unknown times.
3170 * Files with "unknowable" times.
3171 * Files with older times.
3172 * Files with newer times.
3173 */
3174
3175 Knowledge time_known_1, time_known_2;
3176 time_t time_1, time_2;
3177
3178 time_1 = 0;
3179 time_2 = 0;
3180
3181 time_known_1 = get_time (file_1, &time_1, type);
3182 time_known_2 = get_time (file_2, &time_2, type);
3183
3184 if (time_known_1 > time_known_2) {
3185 return -1;
3186 }
3187 if (time_known_1 < time_known_2) {
3188 return +1;
3189 }
3190
3191 /* Now time_known_1 is equal to time_known_2. Check whether
3192 * we failed to get modification times for files
3193 */
3194 if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3195 return 0;
3196 }
3197
3198 if (time_1 < time_2) {
3199 return -1;
3200 }
3201 if (time_1 > time_2) {
3202 return +1;
3203 }
3204
3205 return 0;
3206}
3207
3208static int
3209compare_by_full_path (CajaFile *file_1, CajaFile *file_2)
3210{
3211 int compare;
3212
3213 compare = compare_by_directory_name (file_1, file_2);
3214 if (compare != 0) {
3215 return compare;
3216 }
3217 return compare_by_display_name (file_1, file_2);
3218}
3219
3220/* prev_extension_segment:
3221 * @basename The basename of a file
3222 * @rem_chars A pointer to the amount of remaining characters
3223 *
3224 * Finds the next segment delimiter to the left. A starting character of '.' is
3225 * set to '\0'.
3226 *
3227 * Return value: The start of the previous segment (right of the dot) or
3228 * basename if there are none remaining.
3229 */
3230static char *
3231prev_extension_segment (char *basename, int *rem_chars)
3232{
3233 if (*basename == '.') {
3234 *basename = 0;
3235 basename--;
3236 (*rem_chars)--;
3237 }
3238
3239 while (*rem_chars > 0 && *basename != '.') {
3240 (*rem_chars)--;
3241 basename--;
3242 }
3243
3244 return basename + 1;
3245}
3246
3247/* is_valid_extension_segment:
3248 * @segment Part of a modifiable zero-terminated string
3249 * @segment_index The index of the current segment
3250 *
3251 * Uses a heuristic to identify valid file extensions.
3252 *
3253 * Return value: Whether the segment is part of the file extension.
3254 */
3255static gboolean
3256is_valid_extension_segment (const char *segment, int segment_index)
3257{
3258 gboolean result;
3259 gboolean has_letters;
3260 int char_offset;
3261 switch (segment_index) {
3262 case 0:
3263 /* extremely long segments are probably not part of the extension */
3264 result = strlen (segment) < 20;
3265 break;
3266 default:
3267 has_letters = FALSE(0);
3268 char_offset = 0;
3269 while (TRUE(!(0))) {
3270 char c;
3271
3272 c = *(segment + char_offset);
3273 if (c == '\0') {
3274 result = has_letters;
3275 break;
3276 }
3277 /* allow digits if there are also letters */
3278 else if (isalpha (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha
)
) {
3279 has_letters = TRUE(!(0));
3280 }
3281 /* fail if it is neither digit nor letter */
3282 else if (!isdigit (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
) {
3283 result = FALSE(0);
3284 break;
3285 }
3286
3287 if (char_offset >= SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3) {
3288 result = FALSE(0);
3289 break;
3290 }
3291 char_offset++;
3292 }
3293 }
3294 return result;
3295}
3296
3297static int
3298compare_by_extension_segments (CajaFile *file_1, CajaFile *file_2)
3299{
3300 char *name_1, *name_2;
3301 char *segment_1, *segment_2;
3302 int compare;
3303 int rem_chars_1, rem_chars_2;
3304 gboolean done_1, done_2;
3305 gboolean is_directory_1, is_directory_2;
3306 int segment_index;
3307
3308
3309 /* Directories do not have an extension */
3310 is_directory_1 = caja_file_is_directory (file_1);
3311 is_directory_2 = caja_file_is_directory (file_2);
3312
3313 if (is_directory_1 && is_directory_2) {
3314 return 0;
3315 } else if (is_directory_1) {
3316 return -1;
3317 } else if (is_directory_2) {
3318 return 1;
3319 }
3320
3321 name_1 = caja_file_get_display_name (file_1);
3322 name_2 = caja_file_get_display_name (file_2);
3323 rem_chars_1 = strlen (name_1);
3324 rem_chars_2 = strlen (name_2);
3325
3326 /* Point to one after the zero character */
3327 segment_1 = name_1 + rem_chars_1 + 1;
3328 segment_2 = name_2 + rem_chars_2 + 1;
3329
3330 segment_index = 0;
3331 do {
3332 segment_1 = prev_extension_segment (segment_1 - 1, &rem_chars_1);
3333 segment_2 = prev_extension_segment (segment_2 - 1, &rem_chars_2);
3334
3335 done_1 = rem_chars_1 <= 0 || !is_valid_extension_segment (segment_1, segment_index);
3336 done_2 = rem_chars_2 <= 0 || !is_valid_extension_segment (segment_2, segment_index);
3337 if (done_1 && !done_2) {
3338 compare = -1;
3339 break;
3340 }
3341 else if (!done_1 && done_2) {
3342 compare = 1;
3343 break;
3344 }
3345 else if (done_1 && done_2) {
3346 compare = 0;
3347 break;
3348 }
3349
3350 segment_index++;
3351 if (segment_index > SORT_BY_EXTENSION_MAX_SEGMENTS3 - 1) {
3352 break;
3353 }
3354 compare = strcmp (segment_1, segment_2);
3355 } while (compare == 0);
3356
3357 g_free (name_1);
3358 g_free (name_2);
3359
3360 return compare;
3361}
3362
3363static gchar *
3364caja_file_get_extension_as_string (CajaFile *file)
3365{
3366 int rem_chars;
3367 char *segment;
3368
3369 if (!caja_file_is_directory (file)) {
3370 char *name;
3371
3372 name = caja_file_get_display_name (file);
3373 rem_chars = strlen (name);
3374 segment = prev_extension_segment (name + rem_chars, &rem_chars);
3375
3376 if (rem_chars > 0 && is_valid_extension_segment (segment, 0)) {
3377 int segment_index;
3378 char *right_segment;
3379 char *result;
3380
3381 segment_index = 1;
3382 do {
3383 right_segment = segment;
3384 segment = prev_extension_segment (segment - 1, &rem_chars);
3385 if (rem_chars > 0 && is_valid_extension_segment (segment, segment_index)) {
3386 /* remove zero-termination of segment */
3387 *(right_segment - 1) = '.';
3388 }
3389 else {
3390 break;
3391 }
3392
3393 segment_index++;
3394 } while (segment_index < SORT_BY_EXTENSION_MAX_SEGMENTS3 + 1);
3395 result = g_strdup (right_segment)g_strdup_inline (right_segment);
3396 g_free (name);
3397 return result;
3398 }
3399 g_free (name);
3400 }
3401 return g_strdup ("")g_strdup_inline ("");
3402}
3403
3404static int
3405caja_file_compare_for_sort_internal (CajaFile *file_1,
3406 CajaFile *file_2,
3407 gboolean directories_first,
3408 gboolean reversed)
3409{
3410 gboolean is_directory_1, is_directory_2;
3411
3412 if (directories_first) {
3413 is_directory_1 = caja_file_is_directory (file_1);
3414 is_directory_2 = caja_file_is_directory (file_2);
3415
3416 if (is_directory_1 && !is_directory_2) {
3417 return -1;
3418 }
3419
3420 if (is_directory_2 && !is_directory_1) {
3421 return +1;
3422 }
3423 }
3424
3425 if (file_1->details->sort_order < file_2->details->sort_order) {
3426 return reversed ? 1 : -1;
3427 } else if (file_1->details->sort_order > file_2->details->sort_order) {
3428 return reversed ? -1 : 1;
3429 }
3430
3431 return 0;
3432}
3433
3434/**
3435 * caja_file_compare_for_sort:
3436 * @file_1: A file object
3437 * @file_2: Another file object
3438 * @sort_type: Sort criterion
3439 * @directories_first: Put all directories before any non-directories
3440 * @reversed: Reverse the order of the items, except that
3441 * the directories_first flag is still respected.
3442 *
3443 * Return value: int < 0 if @file_1 should come before file_2 in a
3444 * sorted list; int > 0 if @file_2 should come before file_1 in a
3445 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3446 * that each named sort type may actually break ties several ways, with the name
3447 * of the sort criterion being the primary but not only differentiator.
3448 **/
3449int
3450caja_file_compare_for_sort (CajaFile *file_1,
3451 CajaFile *file_2,
3452 CajaFileSortType sort_type,
3453 gboolean directories_first,
3454 gboolean reversed)
3455{
3456 int result;
3457
3458 if (file_1 == file_2) {
3459 return 0;
3460 }
3461
3462 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3463
3464 if (result == 0) {
3465 switch (sort_type) {
3466 case CAJA_FILE_SORT_BY_DISPLAY_NAME:
3467 result = compare_by_display_name (file_1, file_2);
3468 if (result == 0) {
3469 result = compare_by_directory_name (file_1, file_2);
3470 }
3471 break;
3472 case CAJA_FILE_SORT_BY_DIRECTORY:
3473 result = compare_by_full_path (file_1, file_2);
3474 break;
3475 case CAJA_FILE_SORT_BY_SIZE:
3476 /* Compare directory sizes ourselves, then if necessary
3477 * use MateVFS to compare file sizes.
3478 */
3479 result = compare_by_size (file_1, file_2, FALSE(0));
3480 if (result == 0) {
3481 result = compare_by_full_path (file_1, file_2);
3482 }
3483 break;
3484 case CAJA_FILE_SORT_BY_SIZE_ON_DISK:
3485 /* Compare directory sizes ourselves, then if necessary
3486 * use MateVFS to compare file sizes.
3487 */
3488 result = compare_by_size (file_1, file_2, TRUE(!(0)));
3489 if (result == 0) {
3490 result = compare_by_full_path (file_1, file_2);
3491 }
3492 break;
3493 case CAJA_FILE_SORT_BY_TYPE:
3494 /* MateVFS doesn't know about our special text for certain
3495 * mime types, so we handle the mime-type sorting ourselves.
3496 */
3497 result = compare_by_type (file_1, file_2);
3498 if (result == 0) {
3499 result = compare_by_full_path (file_1, file_2);
3500 }
3501 break;
3502 case CAJA_FILE_SORT_BY_MTIME:
3503 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_MODIFIED);
3504 if (result == 0) {
3505 result = compare_by_full_path (file_1, file_2);
3506 }
3507 break;
3508 case CAJA_FILE_SORT_BY_BTIME:
3509 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_CREATED);
3510 if (result == 0) {
3511 result = compare_by_full_path (file_1, file_2);
3512 }
3513 break;
3514 case CAJA_FILE_SORT_BY_ATIME:
3515 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_ACCESSED);
3516 if (result == 0) {
3517 result = compare_by_full_path (file_1, file_2);
3518 }
3519 break;
3520 case CAJA_FILE_SORT_BY_TRASHED_TIME:
3521 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_TRASHED);
3522 if (result == 0) {
3523 result = compare_by_full_path (file_1, file_2);
3524 }
3525 break;
3526 case CAJA_FILE_SORT_BY_EMBLEMS:
3527 /* MateVFS doesn't know squat about our emblems, so
3528 * we handle comparing them here, before falling back
3529 * to tie-breakers.
3530 */
3531 result = compare_by_emblems (file_1, file_2);
3532 if (result == 0) {
3533 result = compare_by_full_path (file_1, file_2);
3534 }
3535 break;
3536 case CAJA_FILE_SORT_BY_EXTENSION:
3537 result = compare_by_extension_segments (file_1, file_2);
3538 if (result == 0) {
3539 result = compare_by_full_path (file_1, file_2);
3540 }
3541 break;
3542 default:
3543 g_return_val_if_reached (0)do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "caja-file.c", 3543, ((const char*) (__func__))); return (0
); } while (0)
;
3544 }
3545
3546 if (reversed) {
3547 result = -result;
3548 }
3549 }
3550
3551 return result;
3552}
3553
3554int
3555caja_file_compare_for_sort_by_attribute_q (CajaFile *file_1,
3556 CajaFile *file_2,
3557 GQuark attribute,
3558 gboolean directories_first,
3559 gboolean reversed)
3560{
3561 int result;
3562
3563 if (file_1 == file_2) {
3564 return 0;
3565 }
3566
3567 /* Convert certain attributes into CajaFileSortTypes and use
3568 * caja_file_compare_for_sort()
3569 */
3570 if (attribute == 0 || attribute == attribute_name_q) {
3571 return caja_file_compare_for_sort (file_1, file_2,
3572 CAJA_FILE_SORT_BY_DISPLAY_NAME,
3573 directories_first,
3574 reversed);
3575 } else if (attribute == attribute_size_q) {
3576 return caja_file_compare_for_sort (file_1, file_2,
3577 CAJA_FILE_SORT_BY_SIZE,
3578 directories_first,
3579 reversed);
3580 } else if (attribute == attribute_size_on_disk_q) {
3581 return caja_file_compare_for_sort (file_1, file_2,
3582 CAJA_FILE_SORT_BY_SIZE_ON_DISK,
3583 directories_first,
3584 reversed);
3585 } else if (attribute == attribute_type_q) {
3586 return caja_file_compare_for_sort (file_1, file_2,
3587 CAJA_FILE_SORT_BY_TYPE,
3588 directories_first,
3589 reversed);
3590 } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q) {
3591 return caja_file_compare_for_sort (file_1, file_2,
3592 CAJA_FILE_SORT_BY_MTIME,
3593 directories_first,
3594 reversed);
3595 } else if (attribute == attribute_creation_date_q || attribute == attribute_date_created_q) {
3596 return caja_file_compare_for_sort (file_1, file_2,
3597 CAJA_FILE_SORT_BY_BTIME,
3598 directories_first,
3599 reversed);
3600 } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q) {
3601 return caja_file_compare_for_sort (file_1, file_2,
3602 CAJA_FILE_SORT_BY_ATIME,
3603 directories_first,
3604 reversed);
3605 } else if (attribute == attribute_trashed_on_q) {
3606 return caja_file_compare_for_sort (file_1, file_2,
3607 CAJA_FILE_SORT_BY_TRASHED_TIME,
3608 directories_first,
3609 reversed);
3610 } else if (attribute == attribute_emblems_q) {
3611 return caja_file_compare_for_sort (file_1, file_2,
3612 CAJA_FILE_SORT_BY_EMBLEMS,
3613 directories_first,
3614 reversed);
3615 } else if (attribute == attribute_extension_q) {
3616 return caja_file_compare_for_sort (file_1, file_2,
3617 CAJA_FILE_SORT_BY_EXTENSION,
3618 directories_first,
3619 reversed);
3620 }
3621
3622 /* it is a normal attribute, compare by strings */
3623
3624 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3625
3626 if (result == 0) {
3627 char *value_1;
3628 char *value_2;
3629
3630 value_1 = caja_file_get_string_attribute_q (file_1,
3631 attribute);
3632 value_2 = caja_file_get_string_attribute_q (file_2,
3633 attribute);
3634
3635 if (value_1 != NULL((void*)0) && value_2 != NULL((void*)0)) {
3636 result = strcmp (value_1, value_2);
3637 }
3638
3639 g_free (value_1);
3640 g_free (value_2);
3641
3642 if (reversed) {
3643 result = -result;
3644 }
3645 }
3646
3647 return result;
3648}
3649
3650int
3651caja_file_compare_for_sort_by_attribute (CajaFile *file_1,
3652 CajaFile *file_2,
3653 const char *attribute,
3654 gboolean directories_first,
3655 gboolean reversed)
3656{
3657 return caja_file_compare_for_sort_by_attribute_q (file_1, file_2,
3658 g_quark_from_string (attribute),
3659 directories_first,
3660 reversed);
3661}
3662
3663
3664/**
3665 * caja_file_compare_name:
3666 * @file: A file object
3667 * @pattern: A string we are comparing it with
3668 *
3669 * Return value: result of a comparison of the file name and the given pattern,
3670 * using the same sorting order as sort by name.
3671 **/
3672int
3673caja_file_compare_display_name (CajaFile *file,
3674 const char *pattern)
3675{
3676 const char *name;
3677 int result;
3678
3679 g_return_val_if_fail (pattern != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_334
; if (pattern != ((void*)0)) _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__)), "pattern != NULL"
); return (-1); } } while (0)
;
3680
3681 name = caja_file_peek_display_name (file);
3682 result = g_utf8_collate (name, pattern);
3683 return result;
3684}
3685
3686
3687gboolean
3688caja_file_is_hidden_file (CajaFile *file)
3689{
3690 return file->details->is_hidden;
3691}
3692
3693static gboolean
3694caja_file_is_backup_file (CajaFile *file)
3695{
3696 return file->details->is_backup;
3697}
3698
3699/**
3700 * caja_file_should_show:
3701 * @file: the file to check.
3702 * @show_hidden: whether we want to show hidden files or not.
3703 * @show_backup: whether we want to show backup files or not.
3704 *
3705 * Determines if a #CajaFile should be shown. Note that when browsing
3706 * a trash directory, this function will always return %TRUE.
3707 *
3708 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3709 */
3710gboolean
3711caja_file_should_show (CajaFile *file,
3712 gboolean show_hidden,
3713 gboolean show_foreign,
3714 gboolean show_backup)
3715{
3716 /* Never hide any files in trash. */
3717 if (caja_file_is_in_trash (file)) {
3718 return TRUE(!(0));
3719 } else {
3720 return (show_hidden || !caja_file_is_hidden_file (file)) &&
3721 (show_backup || !caja_file_is_backup_file (file)) &&
3722 (show_foreign || !(caja_file_is_in_desktop (file) && caja_file_is_foreign_link (file)));
3723 }
3724}
3725
3726gboolean
3727caja_file_is_home (CajaFile *file)
3728{
3729 GFile *dir;
3730
3731 dir = file->details->directory->details->location;
3732 if (dir == NULL((void*)0)) {
3733 return FALSE(0);
3734 }
3735
3736 return caja_is_home_directory_file (dir, file->details->name);
3737}
3738
3739gboolean
3740caja_file_is_in_desktop (CajaFile *file)
3741{
3742 if (file->details->directory->details->location) {
3743 return caja_is_desktop_directory (file->details->directory->details->location);
3744 }
3745 return FALSE(0);
3746
3747}
3748
3749static gboolean
3750filter_hidden_partition_callback (gpointer data,
3751 gpointer callback_data)
3752{
3753 CajaFile *file;
3754 FilterOptions options;
3755
3756 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
3757 options = GPOINTER_TO_INT (callback_data)((gint) (glong) (callback_data));
3758
3759 return caja_file_should_show (file,
3760 options & SHOW_HIDDEN,
3761 TRUE(!(0)),
3762 options & SHOW_BACKUP);
3763}
3764
3765GList *
3766caja_file_list_filter_hidden (GList *files,
3767 gboolean show_hidden)
3768{
3769 GList *filtered_files;
3770 GList *removed_files;
3771
3772 /* FIXME bugzilla.gnome.org 40653:
3773 * Eventually this should become a generic filtering thingy.
3774 */
3775
3776 filtered_files = caja_file_list_copy (files);
3777 filtered_files = eel_g_list_partition (filtered_files,
3778 filter_hidden_partition_callback,
3779 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0))((gpointer) (glong) ((show_hidden ? SHOW_HIDDEN : 0))),
3780 &removed_files);
3781 caja_file_list_free (removed_files);
3782
3783 return filtered_files;
3784}
3785
3786char *
3787caja_file_get_metadata (CajaFile *file,
3788 const char *key,
3789 const char *default_metadata)
3790{
3791 guint id;
3792 char *value;
3793
3794 g_return_val_if_fail (key != NULL, g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_335
; if (key != ((void*)0)) _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__)), "key != NULL"); return
(g_strdup_inline (default_metadata)); } } while (0)
;
3795 g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_336
; if (key[0] != '\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__)), "key[0] != '\\0'"
); return (g_strdup_inline (default_metadata)); } } while (0)
;
3796
3797 if (file == NULL((void*)0) ||
3798 file->details->metadata == NULL((void*)0)) {
3799 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3800 }
3801
3802 g_return_val_if_fail (CAJA_IS_FILE (file), g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_337
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_337
= 1; else _g_boolean_var_337 = 0; _g_boolean_var_337; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (g_strdup_inline
(default_metadata)); } } while (0)
;
3803
3804 id = caja_metadata_get_id (key);
3805 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3806
3807 if (value) {
3808 return g_strdup (value)g_strdup_inline (value);
3809 }
3810 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3811}
3812
3813GList *
3814caja_file_get_metadata_list (CajaFile *file,
3815 const char *key)
3816{
3817 guint id;
3818 char **value;
3819
3820 g_return_val_if_fail (key != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_338
; if (key != ((void*)0)) _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__)), "key != NULL"); return
(((void*)0)); } } while (0)
;
3821 g_return_val_if_fail (key[0] != '\0', NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_339
; if (key[0] != '\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__)), "key[0] != '\\0'"
); return (((void*)0)); } } while (0)
;
3822
3823 if (file == NULL((void*)0) ||
3824 file->details->metadata == NULL((void*)0)) {
3825 return NULL((void*)0);
3826 }
3827
3828 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_340
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_340
= 1; else _g_boolean_var_340 = 0; _g_boolean_var_340; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
3829
3830 id = caja_metadata_get_id (key);
3831 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
3832
3833 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3834
3835 if (value) {
3836 GList *res;
3837 int i;
3838
3839 res = NULL((void*)0);
3840 for (i = 0; value[i] != NULL((void*)0); i++) {
3841 res = g_list_prepend (res, g_strdup (value[i])g_strdup_inline (value[i]));
3842 }
3843 return g_list_reverse (res);
3844 }
3845
3846 return NULL((void*)0);
3847}
3848
3849void
3850caja_file_set_metadata (CajaFile *file,
3851 const char *key,
3852 const char *default_metadata,
3853 const char *metadata)
3854{
3855 const char *val;
3856
3857 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_341
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_341
= 1; else _g_boolean_var_341 = 0; _g_boolean_var_341; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3858 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_342
; if (key != ((void*)0)) _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__)), "key != NULL"); return
; } } while (0)
;
3859 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_343
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return; } } while (0)
;
3860
3861 val = metadata;
3862 if (val == NULL((void*)0)) {
3863 val = default_metadata;
3864 }
3865
3866 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3867 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3868 set_metadata, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
;
3869}
3870
3871void
3872caja_file_set_metadata_list (CajaFile *file,
3873 const char *key,
3874 GList *list)
3875{
3876 char **val;
3877 int len, i;
3878 GList *l;
3879
3880 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_344
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_344
= 1; else _g_boolean_var_344 = 0; _g_boolean_var_344; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3881 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_345
; if (key != ((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__)), "key != NULL"); return
; } } while (0)
;
3882 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_346
; if (key[0] != '\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__)), "key[0] != '\\0'"
); return; } } while (0)
;
3883
3884 len = g_list_length (list);
3885 val = g_new (char *, len + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
3886 for (l = list, i = 0; l != NULL((void*)0); l = l->next, i++) {
3887 val[i] = l->data;
3888 }
3889 val[i] = NULL((void*)0);
3890
3891 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3892 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3893 set_metadata_as_list, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
;
3894
3895 g_free (val);
3896}
3897
3898
3899gboolean
3900caja_file_get_boolean_metadata (CajaFile *file,
3901 const char *key,
3902 gboolean default_metadata)
3903{
3904 char *result_as_string;
3905 gboolean result;
3906
3907 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_347
; if (key != ((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__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3908 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_348
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3909
3910 if (file == NULL((void*)0)) {
3911 return default_metadata;
3912 }
3913
3914 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_349
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_349
= 1; else _g_boolean_var_349 = 0; _g_boolean_var_349; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3915
3916 result_as_string = caja_file_get_metadata
3917 (file, key, default_metadata ? "true" : "false");
3918 g_assert (result_as_string != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_350
; if (result_as_string != ((void*)0)) _g_boolean_var_350 = 1;
else _g_boolean_var_350 = 0; _g_boolean_var_350; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file.c", 3918,
((const char*) (__func__)), "result_as_string != NULL"); } while
(0)
;
3919
3920 if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3921 result = TRUE(!(0));
3922 } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3923 result = FALSE(0);
3924 } else {
3925 g_error ("boolean metadata with value other than true or false");
3926 result = default_metadata;
3927 }
3928
3929 g_free (result_as_string);
3930 return result;
3931}
3932
3933int
3934caja_file_get_integer_metadata (CajaFile *file,
3935 const char *key,
3936 int default_metadata)
3937{
3938 char *result_as_string;
3939 char default_as_string[32];
3940 int result;
3941 char c;
3942
3943 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_351
; if (key != ((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__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3944 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_352
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3945
3946 if (file == NULL((void*)0)) {
3947 return default_metadata;
3948 }
3949 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_353
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_353
= 1; else _g_boolean_var_353 = 0; _g_boolean_var_353; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3950
3951 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3952 result_as_string = caja_file_get_metadata
3953 (file, key, default_as_string);
3954
3955 /* Normally we can't get a a NULL, but we check for it here to
3956 * handle the oddball case of a non-existent directory.
3957 */
3958 if (result_as_string == NULL((void*)0)) {
3959 result = default_metadata;
3960 } else {
3961 if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3962 result = default_metadata;
3963 }
3964 g_free (result_as_string);
3965 }
3966
3967 return result;
3968}
3969
3970static gboolean
3971get_time_from_time_string (const char *time_string,
3972 time_t *time)
3973{
3974 long scanned_time;
3975 char c;
3976
3977 g_assert (time != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_354
; if (time != ((void*)0)) _g_boolean_var_354 = 1; else _g_boolean_var_354
= 0; _g_boolean_var_354; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3977, ((const char*) (__func__
)), "time != NULL"); } while (0)
;
3978
3979 /* Only accept string if it has one integer with nothing
3980 * afterwards.
3981 */
3982 if (time_string == NULL((void*)0) ||
3983 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3984 return FALSE(0);
3985 }
3986 *time = (time_t) scanned_time;
3987 return TRUE(!(0));
3988}
3989
3990time_t
3991caja_file_get_time_metadata (CajaFile *file,
3992 const char *key)
3993{
3994 time_t time;
3995 char *time_string;
3996
3997 time_string = caja_file_get_metadata (file, key, NULL((void*)0));
3998 if (!get_time_from_time_string (time_string, &time)) {
3999 time = UNDEFINED_TIME((time_t) (-1));
4000 }
4001 g_free (time_string);
4002
4003 return time;
4004}
4005
4006void
4007caja_file_set_time_metadata (CajaFile *file,
4008 const char *key,
4009 time_t time)
4010{
4011 char time_str[21];
4012 char *metadata;
4013
4014 if (time != UNDEFINED_TIME((time_t) (-1))) {
4015 /* 2^64 turns out to be 20 characters */
4016 g_snprintf (time_str, 20, "%ld", (long int)time);
4017 time_str[20] = '\0';
4018 metadata = time_str;
4019 } else {
4020 metadata = NULL((void*)0);
4021 }
4022
4023 caja_file_set_metadata (file, key, NULL((void*)0), metadata);
4024}
4025
4026
4027void
4028caja_file_set_boolean_metadata (CajaFile *file,
4029 const char *key,
4030 gboolean default_metadata,
4031 gboolean metadata)
4032{
4033 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_355
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_355
= 1; else _g_boolean_var_355 = 0; _g_boolean_var_355; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4034 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_356
; if (key != ((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__)), "key != NULL"); return
; } } while (0)
;
4035 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_357
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return; } } while (0)
;
4036
4037 caja_file_set_metadata (file, key,
4038 default_metadata ? "true" : "false",
4039 metadata ? "true" : "false");
4040}
4041
4042void
4043caja_file_set_integer_metadata (CajaFile *file,
4044 const char *key,
4045 int default_metadata,
4046 int metadata)
4047{
4048 char value_as_string[32];
4049 char default_as_string[32];
4050
4051 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_358
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_358
= 1; else _g_boolean_var_358 = 0; _g_boolean_var_358; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4052 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_359
; if (key != ((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__)), "key != NULL"); return
; } } while (0)
;
4053 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_360
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return; } } while (0)
;
4054
4055 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4056 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4057
4058 caja_file_set_metadata (file, key,
4059 default_as_string, value_as_string);
4060}
4061
4062static const char *
4063caja_file_peek_display_name_collation_key (CajaFile *file)
4064{
4065 const char *res;
4066
4067 res = file->details->display_name_collation_key;
4068 if (res == NULL((void*)0))
4069 res = "";
4070
4071 return res;
4072}
4073
4074static const char *
4075caja_file_peek_display_name (CajaFile *file)
4076{
4077 /*
4078 stefano-k: Imported 15_nautilus_file_peek_crash.patch from debian nautilus
4079 Date: Thu, 27 Jan 2011 10:22:10 +0000
4080 Subject: Prevent a crash in nautilus_file_peek_display_name() on invalid NautilusFile
4081 This is more a workaround only, expect assert failures at other
4082 places when something bad happens. There's a race condition somewhere,
4083 this patch only prevents immediate crash.
4084 Patch by Marcus Husar <marcus.husar@rose.uni-heidelberg.de>
4085 https://bugzilla.gnome.org/show_bug.cgi?id=602500
4086 */
4087 if (file == NULL((void*)0) || caja_file_is_gone (file))
4088 return "";
4089
4090 /* Default to display name based on filename if its not set yet */
4091
4092 if (file->details->display_name == NULL((void*)0)) {
4093 const char *name;
4094
4095 name = file->details->name;
4096 if (g_utf8_validate (name, -1, NULL((void*)0))) {
4097 caja_file_set_display_name (file,
4098 name,
4099 NULL((void*)0),
4100 FALSE(0));
4101 } else {
4102 char *escaped_name;
4103
4104 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
4105 caja_file_set_display_name (file,
4106 escaped_name,
4107 NULL((void*)0),
4108 FALSE(0));
4109 g_free (escaped_name);
4110 }
4111 }
4112
4113 return file->details->display_name;
4114}
4115
4116char *
4117caja_file_get_display_name (CajaFile *file)
4118{
4119 return g_strdup (caja_file_peek_display_name (file))g_strdup_inline (caja_file_peek_display_name (file));
4120}
4121
4122char *
4123caja_file_get_edit_name (CajaFile *file)
4124{
4125 const char *res;
4126
4127 res = file->details->edit_name;
4128 if (res == NULL((void*)0))
4129 res = "";
4130
4131 return g_strdup (res)g_strdup_inline (res);
4132}
4133
4134char *
4135caja_file_get_name (CajaFile *file)
4136{
4137 return g_strdup (file->details->name)g_strdup_inline (file->details->name);
4138}
4139
4140/**
4141 * caja_file_get_description:
4142 * @file: a #CajaFile.
4143 *
4144 * Gets the standard::description key from @file, if
4145 * it has been cached.
4146 *
4147 * Returns: a string containing the value of the standard::description
4148 * key, or %NULL.
4149 */
4150char *
4151caja_file_get_description (CajaFile *file)
4152{
4153 return g_strdup (file->details->description)g_strdup_inline (file->details->description);
4154}
4155
4156void
4157caja_file_monitor_add (CajaFile *file,
4158 gconstpointer client,
4159 CajaFileAttributes attributes)
4160{
4161 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_361
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_361
= 1; else _g_boolean_var_361 = 0; _g_boolean_var_361; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4162 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_362
; if (client != ((void*)0)) _g_boolean_var_362 = 1; else _g_boolean_var_362
= 0; _g_boolean_var_362; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4163
4164 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4165 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4166 monitor_add, (file, client, attributes))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
;
4167}
4168
4169void
4170caja_file_monitor_remove (CajaFile *file,
4171 gconstpointer client)
4172{
4173 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_363
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_363
= 1; else _g_boolean_var_363 = 0; _g_boolean_var_363; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4174 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_364
; if (client != ((void*)0)) _g_boolean_var_364 = 1; else _g_boolean_var_364
= 0; _g_boolean_var_364; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "client != NULL")
; return; } } while (0)
;
4175
4176 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4177 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4178 monitor_remove, (file, client))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
;
4179}
4180
4181gboolean
4182caja_file_is_launcher (CajaFile *file)
4183{
4184 return file->details->is_launcher;
4185}
4186
4187gboolean
4188caja_file_is_foreign_link (CajaFile *file)
4189{
4190 return file->details->is_foreign_link;
4191}
4192
4193gboolean
4194caja_file_is_trusted_link (CajaFile *file)
4195{
4196 return file->details->is_trusted_link;
4197}
4198
4199gboolean
4200caja_file_has_activation_uri (CajaFile *file)
4201{
4202 return file->details->activation_uri != NULL((void*)0);
4203}
4204
4205
4206/* Return the uri associated with the passed-in file, which may not be
4207 * the actual uri if the file is an desktop file or a caja
4208 * xml link file.
4209 */
4210char *
4211caja_file_get_activation_uri (CajaFile *file)
4212{
4213 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_365
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_365
= 1; else _g_boolean_var_365 = 0; _g_boolean_var_365; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4214
4215 if (file->details->activation_uri != NULL((void*)0)) {
4216 return g_strdup (file->details->activation_uri)g_strdup_inline (file->details->activation_uri);
4217 }
4218
4219 return caja_file_get_uri (file);
4220}
4221
4222GFile *
4223caja_file_get_activation_location (CajaFile *file)
4224{
4225 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_366
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_366
= 1; else _g_boolean_var_366 = 0; _g_boolean_var_366; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4226
4227 if (file->details->activation_uri != NULL((void*)0)) {
4228 return g_file_new_for_uri (file->details->activation_uri);
4229 }
4230
4231 return caja_file_get_location (file);
4232}
4233
4234
4235char *
4236caja_file_get_drop_target_uri (CajaFile *file)
4237{
4238 char *uri, *target_uri;
4239 GFile *location;
4240
4241 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_367
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_367
= 1; else _g_boolean_var_367 = 0; _g_boolean_var_367; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4242
4243 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
4244 CajaDesktopLink *link;
4245
4246 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
4247
4248 if (link != NULL((void*)0)) {
4249 location = caja_desktop_link_get_activation_location (link);
4250 g_object_unref (link);
4251 if (location != NULL((void*)0)) {
4252 uri = g_file_get_uri (location);
4253 g_object_unref (location);
4254 return uri;
4255 }
4256 }
4257 }
4258
4259 uri = caja_file_get_uri (file);
4260
4261 /* Check for Caja link */
4262 if (caja_file_is_caja_link (file)) {
4263 location = caja_file_get_location (file);
4264 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
4265 if (g_file_is_native (location)) {
4266 target_uri = caja_link_local_get_link_uri (uri);
4267 if (target_uri != NULL((void*)0)) {
4268 g_free (uri);
4269 uri = target_uri;
4270 }
4271 }
4272 g_object_unref (location);
4273 }
4274
4275 return uri;
4276}
4277
4278static gboolean
4279is_uri_relative (const char *uri)
4280{
4281 char *scheme;
4282 gboolean ret;
4283
4284 scheme = g_uri_parse_scheme (uri);
4285 ret = (scheme == NULL((void*)0));
4286 g_free (scheme);
4287 return ret;
4288}
4289
4290static char *
4291get_custom_icon_metadata_uri (CajaFile *file)
4292{
4293 char *custom_icon_uri;
4294 char *uri;
4295
4296 uri = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
4297 if (uri != NULL((void*)0) &&
4298 caja_file_is_directory (file) &&
4299 is_uri_relative (uri)) {
4300 char *dir_uri;
4301
4302 dir_uri = caja_file_get_uri (file);
4303 custom_icon_uri = g_build_filename (dir_uri, uri, NULL((void*)0));
4304 g_free (dir_uri);
4305 g_free (uri);
4306 } else {
4307 custom_icon_uri = uri;
4308 }
4309 return custom_icon_uri;
4310}
4311
4312static GIcon *
4313get_custom_icon (CajaFile *file)
4314{
4315 char *custom_icon_uri;
4316 GFile *icon_file;
4317 GIcon *icon;
4318
4319 if (file == NULL((void*)0)) {
4320 return NULL((void*)0);
4321 }
4322
4323 icon = NULL((void*)0);
4324
4325 /* Metadata takes precedence */
4326 custom_icon_uri = get_custom_icon_metadata_uri (file);
4327
4328 if (custom_icon_uri) {
4329 icon_file = g_file_new_for_uri (custom_icon_uri);
4330 icon = g_file_icon_new (icon_file);
4331 g_object_unref (icon_file);
4332 g_free (custom_icon_uri);
4333 }
4334
4335 if (icon == NULL((void*)0) && file->details->got_link_info && file->details->custom_icon != NULL((void*)0)) {
4336 if (g_path_is_absolute (file->details->custom_icon)) {
4337 icon_file = g_file_new_for_path (file->details->custom_icon);
4338 icon = g_file_icon_new (icon_file);
4339 g_object_unref (icon_file);
4340 } else {
4341 icon = g_themed_icon_new (file->details->custom_icon);
4342 }
4343 }
4344
4345 return icon;
4346}
4347
4348
4349static guint64 cached_thumbnail_limit;
4350int cached_thumbnail_size;
4351static int show_image_thumbs;
4352
4353GFilesystemPreviewType
4354caja_file_get_filesystem_use_preview (CajaFile *file)
4355{
4356 GFilesystemPreviewType use_preview;
4357 CajaFile *parent;
4358
4359 parent = caja_file_get_parent (file);
4360 if (parent != NULL((void*)0)) {
4361 use_preview = parent->details->filesystem_use_preview;
4362 g_object_unref (parent);
4363 } else {
4364 use_preview = 0;
4365 }
4366
4367 return use_preview;
4368}
4369
4370gboolean
4371caja_file_should_show_thumbnail (CajaFile *file)
4372{
4373 const char *mime_type;
4374 GFilesystemPreviewType use_preview;
4375
4376 use_preview = caja_file_get_filesystem_use_preview (file);
4377
4378 mime_type = file->details->mime_type;
4379 if (mime_type == NULL((void*)0)) {
4380 mime_type = "application/octet-stream";
4381 }
4382
4383 /* If the thumbnail has already been created, don't care about the size
4384 * of the original file.
4385 */
4386 if (caja_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4387 file->details->thumbnail_path == NULL((void*)0) &&
4388 caja_file_get_size (file) > cached_thumbnail_limit) {
4389 return FALSE(0);
4390 }
4391
4392 if (show_image_thumbs == CAJA_SPEED_TRADEOFF_ALWAYS) {
4393 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4394 return FALSE(0);
4395 } else {
4396 return TRUE(!(0));
4397 }
4398 } else if (show_image_thumbs == CAJA_SPEED_TRADEOFF_NEVER) {
4399 return FALSE(0);
4400 } else {
4401 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4402 /* file system says to never thumbnail anything */
4403 return FALSE(0);
4404 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4405 /* file system says we should treat file as if it's local */
4406 return TRUE(!(0));
4407 } else {
4408 /* only local files */
4409 return caja_file_is_local (file);
4410 }
4411 }
4412
4413 return FALSE(0);
4414}
4415
4416static void
4417prepend_icon_name (const char *name,
4418 GThemedIcon *icon)
4419{
4420 g_themed_icon_prepend_name(icon, name);
4421}
4422
4423GIcon *
4424caja_file_get_gicon (CajaFile *file,
4425 CajaFileIconFlags flags)
4426{
4427 const char * const * names;
4428 GIcon *icon, *mount_icon = NULL((void*)0), *emblemed_icon;
4429 gboolean is_folder = FALSE(0), is_preview = FALSE(0), is_inode_directory = FALSE(0);
4430
4431 if (file == NULL((void*)0)) {
4432 return NULL((void*)0);
4433 }
4434
4435 icon = get_custom_icon (file);
4436 if (icon != NULL((void*)0)) {
4437 return icon;
4438 }
4439
4440 if (file->details->icon) {
4441 icon = NULL((void*)0);
4442
4443 /* fetch the mount icon here, we'll use it later */
4444 if (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4445 flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4446 GMount *mount;
4447
4448 mount = caja_file_get_mount (file);
4449
4450 if (mount != NULL((void*)0)) {
4451 mount_icon = g_mount_get_icon (mount);
4452 g_object_unref (mount);
4453 }
4454 }
4455
4456 if (((flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4457 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4458 (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4459 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4460 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4461 ((flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4462 caja_file_has_open_window (file))) &&
4463 G_IS_THEMED_ICON (file->details->icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file->details->icon)); GType __t = ((g_themed_icon_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; }))))
) {
4464 GPtrArray *prepend_array;
4465 int i;
4466
4467 names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon)((((GThemedIcon*) (void *) ((file->details->icon))))));
4468 prepend_array = g_ptr_array_new ();
4469
4470 for (i = 0; names[i] != NULL((void*)0); i++) {
4471 const char *name;
4472
4473 name = names[i];
4474
4475 if (strcmp (name, "folder") == 0) {
4476 is_folder = TRUE(!(0));
4477 }
4478 if (strcmp (name, "inode-directory") == 0) {
4479 is_inode_directory = TRUE(!(0));
4480 }
4481 if (strcmp (name, "text-x-generic") == 0 &&
4482 (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4483 is_preview = TRUE(!(0));
4484 }
4485 }
4486
4487 /* Here, we add icons in reverse order of precedence,
4488 * because they are later prepended */
4489 if (is_preview) {
4490 g_ptr_array_add (prepend_array, "text-x-preview");
4491 }
4492
4493 /* "folder" should override "inode-directory", not the other way around */
4494 if (is_inode_directory) {
4495 g_ptr_array_add (prepend_array, "folder");
4496 }
4497 if (is_folder && (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4498 g_ptr_array_add (prepend_array, "folder-open");
4499 }
4500 if (is_folder &&
4501 (flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4502 caja_file_has_open_window (file)) {
4503 g_ptr_array_add (prepend_array, "folder-visiting");
4504 }
4505 if (is_folder &&
4506 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4507 g_ptr_array_add (prepend_array, "folder-drag-accept");
4508 }
4509
4510 if (prepend_array->len) {
4511 /* When constructing GThemed Icon, pointers from the array
4512 * are reused, but not the array itself, so the cast is safe */
4513 icon = g_themed_icon_new_from_names ((char**) names, -1);
4514 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4515 }
4516
4517 g_ptr_array_free (prepend_array, TRUE(!(0)));
4518 }
4519
4520 if (icon == NULL((void*)0)) {
4521 icon = g_object_ref (file->details->icon)((__typeof__ (file->details->icon)) (g_object_ref) (file
->details->icon))
;
4522 }
4523
4524 if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4525 mount_icon != NULL((void*)0)) {
4526 g_object_unref (icon);
4527 icon = mount_icon;
4528 } else if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4529 mount_icon != NULL((void*)0) && !g_icon_equal (mount_icon, icon)) {
4530 GEmblem *emblem;
4531
4532 emblem = g_emblem_new (mount_icon);
4533 emblemed_icon = g_emblemed_icon_new (icon, emblem);
4534
4535 g_object_unref (emblem);
4536 g_object_unref (icon);
4537 g_object_unref (mount_icon);
4538
4539 icon = emblemed_icon;
4540 } else if (mount_icon != NULL((void*)0)) {
4541 g_object_unref (mount_icon);
4542 }
4543
4544 return icon;
4545 }
4546
4547 return g_themed_icon_new ("text-x-generic");
4548}
4549
4550static GIcon *
4551get_default_file_icon (CajaFileIconFlags flags)
4552{
4553 static GIcon *fallback_icon = NULL((void*)0);
4554 static GIcon *fallback_icon_preview = NULL((void*)0);
4555 if (fallback_icon == NULL((void*)0)) {
4556 fallback_icon = g_themed_icon_new ("text-x-generic");
4557 fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4558 g_themed_icon_append_name (G_THEMED_ICON (fallback_icon_preview)((((GThemedIcon*) (void *) ((fallback_icon_preview))))), "text-x-generic");
4559 }
4560 if (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4561 return fallback_icon_preview;
4562 } else {
4563 return fallback_icon;
4564 }
4565}
4566
4567CajaIconInfo *
4568caja_file_get_icon (CajaFile *file,
4569 int size,
4570 int scale,
4571 CajaFileIconFlags flags)
4572{
4573 CajaIconInfo *icon;
4574 GIcon *gicon;
4575 GdkPixbuf *scaled_pixbuf;
4576
4577 if (file == NULL((void*)0)) {
4578 return NULL((void*)0);
4579 }
4580
4581 gicon = get_custom_icon (file);
4582 if (gicon) {
4583 GdkPixbuf *pixbuf;
4584
4585 icon = caja_icon_info_lookup (gicon, size, scale);
4586 g_object_unref (gicon);
4587
4588 pixbuf = caja_icon_info_get_pixbuf (icon);
4589 if (pixbuf != NULL((void*)0)) {
4590 if (!file->details->is_launcher && !gdk_pixbuf_get_has_alpha (pixbuf)) {
4591 caja_ui_frame_image (&pixbuf);
4592 }
4593 g_object_unref (icon);
4594
4595 icon = caja_icon_info_new_for_pixbuf (pixbuf, scale);
4596 g_object_unref (pixbuf);
4597 }
4598
4599 return icon;
4600 }
4601
4602 if (flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4603 caja_file_should_show_thumbnail (file)) {
4604 int modified_size;
4605
4606 if (flags & CAJA_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4607 modified_size = size * scale;
4608 } else {
4609 modified_size = size * scale * cached_thumbnail_size / CAJA_ICON_SIZE_STANDARD48;
4610 }
4611
4612 if (file->details->thumbnail) {
4613 int w, h, s;
4614 double thumb_scale;
4615 GdkPixbuf *raw_pixbuf;
4616
4617 raw_pixbuf = g_object_ref (file->details->thumbnail)((__typeof__ (file->details->thumbnail)) (g_object_ref)
(file->details->thumbnail))
;
4618
4619 w = gdk_pixbuf_get_width (raw_pixbuf);
4620 h = gdk_pixbuf_get_height (raw_pixbuf);
4621
4622 s = MAX (w, h)(((w) > (h)) ? (w) : (h));
4623 /* Don't scale up small thumbnails in the standard view */
4624 if (s <= cached_thumbnail_size) {
4625 thumb_scale = (double)size / CAJA_ICON_SIZE_STANDARD48;
4626 }
4627 else {
4628 thumb_scale = (double)modified_size / s;
4629 }
4630 /* Make sure that icons don't get smaller than CAJA_ICON_SIZE_SMALLEST */
4631 if (s*thumb_scale <= CAJA_ICON_SIZE_SMALLEST16) {
4632 thumb_scale = (double) CAJA_ICON_SIZE_SMALLEST16 / s;
4633 }
4634
4635 scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4636 MAX (w * thumb_scale, 1)(((w * thumb_scale) > (1)) ? (w * thumb_scale) : (1)),
4637 MAX (h * thumb_scale, 1)(((h * thumb_scale) > (1)) ? (h * thumb_scale) : (1)),
4638 GDK_INTERP_BILINEAR);
4639
4640 /* Render frames only for thumbnails of non-image files
4641 and for images with no alpha channel. */
4642 gboolean is_image = file->details->mime_type &&
4643 (strncmp (file->details->mime_type, "image/", 6) == 0);
4644 if (!is_image || !gdk_pixbuf_get_has_alpha (raw_pixbuf)) {
4645 caja_ui_frame_image (&scaled_pixbuf);
4646 }
4647
4648 g_object_unref (raw_pixbuf);
4649
4650 /* Don't scale up if more than 25%, then read the original
4651 image instead. We don't want to compare to exactly 100%,
4652 since the zoom level 150% gives thumbnails at 144, which is
4653 ok to scale up from 128. */
4654 if (modified_size > 128 * 1.25 * scale &&
4655 !file->details->thumbnail_wants_original &&
4656 caja_can_thumbnail_internally (file)) {
4657 /* Invalidate if we resize upward */
4658 file->details->thumbnail_wants_original = TRUE(!(0));
4659 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_THUMBNAIL);
4660 }
4661
4662 icon = caja_icon_info_new_for_pixbuf (scaled_pixbuf, scale);
4663 g_object_unref (scaled_pixbuf);
4664 return icon;
4665 } else if (file->details->thumbnail_path == NULL((void*)0) &&
4666 file->details->can_read &&
4667 !file->details->is_thumbnailing &&
4668 !file->details->thumbnailing_failed) {
4669 if (caja_can_thumbnail (file)) {
4670 caja_create_thumbnail (file);
4671 }
4672 }
4673 }
4674
4675 if (file->details->is_thumbnailing &&
4676 flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS)
4677 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING"image-loading");
4678 else
4679 gicon = caja_file_get_gicon (file, flags);
4680
4681 if (gicon) {
4682 icon = caja_icon_info_lookup (gicon, size, scale);
4683 g_object_unref (gicon);
4684 return icon;
4685 } else {
4686 return caja_icon_info_lookup (get_default_file_icon (flags), size, scale);
4687 }
4688}
4689
4690cairo_surface_t *
4691caja_file_get_icon_surface (CajaFile *file,
4692 int size,
4693 gboolean force_size,
4694 int scale,
4695 CajaFileIconFlags flags)
4696{
4697 CajaIconInfo *info;
4698 cairo_surface_t *surface;
4699
4700 info = caja_file_get_icon (file, size, scale, flags);
4701 if (force_size) {
4702 surface = caja_icon_info_get_surface_at_size (info, size);
4703 } else {
4704 surface = caja_icon_info_get_surface (info);
4705 }
4706 g_object_unref (info);
4707
4708 return surface;
4709}
4710
4711char *
4712caja_file_get_custom_icon (CajaFile *file)
4713{
4714 char *custom_icon;
4715
4716 if (file == NULL((void*)0)) {
4717 return NULL((void*)0);
4718 }
4719
4720 /* Metadata takes precedence */
4721 custom_icon = get_custom_icon_metadata_uri (file);
4722
4723 if (custom_icon == NULL((void*)0) && file->details->got_link_info) {
4724 custom_icon = g_strdup (file->details->custom_icon)g_strdup_inline (file->details->custom_icon);
4725 }
4726
4727 return custom_icon;
4728}
4729
4730
4731gboolean
4732caja_file_get_date (CajaFile *file,
4733 CajaDateType date_type,
4734 time_t *date)
4735{
4736 if (date != NULL((void*)0)) {
4737 *date = 0;
4738 }
4739
4740 g_return_val_if_fail (date_type == CAJA_DATE_TYPE_CHANGEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_368
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_368 = 1; else _g_boolean_var_368 = 0; _g_boolean_var_368
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4741 || date_type == CAJA_DATE_TYPE_ACCESSEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_368
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_368 = 1; else _g_boolean_var_368 = 0; _g_boolean_var_368
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4742 || date_type == CAJA_DATE_TYPE_MODIFIEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_368
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_368 = 1; else _g_boolean_var_368 = 0; _g_boolean_var_368
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4743 || date_type == CAJA_DATE_TYPE_CREATEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_368
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_368 = 1; else _g_boolean_var_368 = 0; _g_boolean_var_368
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4744 || date_type == CAJA_DATE_TYPE_TRASHEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_368
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_368 = 1; else _g_boolean_var_368 = 0; _g_boolean_var_368
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4745 || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_368
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _g_boolean_var_368 = 1; else _g_boolean_var_368 = 0; _g_boolean_var_368
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
;
4746
4747 if (file == NULL((void*)0)) {
4748 return FALSE(0);
4749 }
4750
4751 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_369
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_369
= 1; else _g_boolean_var_369 = 0; _g_boolean_var_369; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
4752
4753 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4754 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4755 get_date, (file, date_type, date))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
;
4756}
4757
4758static char *
4759caja_file_get_where_string (CajaFile *file)
4760{
4761 if (file == NULL((void*)0)) {
4762 return NULL((void*)0);
4763 }
4764
4765 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_370
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_370
= 1; else _g_boolean_var_370 = 0; _g_boolean_var_370; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4766
4767 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4768 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4769 get_where_string, (file))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
;
4770}
4771
4772static const char *TODAY_TIME_FORMATS [] = {
4773 /* Today, use special word.
4774 * strftime patterns preceeded with the widest
4775 * possible resulting string for that pattern.
4776 *
4777 * Note to localizers: You can look at man strftime
4778 * for details on the format, but you should only use
4779 * the specifiers from the C standard, not extensions.
4780 * These include "%" followed by one of
4781 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
4782 * in the Caja version of strftime that can be
4783 * used (and match GNU extensions). Putting a "-"
4784 * between the "%" and any numeric directive will turn
4785 * off zero padding, and putting a "_" there will use
4786 * space padding instead of zero padding.
4787 */
4788 N_("today at 00:00:00 PM")("today at 00:00:00 PM"),
4789 N_("today at %-I:%M:%S %p")("today at %-I:%M:%S %p"),
4790
4791 N_("today at 00:00 PM")("today at 00:00 PM"),
4792 N_("today at %-I:%M %p")("today at %-I:%M %p"),
4793
4794 N_("today, 00:00 PM")("today, 00:00 PM"),
4795 N_("today, %-I:%M %p")("today, %-I:%M %p"),
4796
4797 N_("today")("today"),
4798 N_("today")("today"),
4799
4800 NULL((void*)0)
4801};
4802
4803static const char *YESTERDAY_TIME_FORMATS [] = {
4804 /* Yesterday, use special word.
4805 * Note to localizers: Same issues as "today" string.
4806 */
4807 N_("yesterday at 00:00:00 PM")("yesterday at 00:00:00 PM"),
4808 N_("yesterday at %-I:%M:%S %p")("yesterday at %-I:%M:%S %p"),
4809
4810 N_("yesterday at 00:00 PM")("yesterday at 00:00 PM"),
4811 N_("yesterday at %-I:%M %p")("yesterday at %-I:%M %p"),
4812
4813 N_("yesterday, 00:00 PM")("yesterday, 00:00 PM"),
4814 N_("yesterday, %-I:%M %p")("yesterday, %-I:%M %p"),
4815
4816 N_("yesterday")("yesterday"),
4817 N_("yesterday")("yesterday"),
4818
4819 NULL((void*)0)
4820};
4821
4822static const char *CURRENT_WEEK_TIME_FORMATS [] = {
4823 /* Current week, include day of week.
4824 * Note to localizers: Same issues as "today" string.
4825 * The width measurement templates correspond to
4826 * the day/month name with the most letters.
4827 */
4828 N_("Wednesday, September 00 0000 at 00:00:00 PM")("Wednesday, September 00 0000 at 00:00:00 PM"),
4829 N_("%A, %B %-d %Y at %-I:%M:%S %p")("%A, %B %-d %Y at %-I:%M:%S %p"),
4830
4831 N_("Mon, Oct 00 0000 at 00:00:00 PM")("Mon, Oct 00 0000 at 00:00:00 PM"),
4832 N_("%a, %b %-d %Y at %-I:%M:%S %p")("%a, %b %-d %Y at %-I:%M:%S %p"),
4833
4834 N_("Mon, Oct 00 0000 at 00:00 PM")("Mon, Oct 00 0000 at 00:00 PM"),
4835 N_("%a, %b %-d %Y at %-I:%M %p")("%a, %b %-d %Y at %-I:%M %p"),
4836
4837 N_("Oct 00 0000 at 00:00 PM")("Oct 00 0000 at 00:00 PM"),
4838 N_("%b %-d %Y at %-I:%M %p")("%b %-d %Y at %-I:%M %p"),
4839
4840 N_("Oct 00 0000, 00:00 PM")("Oct 00 0000, 00:00 PM"),
4841 N_("%b %-d %Y, %-I:%M %p")("%b %-d %Y, %-I:%M %p"),
4842
4843 N_("00/00/00, 00:00 PM")("00/00/00, 00:00 PM"),
4844 N_("%m/%-d/%y, %-I:%M %p")("%m/%-d/%y, %-I:%M %p"),
4845
4846 N_("00/00/00")("00/00/00"),
4847 N_("%m/%d/%y")("%m/%d/%y"),
4848
4849 NULL((void*)0)
4850};
4851
4852static char *
4853caja_file_fit_date_as_string (CajaFile *file,
4854 CajaDateType date_type,
4855 int width,
4856 CajaWidthMeasureCallback measure_callback,
4857 CajaTruncateCallback truncate_callback,
4858 void *measure_context)
4859{
4860 time_t file_time_raw;
4861 const char **formats;
4862 const char *format;
4863 char *date_string;
4864 gchar *result = NULL((void*)0);
4865 int i;
4866 GDateTime *date_time, *today, *end_of_today;
4867 GTimeSpan file_date_age;
4868
4869 if (!caja_file_get_date (file, date_type, &file_time_raw)) {
4870 return NULL((void*)0);
4871 }
4872
4873 date_time = g_date_time_new_from_unix_local (file_time_raw);
4874
4875 if (date_format_pref == CAJA_DATE_FORMAT_LOCALE) {
4876 result = g_date_time_format (date_time, "%c");
4877 goto out;
4878 } else if (date_format_pref == CAJA_DATE_FORMAT_ISO) {
4879 result = g_date_time_format (date_time, "%Y-%m-%d %H:%M:%S");
4880 goto out;
4881 }
4882
4883 today = g_date_time_new_now_local ();
4884 end_of_today = g_date_time_add_full (today, 0, 0, 1,
4885 -1 * g_date_time_get_hour (today),
4886 -1 * g_date_time_get_minute (today),
4887 -1.0 * g_date_time_get_seconds (today));
4888 g_date_time_unref (today);
4889
4890 file_date_age = g_date_time_difference (end_of_today, date_time);
4891 g_date_time_unref (end_of_today);
4892
4893 /* Format varies depending on how old the date is. This minimizes
4894 * the length (and thus clutter & complication) of typical dates
4895 * while providing sufficient detail for recent dates to make
4896 * them maximally understandable at a glance. Keep all format
4897 * strings separate rather than combining bits & pieces for
4898 * internationalization's sake.
4899 */
4900
4901 if (file_date_age <= 0 || file_date_age > 2 * G_TIME_SPAN_DAY((86400000000L))) {
4902 formats = CURRENT_WEEK_TIME_FORMATS;
4903 } else if (file_date_age > G_TIME_SPAN_DAY((86400000000L))) {
4904 formats = YESTERDAY_TIME_FORMATS;
4905 } else {
4906 formats = TODAY_TIME_FORMATS;
4907 }
4908
4909 /* Find the date format that just fits the required width. Instead of measuring
4910 * the resulting string width directly, measure the width of a template that represents
4911 * the widest possible version of a date in a given format. This is done by using M, m
4912 * and 0 for the variable letters/digits respectively.
4913 */
4914 format = NULL((void*)0);
4915
4916 for (i = 0; ; i += 2) {
4917 const char *width_template;
4918
4919 width_template = (formats [i] ? _(formats [i])dcgettext (((void*)0), formats [i], 5) : NULL((void*)0));
4920 if (width_template == NULL((void*)0)) {
4921 /* no more formats left */
4922 g_assert (format != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_371
; if (format != ((void*)0)) _g_boolean_var_371 = 1; else _g_boolean_var_371
= 0; _g_boolean_var_371; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 4922, ((const char*) (__func__
)), "format != NULL"); } while (0)
;
4923
4924 /* Can't fit even the shortest format -- return an ellipsized form in the
4925 * shortest format
4926 */
4927
4928 date_string = g_date_time_format (date_time, format);
4929
4930 if (truncate_callback == NULL((void*)0)) {
4931 result = date_string;
4932 break;
4933 }
4934
4935 result = (* truncate_callback) (date_string, width, measure_context);
4936 g_free (date_string);
4937 break;
4938 }
4939
4940 format = _(formats [i + 1])dcgettext (((void*)0), formats [i + 1], 5);
4941
4942 if (measure_callback == NULL((void*)0)) {
4943 /* don't care about fitting the width */
4944 break;
4945 }
4946
4947 if ((* measure_callback) (width_template, measure_context) <= width) {
4948 /* The template fits, this is the format we can fit. */
4949 break;
4950 }
4951 }
4952
4953 if (result == NULL((void*)0)) {
4954 result = g_date_time_format (date_time, format);
4955 }
4956
4957out:
4958 g_date_time_unref (date_time);
4959 return result;
4960}
4961
4962/**
4963 * caja_file_fit_modified_date_as_string:
4964 *
4965 * Get a user-displayable string representing a file modification date,
4966 * truncated to @width using the measuring and truncating callbacks.
4967 * @file: CajaFile representing the file in question.
4968 * @width: The desired resulting string width.
4969 * @measure_callback: The callback used to measure the string width.
4970 * @truncate_callback: The callback used to truncate the string to a desired width.
4971 * @measure_context: Data neede when measuring and truncating.
4972 *
4973 * Returns: Newly allocated string ready to display to the user.
4974 *
4975 **/
4976char *
4977caja_file_fit_modified_date_as_string (CajaFile *file,
4978 int width,
4979 CajaWidthMeasureCallback measure_callback,
4980 CajaTruncateCallback truncate_callback,
4981 void *measure_context)
4982{
4983 return caja_file_fit_date_as_string (file, CAJA_DATE_TYPE_MODIFIED,
4984 width, measure_callback, truncate_callback, measure_context);
4985}
4986
4987static char *
4988caja_file_get_trash_original_file_parent_as_string (CajaFile *file)
4989{
4990 if (file->details->trash_orig_path != NULL((void*)0)) {
4991 CajaFile *orig_file, *parent;
4992 GFile *location;
4993 char *filename;
4994
4995 orig_file = caja_file_get_trash_original_file (file);
4996 parent = caja_file_get_parent (orig_file);
4997 location = caja_file_get_location (parent);
4998
4999 filename = g_file_get_parse_name (location);
5000
5001 g_object_unref (location);
5002 caja_file_unref (parent);
5003 caja_file_unref (orig_file);
5004
5005 return filename;
5006 }
5007
5008 return NULL((void*)0);
5009}
5010
5011/**
5012 * caja_file_get_date_as_string:
5013 *
5014 * Get a user-displayable string representing a file modification date.
5015 * The caller is responsible for g_free-ing this string.
5016 * @file: CajaFile representing the file in question.
5017 *
5018 * Returns: Newly allocated string ready to display to the user.
5019 *
5020 **/
5021static char *
5022caja_file_get_date_as_string (CajaFile *file, CajaDateType date_type)
5023{
5024 return caja_file_fit_date_as_string (file, date_type,
5025 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5026}
5027
5028static CajaSpeedTradeoffValue show_directory_item_count;
5029static CajaSpeedTradeoffValue show_text_in_icons;
5030
5031static void
5032show_text_in_icons_changed_callback (gpointer callback_data)
5033{
5034 show_text_in_icons = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS"show-icon-text");
5035}
5036
5037static void
5038show_directory_item_count_changed_callback (gpointer callback_data)
5039{
5040 show_directory_item_count = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS"show-directory-item-counts");
5041}
5042
5043static gboolean
5044get_speed_tradeoff_preference_for_file (CajaFile *file, CajaSpeedTradeoffValue value)
5045{
5046 GFilesystemPreviewType use_preview;
5047
5048 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_372
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_372
= 1; else _g_boolean_var_372 = 0; _g_boolean_var_372; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5049
5050 use_preview = caja_file_get_filesystem_use_preview (file);
5051
5052 if (value == CAJA_SPEED_TRADEOFF_ALWAYS) {
5053 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5054 return FALSE(0);
5055 } else {
5056 return TRUE(!(0));
5057 }
5058 }
5059
5060 if (value == CAJA_SPEED_TRADEOFF_NEVER) {
5061 return FALSE(0);
5062 }
5063
5064 g_assert (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_373
; if (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY) _g_boolean_var_373
= 1; else _g_boolean_var_373 = 0; _g_boolean_var_373; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5064, ((const char*) (__func__)), "value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY"
); } while (0)
;
5065
5066 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5067 /* file system says to never preview anything */
5068 return FALSE(0);
5069 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
5070 /* file system says we should treat file as if it's local */
5071 return TRUE(!(0));
5072 } else {
5073 /* only local files */
5074 return caja_file_is_local (file);
5075 }
5076}
5077
5078gboolean
5079caja_file_should_show_directory_item_count (CajaFile *file)
5080{
5081 static gboolean show_directory_item_count_callback_added = FALSE(0);
5082
5083 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_374
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_374
= 1; else _g_boolean_var_374 = 0; _g_boolean_var_374; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5084
5085 if (file->details->mime_type &&
5086 strcmp (file->details->mime_type, "x-directory/smb-share") == 0) {
5087 return FALSE(0);
5088 }
5089
5090 /* Add the callback once for the life of our process */
5091 if (!show_directory_item_count_callback_added) {
5092 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5093 "changed::" CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5094 G_CALLBACK(show_directory_item_count_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5095 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5096 show_directory_item_count_callback_added = TRUE(!(0));
5097
5098 /* Peek for the first time */
5099 show_directory_item_count_changed_callback (NULL((void*)0));
5100 }
5101
5102 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5103}
5104
5105gboolean
5106caja_file_should_show_type (CajaFile *file)
5107{
5108 char *uri;
5109 gboolean ret;
5110
5111 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_375
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_375
= 1; else _g_boolean_var_375 = 0; _g_boolean_var_375; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5112
5113 uri = caja_file_get_uri (file);
5114 ret = ((strcmp (uri, "computer:///") != 0) &&
5115 (strcmp (uri, "network:///") != 0) &&
5116 (strcmp (uri, "smb:///") != 0));
5117 g_free (uri);
5118
5119 return ret;
5120}
5121
5122gboolean
5123caja_file_should_get_top_left_text (CajaFile *file)
5124{
5125 static gboolean show_text_in_icons_callback_added = FALSE(0);
5126
5127 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_376
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_376
= 1; else _g_boolean_var_376 = 0; _g_boolean_var_376; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5128
5129 /* Add the callback once for the life of our process */
5130 if (!show_text_in_icons_callback_added) {
5131 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5132 "changed::" CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5133 G_CALLBACK (show_text_in_icons_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5134 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5135 show_text_in_icons_callback_added = TRUE(!(0));
5136
5137 /* Peek for the first time */
5138 show_text_in_icons_changed_callback (NULL((void*)0));
5139 }
5140
5141 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_ALWAYS) {
5142 return TRUE(!(0));
5143 }
5144
5145 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_NEVER) {
5146 return FALSE(0);
5147 }
5148
5149 return get_speed_tradeoff_preference_for_file (file, show_text_in_icons);
5150}
5151
5152/**
5153 * caja_file_get_directory_item_count
5154 *
5155 * Get the number of items in a directory.
5156 * @file: CajaFile representing a directory.
5157 * @count: Place to put count.
5158 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5159 * the item count from being read on this directory. Otherwise set to FALSE.
5160 *
5161 * Returns: TRUE if count is available.
5162 *
5163 **/
5164gboolean
5165caja_file_get_directory_item_count (CajaFile *file,
5166 guint *count,
5167 gboolean *count_unreadable)
5168{
5169 if (count != NULL((void*)0)) {
5170 *count = 0;
5171 }
5172 if (count_unreadable != NULL((void*)0)) {
5173 *count_unreadable = FALSE(0);
5174 }
5175
5176 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_377
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_377
= 1; else _g_boolean_var_377 = 0; _g_boolean_var_377; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5177
5178 if (!caja_file_is_directory (file)) {
5179 return FALSE(0);
5180 }
5181
5182 if (!caja_file_should_show_directory_item_count (file)) {
5183 return FALSE(0);
5184 }
5185
5186 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5187 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5188 get_item_count, (file, count, count_unreadable))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
;
5189}
5190
5191/**
5192 * caja_file_get_deep_counts
5193 *
5194 * Get the statistics about items inside a directory.
5195 * @file: CajaFile representing a directory or file.
5196 * @directory_count: Place to put count of directories inside.
5197 * @files_count: Place to put count of files inside.
5198 * @unreadable_directory_count: Number of directories encountered
5199 * that were unreadable.
5200 * @total_size: Total size of all files and directories visited.
5201 * @total_size_on_disk: Total size on disk of all files and directories visited.
5202 * @force: Whether the deep counts should even be collected if
5203 * caja_file_should_show_directory_item_count returns FALSE
5204 * for this file.
5205 *
5206 * Returns: Status to indicate whether sizes are available.
5207 *
5208 **/
5209CajaRequestStatus
5210caja_file_get_deep_counts (CajaFile *file,
5211 guint *directory_count,
5212 guint *file_count,
5213 guint *unreadable_directory_count,
5214 goffset *total_size,
5215 goffset *total_size_on_disk,
5216 gboolean force)
5217{
5218 if (directory_count != NULL((void*)0)) {
5219 *directory_count = 0;
5220 }
5221 if (file_count != NULL((void*)0)) {
5222 *file_count = 0;
5223 }
5224 if (unreadable_directory_count != NULL((void*)0)) {
5225 *unreadable_directory_count = 0;
5226 }
5227 if (total_size != NULL((void*)0)) {
5228 *total_size = 0;
5229 }
5230 if (total_size_on_disk != NULL((void*)0)) {
5231 *total_size_on_disk = 0;
5232 }
5233
5234 g_return_val_if_fail (CAJA_IS_FILE (file), CAJA_REQUEST_DONE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_378
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_378
= 1; else _g_boolean_var_378 = 0; _g_boolean_var_378; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (CAJA_REQUEST_DONE
); } } while (0)
;
5235
5236 if (!force && !caja_file_should_show_directory_item_count (file)) {
5237 /* Set field so an existing value isn't treated as up-to-date
5238 * when preference changes later.
5239 */
5240 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5241 return file->details->deep_counts_status;
5242 }
5243
5244 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5245 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5246 get_deep_counts, (file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5247 directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5248 file_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5249 unreadable_directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5250 total_size,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5251 total_size_on_disk))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
;
5252}
5253
5254void
5255caja_file_recompute_deep_counts (CajaFile *file)
5256{
5257 if (file->details->deep_counts_status != CAJA_REQUEST_IN_PROGRESS) {
5258 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5259 if (file->details->directory != NULL((void*)0)) {
5260 caja_directory_add_file_to_work_queue (file->details->directory, file);
5261 caja_directory_async_state_changed (file->details->directory);
5262 }
5263 }
5264}
5265
5266gboolean
5267caja_file_can_get_size (CajaFile *file)
5268{
5269 return file->details->size == -1;
5270}
5271
5272
5273/**
5274 * caja_file_get_size
5275 *
5276 * Get the file size.
5277 * @file: CajaFile representing the file in question.
5278 *
5279 * Returns: Size in bytes.
5280 *
5281 **/
5282goffset
5283caja_file_get_size (CajaFile *file)
5284{
5285 /* Before we have info on the file, we don't know the size. */
5286 if (file->details->size == -1)
5287 return 0;
5288 return file->details->size;
5289}
5290
5291/**
5292 * caja_file_get_size_on_disk
5293 *
5294 * Get the file size on disk (how many bytes is using on the filesystem).
5295 * e.g.: usually files with 1 byte will use a whole inode so it will return the
5296 * size of 1 inode. If the file is sparse the size on disk will be equal or less
5297 * than the size of the file.
5298 * @file: CajaFile representing the file in question.
5299 *
5300 * Returns: Size in bytes.
5301 *
5302 **/
5303goffset
5304caja_file_get_size_on_disk (CajaFile *file)
5305{
5306 /* Before we have info on the file, we don't know the size. */
5307 if (file->details->size_on_disk == -1)
5308 return 0;
5309 return file->details->size_on_disk;
5310}
5311
5312time_t
5313caja_file_get_mtime (CajaFile *file)
5314{
5315 return file->details->mtime;
5316}
5317
5318
5319static void
5320set_attributes_get_info_callback (GObject *source_object,
5321 GAsyncResult *res,
5322 gpointer callback_data)
5323{
5324 CajaFileOperation *op;
5325 GFileInfo *new_info;
5326 GError *error;
5327
5328 op = callback_data;
5329
5330 error = NULL((void*)0);
5331 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
5332 if (new_info != NULL((void*)0)) {
5333 if (caja_file_update_info (op->file, new_info)) {
5334 caja_file_changed (op->file);
5335 }
5336 g_object_unref (new_info);
5337 }
5338 caja_file_operation_complete (op, NULL((void*)0), error);
5339 if (error) {
5340 g_error_free (error);
5341 }
5342}
5343
5344
5345static void
5346set_attributes_callback (GObject *source_object,
5347 GAsyncResult *result,
5348 gpointer callback_data)
5349{
5350 CajaFileOperation *op;
5351 GError *error;
5352 gboolean res;
5353
5354 op = callback_data;
5355
5356 error = NULL((void*)0);
5357 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5358 result,
5359 NULL((void*)0),
5360 &error);
5361
5362 if (res) {
5363 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5364 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
5365 0,
5366 G_PRIORITY_DEFAULT0,
5367 op->cancellable,
5368 set_attributes_get_info_callback, op);
5369 } else {
5370 caja_file_operation_complete (op, NULL((void*)0), error);
5371 g_error_free (error);
5372 }
5373}
5374
5375void
5376caja_file_set_attributes (CajaFile *file,
5377 GFileInfo *attributes,
5378 CajaFileOperationCallback callback,
5379 gpointer callback_data)
5380{
5381 CajaFileOperation *op;
5382 GFile *location;
5383
5384 op = caja_file_operation_new (file, callback, callback_data);
5385
5386 location = caja_file_get_location (file);
5387 g_file_set_attributes_async (location,
5388 attributes,
5389 0,
5390 G_PRIORITY_DEFAULT0,
5391 op->cancellable,
5392 set_attributes_callback,
5393 op);
5394 g_object_unref (location);
5395}
5396
5397
5398/**
5399 * caja_file_can_get_permissions:
5400 *
5401 * Check whether the permissions for a file are determinable.
5402 * This might not be the case for files on non-UNIX file systems.
5403 *
5404 * @file: The file in question.
5405 *
5406 * Return value: TRUE if the permissions are valid.
5407 */
5408gboolean
5409caja_file_can_get_permissions (CajaFile *file)
5410{
5411 return file->details->has_permissions;
5412}
5413
5414/**
5415 * caja_file_can_set_permissions:
5416 *
5417 * Check whether the current user is allowed to change
5418 * the permissions of a file.
5419 *
5420 * @file: The file in question.
5421 *
5422 * Return value: TRUE if the current user can change the
5423 * permissions of @file, FALSE otherwise. It's always possible
5424 * that when you actually try to do it, you will fail.
5425 */
5426gboolean
5427caja_file_can_set_permissions (CajaFile *file)
5428{
5429 uid_t user_id;
5430
5431 if (file->details->uid != -1 &&
5432 caja_file_is_local (file)) {
5433 /* Check the user. */
5434 user_id = geteuid();
5435
5436 /* Owner is allowed to set permissions. */
5437 if (user_id == (uid_t) file->details->uid) {
5438 return TRUE(!(0));
5439 }
5440
5441 /* Root is also allowed to set permissions. */
5442 if (user_id == 0) {
5443 return TRUE(!(0));
5444 }
5445
5446 /* Nobody else is allowed. */
5447 return FALSE(0);
5448 }
5449
5450 /* pretend to have full chmod rights when no info is available, relevant when
5451 * the FS can't provide ownership info, for instance for FTP */
5452 return TRUE(!(0));
5453}
5454
5455guint
5456caja_file_get_permissions (CajaFile *file)
5457{
5458 g_return_val_if_fail (caja_file_can_get_permissions (file), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_379
; if (caja_file_can_get_permissions (file)) _g_boolean_var_379
= 1; else _g_boolean_var_379 = 0; _g_boolean_var_379; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "caja_file_can_get_permissions (file)");
return (0); } } while (0)
;
5459
5460 return file->details->permissions;
5461}
5462
5463/**
5464 * caja_file_set_permissions:
5465 *
5466 * Change a file's permissions. This should only be called if
5467 * caja_file_can_set_permissions returned TRUE.
5468 *
5469 * @file: CajaFile representing the file in question.
5470 * @new_permissions: New permissions value. This is the whole
5471 * set of permissions, not a delta.
5472 **/
5473void
5474caja_file_set_permissions (CajaFile *file,
5475 guint32 new_permissions,
5476 CajaFileOperationCallback callback,
5477 gpointer callback_data)
5478{
5479 GFileInfo *info;
5480
5481 if (!caja_file_can_set_permissions (file)) {
5482 GError *error;
5483
5484 /* Claim that something changed even if the permission change failed.
5485 * This makes it easier for some clients who see the "reverting"
5486 * to the old permissions as "changing back".
5487 */
5488 caja_file_changed (file);
5489 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5490 _("Not allowed to set permissions")dcgettext (((void*)0), "Not allowed to set permissions", 5));
5491 (* callback) (file, NULL((void*)0), error, callback_data);
5492 g_error_free (error);
5493 return;
5494 }
5495
5496 /* Test the permissions-haven't-changed case explicitly
5497 * because we don't want to send the file-changed signal if
5498 * nothing changed.
5499 */
5500 if (new_permissions == file->details->permissions) {
5501 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5502 return;
5503 }
5504
5505 // Start UNDO-REDO
5506 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5507 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_SETPERMISSIONS, 1);
5508 caja_undostack_manager_data_set_file_permissions(undo_redo_data, caja_file_get_uri(file), file->details->permissions, new_permissions);
5509 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5510 undo_redo_data);
5511 }
5512 // End UNDO-REDO
5513
5514 info = g_file_info_new ();
5515 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode", new_permissions);
5516 caja_file_set_attributes (file, info, callback, callback_data);
5517 g_object_unref (info);
5518}
5519
5520/**
5521 * caja_file_can_get_selinux_context:
5522 *
5523 * Check whether the selinux context for a file are determinable.
5524 * This might not be the case for files on non-UNIX file systems,
5525 * files without a context or systems that don't support selinux.
5526 *
5527 * @file: The file in question.
5528 *
5529 * Return value: TRUE if the permissions are valid.
5530 */
5531gboolean
5532caja_file_can_get_selinux_context (CajaFile *file)
5533{
5534 return file->details->selinux_context != NULL((void*)0);
5535}
5536
5537
5538/**
5539 * caja_file_get_selinux_context:
5540 *
5541 * Get a user-displayable string representing a file's selinux
5542 * context
5543 * @file: CajaFile representing the file in question.
5544 *
5545 * Returns: Newly allocated string ready to display to the user.
5546 *
5547 **/
5548char *
5549caja_file_get_selinux_context (CajaFile *file)
5550{
5551 char *translated;
5552 char *raw;
5553
5554 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_380
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_380
= 1; else _g_boolean_var_380 = 0; _g_boolean_var_380; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
5555
5556 if (!caja_file_can_get_selinux_context (file)) {
5557 return NULL((void*)0);
5558 }
5559
5560 raw = file->details->selinux_context;
5561
5562#ifdef HAVE_SELINUX1
5563 if (selinux_raw_to_trans_context (raw, &translated) == 0) {
5564 char *tmp;
5565 tmp = g_strdup (translated)g_strdup_inline (translated);
5566 freecon (translated);
5567 translated = tmp;
5568 }
5569 else
5570#endif
5571 {
5572 translated = g_strdup (raw)g_strdup_inline (raw);
5573 }
5574
5575 return translated;
5576}
5577
5578static char *
5579get_real_name (const char *name, const char *gecos)
5580{
5581 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
5582
5583 if (gecos == NULL((void*)0)) {
5584 return NULL((void*)0);
5585 }
5586
5587 locale_string = eel_str_strip_substring_and_after (gecos, ",");
5588 if (!g_utf8_validate (locale_string, -1, NULL((void*)0))) {
5589 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5590 g_free (locale_string);
5591 } else {
5592 part_before_comma = locale_string;
5593 }
5594
5595 if (!g_utf8_validate (name, -1, NULL((void*)0))) {
5596 locale_string = g_locale_to_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5597 } else {
5598 locale_string = g_strdup (name)g_strdup_inline (name);
5599 }
5600
5601 capitalized_login_name = eel_str_capitalize (locale_string);
5602 g_free (locale_string);
5603
5604 if (capitalized_login_name == NULL((void*)0)) {
5605 real_name = part_before_comma;
5606 } else {
5607 real_name = eel_str_replace_substring
5608 (part_before_comma, "&", capitalized_login_name);
5609 g_free (part_before_comma);
5610 }
5611
5612
5613 if (eel_str_is_empty (real_name)
5614 || eel_strcmp (name, real_name) == 0
5615 || eel_strcmp (capitalized_login_name, real_name) == 0) {
5616 g_free (real_name);
5617 real_name = NULL((void*)0);
5618 }
5619
5620 g_free (capitalized_login_name);
5621
5622 return real_name;
5623}
5624
5625static gboolean
5626get_group_id_from_group_name (const char *group_name, uid_t *gid)
5627{
5628 struct group *group;
5629
5630 g_assert (gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_381
; if (gid != ((void*)0)) _g_boolean_var_381 = 1; else _g_boolean_var_381
= 0; _g_boolean_var_381; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5630, ((const char*) (__func__
)), "gid != NULL"); } while (0)
;
5631
5632 group = getgrnam (group_name);
5633
5634 if (group == NULL((void*)0)) {
5635 return FALSE(0);
5636 }
5637
5638 *gid = group->gr_gid;
5639
5640 return TRUE(!(0));
5641}
5642
5643static gboolean
5644get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid)
5645{
5646 struct passwd *password_info;
5647
5648 g_assert (uid != NULL || gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_382
; if (uid != ((void*)0) || gid != ((void*)0)) _g_boolean_var_382
= 1; else _g_boolean_var_382 = 0; _g_boolean_var_382; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5648, ((const char*) (__func__)), "uid != NULL || gid != NULL"
); } while (0)
;
5649
5650 password_info = getpwnam (user_name);
5651
5652 if (password_info == NULL((void*)0)) {
5653 return FALSE(0);
5654 }
5655
5656 if (uid != NULL((void*)0)) {
5657 *uid = password_info->pw_uid;
5658 }
5659
5660 if (gid != NULL((void*)0)) {
5661 *gid = password_info->pw_gid;
5662 }
5663
5664 return TRUE(!(0));
5665}
5666
5667static gboolean
5668get_user_id_from_user_name (const char *user_name, uid_t *id)
5669{
5670 return get_ids_from_user_name (user_name, id, NULL((void*)0));
5671}
5672
5673static gboolean
5674get_id_from_digit_string (const char *digit_string, uid_t *id)
5675{
5676 long scanned_id;
5677 char c;
5678
5679 g_assert (id != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_383
; if (id != ((void*)0)) _g_boolean_var_383 = 1; else _g_boolean_var_383
= 0; _g_boolean_var_383; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5679, ((const char*) (__func__
)), "id != NULL"); } while (0)
;
5680
5681 /* Only accept string if it has one integer with nothing
5682 * afterwards.
5683 */
5684 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) {
5685 return FALSE(0);
5686 }
5687 *id = scanned_id;
5688 return TRUE(!(0));
5689}
5690
5691/**
5692 * caja_file_can_get_owner:
5693 *
5694 * Check whether the owner a file is determinable.
5695 * This might not be the case for files on non-UNIX file systems.
5696 *
5697 * @file: The file in question.
5698 *
5699 * Return value: TRUE if the owner is valid.
5700 */
5701gboolean
5702caja_file_can_get_owner (CajaFile *file)
5703{
5704 /* Before we have info on a file, the owner is unknown. */
5705 return file->details->uid != -1;
5706}
5707
5708/**
5709 * caja_file_get_owner_name:
5710 *
5711 * Get the user name of the file's owner. If the owner has no
5712 * name, returns the userid as a string. The caller is responsible
5713 * for g_free-ing this string.
5714 *
5715 * @file: The file in question.
5716 *
5717 * Return value: A newly-allocated string.
5718 */
5719char *
5720caja_file_get_owner_name (CajaFile *file)
5721{
5722 return caja_file_get_owner_as_string (file, FALSE(0));
5723}
5724
5725/**
5726 * caja_file_can_set_owner:
5727 *
5728 * Check whether the current user is allowed to change
5729 * the owner of a file.
5730 *
5731 * @file: The file in question.
5732 *
5733 * Return value: TRUE if the current user can change the
5734 * owner of @file, FALSE otherwise. It's always possible
5735 * that when you actually try to do it, you will fail.
5736 */
5737gboolean
5738caja_file_can_set_owner (CajaFile *file)
5739{
5740 /* Not allowed to set the owner if we can't
5741 * even read it. This can happen on non-UNIX file
5742 * systems.
5743 */
5744 if (!caja_file_can_get_owner (file)) {
5745 return FALSE(0);
5746 }
5747
5748 /* Only root is also allowed to set the owner. */
5749 return geteuid() == 0;
5750}
5751
5752/**
5753 * caja_file_set_owner:
5754 *
5755 * Set the owner of a file. This will only have any effect if
5756 * caja_file_can_set_owner returns TRUE.
5757 *
5758 * @file: The file in question.
5759 * @user_name_or_id: The user name to set the owner to.
5760 * If the string does not match any user name, and the
5761 * string is an integer, the owner will be set to the
5762 * userid represented by that integer.
5763 * @callback: Function called when asynch owner change succeeds or fails.
5764 * @callback_data: Parameter passed back with callback function.
5765 */
5766void
5767caja_file_set_owner (CajaFile *file,
5768 const char *user_name_or_id,
5769 CajaFileOperationCallback callback,
5770 gpointer callback_data)
5771{
5772 GError *error;
5773 GFileInfo *info;
5774 uid_t new_id;
5775
5776 if (!caja_file_can_set_owner (file)) {
5777 /* Claim that something changed even if the permission
5778 * change failed. This makes it easier for some
5779 * clients who see the "reverting" to the old owner as
5780 * "changing back".
5781 */
5782 caja_file_changed (file);
5783 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5784 _("Not allowed to set owner")dcgettext (((void*)0), "Not allowed to set owner", 5));
5785 (* callback) (file, NULL((void*)0), error, callback_data);
5786 g_error_free (error);
5787 return;
5788 }
5789
5790 /* If no match treating user_name_or_id as name, try treating
5791 * it as id.
5792 */
5793 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
5794 && !get_id_from_digit_string (user_name_or_id, &new_id)) {
5795 /* Claim that something changed even if the permission
5796 * change failed. This makes it easier for some
5797 * clients who see the "reverting" to the old owner as
5798 * "changing back".
5799 */
5800 caja_file_changed (file);
5801 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
5802 _("Specified owner '%s' doesn't exist")dcgettext (((void*)0), "Specified owner '%s' doesn't exist", 5
)
, user_name_or_id);
5803 (* callback) (file, NULL((void*)0), error, callback_data);
5804 g_error_free (error);
5805 return;
5806 }
5807
5808 /* Test the owner-hasn't-changed case explicitly because we
5809 * don't want to send the file-changed signal if nothing
5810 * changed.
5811 */
5812 if (new_id == (uid_t) file->details->uid) {
5813 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5814 return;
5815 }
5816
5817 // Start UNDO-REDO
5818 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5819 char* current_owner = caja_file_get_owner_as_string (file, FALSE(0));
5820 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEOWNER, 1);
5821 caja_undostack_manager_data_set_owner_change_information(undo_redo_data, caja_file_get_uri(file), current_owner, user_name_or_id);
5822 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5823 undo_redo_data);
5824 g_free(current_owner);
5825 }
5826 // End UNDO-REDO
5827
5828 info = g_file_info_new ();
5829 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid", new_id);
5830 caja_file_set_attributes (file, info, callback, callback_data);
5831 g_object_unref (info);
5832}
5833
5834/**
5835 * caja_get_user_names:
5836 *
5837 * Get a list of user names. For users with a different associated
5838 * "real name", the real name follows the standard user name, separated
5839 * by a carriage return. The caller is responsible for freeing this list
5840 * and its contents.
5841 */
5842GList *
5843caja_get_user_names (void)
5844{
5845 GList *list;
5846 char *name;
5847 struct passwd *user;
5848
5849 list = NULL((void*)0);
5850
5851 setpwent ();
5852
5853 while ((user = getpwent ()) != NULL((void*)0)) {
5854 char *real_name;
5855
5856 real_name = get_real_name (user->pw_name, user->pw_gecos);
5857 if (real_name != NULL((void*)0)) {
5858 name = g_strconcat (user->pw_name, "\n", real_name, NULL((void*)0));
5859 } else {
5860 name = g_strdup (user->pw_name)g_strdup_inline (user->pw_name);
5861 }
5862 g_free (real_name);
5863 list = g_list_prepend (list, name);
5864 }
5865
5866 endpwent ();
5867
5868 return eel_g_str_list_alphabetize (list);
5869}
5870
5871/**
5872 * caja_file_can_get_group:
5873 *
5874 * Check whether the group a file is determinable.
5875 * This might not be the case for files on non-UNIX file systems.
5876 *
5877 * @file: The file in question.
5878 *
5879 * Return value: TRUE if the group is valid.
5880 */
5881gboolean
5882caja_file_can_get_group (CajaFile *file)
5883{
5884 /* Before we have info on a file, the group is unknown. */
5885 return file->details->gid != -1;
5886}
5887
5888/**
5889 * caja_file_get_group_name:
5890 *
5891 * Get the name of the file's group. If the group has no
5892 * name, returns the groupid as a string. The caller is responsible
5893 * for g_free-ing this string.
5894 *
5895 * @file: The file in question.
5896 *
5897 * Return value: A newly-allocated string.
5898 **/
5899char *
5900caja_file_get_group_name (CajaFile *file)
5901{
5902 return g_strdup (file->details->group)g_strdup_inline (file->details->group);
5903}
5904
5905/**
5906 * caja_file_can_set_group:
5907 *
5908 * Check whether the current user is allowed to change
5909 * the group of a file.
5910 *
5911 * @file: The file in question.
5912 *
5913 * Return value: TRUE if the current user can change the
5914 * group of @file, FALSE otherwise. It's always possible
5915 * that when you actually try to do it, you will fail.
5916 */
5917gboolean
5918caja_file_can_set_group (CajaFile *file)
5919{
5920 uid_t user_id;
5921
5922 /* Not allowed to set the permissions if we can't
5923 * even read them. This can happen on non-UNIX file
5924 * systems.
5925 */
5926 if (!caja_file_can_get_group (file)) {
5927 return FALSE(0);
5928 }
5929
5930 /* Check the user. */
5931 user_id = geteuid();
5932
5933 /* Owner is allowed to set group (with restrictions). */
5934 if (user_id == (uid_t) file->details->uid) {
5935 return TRUE(!(0));
5936 }
5937
5938 /* Root is also allowed to set group. */
5939 if (user_id == 0) {
5940 return TRUE(!(0));
5941 }
5942
5943 /* Nobody else is allowed. */
5944 return FALSE(0);
5945}
5946
5947/* Get a list of group names, filtered to only the ones
5948 * that contain the given username. If the username is
5949 * NULL, returns a list of all group names.
5950 */
5951static GList *
5952caja_get_group_names_for_user (void)
5953{
5954 GList *list;
5955 int count, i;
5956 gid_t gid_list[NGROUPS_MAX65536 + 1];
5957 struct group *group = NULL((void*)0);
5958
5959
5960 list = NULL((void*)0);
5961
5962 count = getgroups (NGROUPS_MAX65536 + 1, gid_list);
5963 for (i = 0; i < count; i++) {
5964 group = getgrgid (gid_list[i]);
5965 if (group == NULL((void*)0))
5966 break;
5967
5968 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5969 }
5970
5971 return eel_g_str_list_alphabetize (list);
5972}
5973
5974/**
5975 * caja_get_group_names:
5976 *
5977 * Get a list of all group names.
5978 */
5979GList *
5980caja_get_all_group_names (void)
5981{
5982 GList *list;
5983 struct group *group;
5984
5985 list = NULL((void*)0);
5986
5987 setgrent ();
5988
5989 while ((group = getgrent ()) != NULL((void*)0))
5990 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5991
5992 endgrent ();
5993
5994 return eel_g_str_list_alphabetize (list);
5995}
5996
5997/**
5998 * caja_file_get_settable_group_names:
5999 *
6000 * Get a list of all group names that the current user
6001 * can set the group of a specific file to.
6002 *
6003 * @file: The CajaFile in question.
6004 */
6005GList *
6006caja_file_get_settable_group_names (CajaFile *file)
6007{
6008 uid_t user_id;
6009 GList *result;
6010
6011 if (!caja_file_can_set_group (file)) {
6012 return NULL((void*)0);
6013 }
6014
6015 /* Check the user. */
6016 user_id = geteuid();
6017
6018 if (user_id == 0) {
6019 /* Root is allowed to set group to anything. */
6020 result = caja_get_all_group_names ();
6021 } else if (user_id == (uid_t) file->details->uid) {
6022 /* Owner is allowed to set group to any that owner is member of. */
6023 result = caja_get_group_names_for_user ();
6024 } else {
6025 g_warning ("unhandled case in caja_get_settable_group_names");
6026 result = NULL((void*)0);
6027 }
6028
6029 return result;
6030}
6031
6032/**
6033 * caja_file_set_group:
6034 *
6035 * Set the group of a file. This will only have any effect if
6036 * caja_file_can_set_group returns TRUE.
6037 *
6038 * @file: The file in question.
6039 * @group_name_or_id: The group name to set the owner to.
6040 * If the string does not match any group name, and the
6041 * string is an integer, the group will be set to the
6042 * group id represented by that integer.
6043 * @callback: Function called when asynch group change succeeds or fails.
6044 * @callback_data: Parameter passed back with callback function.
6045 */
6046void
6047caja_file_set_group (CajaFile *file,
6048 const char *group_name_or_id,
6049 CajaFileOperationCallback callback,
6050 gpointer callback_data)
6051{
6052 GError *error;
6053 GFileInfo *info;
6054 uid_t new_id;
6055
6056 if (!caja_file_can_set_group (file)) {
6057 /* Claim that something changed even if the group
6058 * change failed. This makes it easier for some
6059 * clients who see the "reverting" to the old group as
6060 * "changing back".
6061 */
6062 caja_file_changed (file);
6063 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
6064 _("Not allowed to set group")dcgettext (((void*)0), "Not allowed to set group", 5));
6065 (* callback) (file, NULL((void*)0), error, callback_data);
6066 g_error_free (error);
6067 return;
6068 }
6069
6070 /* If no match treating group_name_or_id as name, try treating
6071 * it as id.
6072 */
6073 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6074 && !get_id_from_digit_string (group_name_or_id, &new_id)) {
6075 /* Claim that something changed even if the group
6076 * change failed. This makes it easier for some
6077 * clients who see the "reverting" to the old group as
6078 * "changing back".
6079 */
6080 caja_file_changed (file);
6081 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
6082 _("Specified group '%s' doesn't exist")dcgettext (((void*)0), "Specified group '%s' doesn't exist", 5
)
, group_name_or_id);
6083 (* callback) (file, NULL((void*)0), error, callback_data);
6084 g_error_free (error);
6085 return;
6086 }
6087
6088 if (new_id == (gid_t) file->details->gid) {
6089 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
6090 return;
6091 }
6092
6093 // Start UNDO-REDO
6094 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6095 char* current_group = caja_file_get_group_name (file);
6096 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEGROUP, 1);
6097 caja_undostack_manager_data_set_group_change_information(undo_redo_data, caja_file_get_uri(file), current_group, group_name_or_id);
6098 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
6099 undo_redo_data);
6100 g_free(current_group);
6101 }
6102 // End UNDO-REDO
6103
6104 info = g_file_info_new ();
6105 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid", new_id);
6106 caja_file_set_attributes (file, info, callback, callback_data);
6107 g_object_unref (info);
6108}
6109
6110/**
6111 * caja_file_get_octal_permissions_as_string:
6112 *
6113 * Get a user-displayable string representing a file's permissions
6114 * as an octal number. The caller
6115 * is responsible for g_free-ing this string.
6116 * @file: CajaFile representing the file in question.
6117 *
6118 * Returns: Newly allocated string ready to display to the user.
6119 *
6120 **/
6121static char *
6122caja_file_get_octal_permissions_as_string (CajaFile *file)
6123{
6124 guint32 permissions;
6125
6126 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_384
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_384
= 1; else _g_boolean_var_384 = 0; _g_boolean_var_384; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6126, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6127
6128 if (!caja_file_can_get_permissions (file)) {
6129 return NULL((void*)0);
6130 }
6131
6132 permissions = file->details->permissions;
6133 return g_strdup_printf ("%03o", permissions);
6134}
6135
6136/**
6137 * caja_file_get_permissions_as_string:
6138 *
6139 * Get a user-displayable string representing a file's permissions. The caller
6140 * is responsible for g_free-ing this string.
6141 * @file: CajaFile representing the file in question.
6142 *
6143 * Returns: Newly allocated string ready to display to the user.
6144 *
6145 **/
6146static char *
6147caja_file_get_permissions_as_string (CajaFile *file)
6148{
6149 guint32 permissions;
6150 gboolean is_directory;
6151 gboolean is_link;
6152 gboolean suid, sgid, sticky;
6153
6154 if (!caja_file_can_get_permissions (file)) {
6155 return NULL((void*)0);
6156 }
6157
6158 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_385
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_385
= 1; else _g_boolean_var_385 = 0; _g_boolean_var_385; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6158, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6159
6160 permissions = file->details->permissions;
6161 is_directory = caja_file_is_directory (file);
6162 is_link = caja_file_is_symbolic_link (file);
6163
6164 /* We use ls conventions for displaying these three obscure flags */
6165 suid = permissions & S_ISUID04000;
6166 sgid = permissions & S_ISGID02000;
6167 sticky = permissions & S_ISVTX01000;
6168
6169 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6170 is_link ? 'l' : is_directory ? 'd' : '-',
6171 permissions & S_IRUSR0400 ? 'r' : '-',
6172 permissions & S_IWUSR0200 ? 'w' : '-',
6173 permissions & S_IXUSR0100
6174 ? (suid ? 's' : 'x')
6175 : (suid ? 'S' : '-'),
6176 permissions & S_IRGRP(0400 >> 3) ? 'r' : '-',
6177 permissions & S_IWGRP(0200 >> 3) ? 'w' : '-',
6178 permissions & S_IXGRP(0100 >> 3)
6179 ? (sgid ? 's' : 'x')
6180 : (sgid ? 'S' : '-'),
6181 permissions & S_IROTH((0400 >> 3) >> 3) ? 'r' : '-',
6182 permissions & S_IWOTH((0200 >> 3) >> 3) ? 'w' : '-',
6183 permissions & S_IXOTH((0100 >> 3) >> 3)
6184 ? (sticky ? 't' : 'x')
6185 : (sticky ? 'T' : '-'));
6186}
6187
6188/**
6189 * caja_file_get_owner_as_string:
6190 *
6191 * Get a user-displayable string representing a file's owner. The caller
6192 * is responsible for g_free-ing this string.
6193 * @file: CajaFile representing the file in question.
6194 * @include_real_name: Whether or not to append the real name (if any)
6195 * for this user after the user name.
6196 *
6197 * Returns: Newly allocated string ready to display to the user.
6198 *
6199 **/
6200static char *
6201caja_file_get_owner_as_string (CajaFile *file, gboolean include_real_name)
6202{
6203 char *user_name;
6204
6205 /* Before we have info on a file, the owner is unknown. */
6206 if (file->details->owner == NULL((void*)0) &&
6207 file->details->owner_real == NULL((void*)0)) {
6208 return NULL((void*)0);
6209 }
6210
6211 if (file->details->owner_real == NULL((void*)0)) {
6212 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6213 } else if (file->details->owner == NULL((void*)0)) {
6214 user_name = g_strdup (file->details->owner_real)g_strdup_inline (file->details->owner_real);
6215 } else if (include_real_name &&
6216 strcmp (file->details->owner, file->details->owner_real) != 0) {
6217 user_name = g_strdup_printf ("%s - %s",
6218 file->details->owner,
6219 file->details->owner_real);
6220 } else {
6221 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6222 }
6223
6224 return user_name;
6225}
6226
6227static char *
6228format_item_count_for_display (guint item_count,
6229 gboolean includes_directories,
6230 gboolean includes_files)
6231{
6232 g_assert (includes_directories || includes_files)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_386
; if (includes_directories || includes_files) _g_boolean_var_386
= 1; else _g_boolean_var_386 = 0; _g_boolean_var_386; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6232, ((const char*) (__func__)), "includes_directories || includes_files"
); } while (0)
;
6233
6234 return g_strdup_printf (includes_directories
6235 ? (includes_files
6236 ? ngettext ("%'u item", "%'u items", item_count)dcngettext (((void*)0), "%'u item", "%'u items", item_count, 5
)
6237 : ngettext ("%'u folder", "%'u folders", item_count)dcngettext (((void*)0), "%'u folder", "%'u folders", item_count
, 5)
)
6238 : ngettext ("%'u file", "%'u files", item_count)dcngettext (((void*)0), "%'u file", "%'u files", item_count, 5
)
, item_count);
6239}
6240
6241/**
6242 * caja_file_get_size_as_string:
6243 *
6244 * Get a user-displayable string representing a file size. The caller
6245 * is responsible for g_free-ing this string. The string is an item
6246 * count for directories.
6247 * @file: CajaFile representing the file in question.
6248 * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
6249 *
6250 * Returns: Newly allocated string ready to display to the user.
6251 *
6252 **/
6253static char *
6254caja_file_get_size_as_string (CajaFile *file,
6255 gboolean size_on_disk)
6256{
6257 guint item_count;
6258 gboolean count_unreadable;
6259 goffset size;
6260
6261 if (file == NULL((void*)0)) {
6262 return NULL((void*)0);
6263 }
6264
6265 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_387
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_387
= 1; else _g_boolean_var_387 = 0; _g_boolean_var_387; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6265, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6266
6267 if (caja_file_is_directory (file)) {
6268 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6269 return NULL((void*)0);
6270 }
6271 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6272 }
6273
6274 if (size_on_disk) {
6275 size = file->details->size_on_disk;
6276 } else {
6277 size = file->details->size;
6278 }
6279
6280 if (size == -1) {
6281 return NULL((void*)0);
6282 }
6283
6284 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6285 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6286 else
6287 return g_format_size (size);
6288}
6289
6290/**
6291 * caja_file_get_size_as_string_with_real_size:
6292 *
6293 * Get a user-displayable string representing a file size. The caller
6294 * is responsible for g_free-ing this string. The string is an item
6295 * count for directories.
6296 * This function adds the real size in the string.
6297 * @file: CajaFile representing the file in question.
6298 *
6299 * Returns: Newly allocated string ready to display to the user.
6300 *
6301 **/
6302static char *
6303caja_file_get_size_as_string_with_real_size (CajaFile *file,
6304 gboolean size_on_disk)
6305{
6306 guint item_count;
6307 gboolean count_unreadable;
6308 goffset size;
6309 char * formatted;
6310 char * formatted_plus_real;
6311 char * real_size;
6312
6313 if (file == NULL((void*)0)) {
6314 return NULL((void*)0);
6315 }
6316
6317 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_388
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_388
= 1; else _g_boolean_var_388 = 0; _g_boolean_var_388; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6317, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6318
6319 if (caja_file_is_directory (file)) {
6320 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6321 return NULL((void*)0);
6322 }
6323 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6324 }
6325
6326 if (size_on_disk) {
6327 size = file->details->size_on_disk;
6328 } else {
6329 size = file->details->size;
6330 }
6331
6332 if (size == -1) {
6333 return NULL((void*)0);
6334 }
6335
6336 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6337 formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6338 else
6339 formatted = g_format_size(size);
6340
6341 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
6342 real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT)dcgettext (((void*)0), "%""lu", 5), (guint64) size);
6343 formatted_plus_real = g_strdup_printf (_("%s (%s bytes)")dcgettext (((void*)0), "%s (%s bytes)", 5), formatted, real_size);
6344 g_free (real_size);
6345 g_free (formatted);
6346 return formatted_plus_real;
6347}
6348
6349static char *
6350caja_file_get_deep_count_as_string_internal (CajaFile *file,
6351 gboolean report_size,
6352 gboolean report_size_on_disk,
6353 gboolean report_directory_count,
6354 gboolean report_file_count)
6355{
6356 CajaRequestStatus status;
6357 guint directory_count;
6358 guint file_count;
6359 guint unreadable_count;
6360 guint total_count;
6361 goffset total_size;
6362 goffset total_size_on_disk;
6363
6364 /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
6365 g_assert (!(report_size && report_size_on_disk))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_389
; if (!(report_size && report_size_on_disk)) _g_boolean_var_389
= 1; else _g_boolean_var_389 = 0; _g_boolean_var_389; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6365, ((const char*) (__func__)), "!(report_size && report_size_on_disk)"
); } while (0)
;
6366 g_assert (!(report_size && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_390
; if (!(report_size && (report_directory_count || report_file_count
))) _g_boolean_var_390 = 1; else _g_boolean_var_390 = 0; _g_boolean_var_390
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6366, ((const char*) (__func__)), "!(report_size && (report_directory_count || report_file_count))"
); } while (0)
;
6367 g_assert (!(report_size_on_disk && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_391
; if (!(report_size_on_disk && (report_directory_count
|| report_file_count))) _g_boolean_var_391 = 1; else _g_boolean_var_391
= 0; _g_boolean_var_391; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6367, ((const char*) (__func__
)), "!(report_size_on_disk && (report_directory_count || report_file_count))"
); } while (0)
;
6368
6369 /* Must ask for something */
6370 g_assert (report_size || report_size_on_disk || report_directory_count || report_file_count)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_392
; if (report_size || report_size_on_disk || report_directory_count
|| report_file_count) _g_boolean_var_392 = 1; else _g_boolean_var_392
= 0; _g_boolean_var_392; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6370, ((const char*) (__func__
)), "report_size || report_size_on_disk || report_directory_count || report_file_count"
); } while (0)
;
6371
6372 if (file == NULL((void*)0)) {
6373 return NULL((void*)0);
6374 }
6375
6376 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_393
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_393
= 1; else _g_boolean_var_393 = 0; _g_boolean_var_393; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6376, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6377 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_394
; if (caja_file_is_directory (file)) _g_boolean_var_394 = 1; else
_g_boolean_var_394 = 0; _g_boolean_var_394; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6377, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
6378
6379 status = caja_file_get_deep_counts (file,
6380 &directory_count,
6381 &file_count,
6382 &unreadable_count,
6383 &total_size,
6384 &total_size_on_disk,
6385 FALSE(0));
6386
6387 /* Check whether any info is available. */
6388 if (status == CAJA_REQUEST_NOT_STARTED) {
6389 return NULL((void*)0);
6390 }
6391
6392 total_count = file_count + directory_count;
6393
6394 if (total_count == 0) {
6395 switch (status) {
6396 case CAJA_REQUEST_IN_PROGRESS:
6397 /* Don't return confident "zero" until we're finished looking,
6398 * because of next case.
6399 */
6400 return NULL((void*)0);
6401 case CAJA_REQUEST_DONE:
6402 /* Don't return "zero" if we there were contents but we couldn't read them. */
6403 if (unreadable_count != 0) {
6404 return NULL((void*)0);
6405 }
6406 default: break;
6407 }
6408 }
6409
6410 /* Note that we don't distinguish the "everything was readable" case
6411 * from the "some things but not everything was readable" case here.
6412 * Callers can distinguish them using caja_file_get_deep_counts
6413 * directly if desired.
6414 */
6415 if (report_size)
6416 {
6417 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6418 return g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
6419 else
6420 return g_format_size(total_size);
6421 }
6422
6423 if (report_size_on_disk)
6424 {
6425 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6426 return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
6427 else
6428 return g_format_size (total_size_on_disk);
6429 }
6430
6431 return format_item_count_for_display (report_directory_count
6432 ? (report_file_count ? total_count : directory_count)
6433 : file_count,
6434 report_directory_count, report_file_count);
6435}
6436
6437/**
6438 * caja_file_get_deep_size_as_string:
6439 *
6440 * Get a user-displayable string representing the size of all contained
6441 * items (only makes sense for directories). The caller
6442 * is responsible for g_free-ing this string.
6443 * @file: CajaFile representing the file in question.
6444 * @size_on_disk: if TRUE will return the size on disk, else return size of file.
6445 *
6446 * Returns: Newly allocated string ready to display to the user.
6447 *
6448 **/
6449static char *
6450caja_file_get_deep_size_as_string (CajaFile *file, gboolean size_on_disk)
6451{
6452 if (size_on_disk) {
6453 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), TRUE(!(0)), FALSE(0), FALSE(0));
6454 } else {
6455 return caja_file_get_deep_count_as_string_internal (file, TRUE(!(0)), FALSE(0), FALSE(0), FALSE(0));
6456 }
6457}
6458
6459/**
6460 * caja_file_get_deep_total_count_as_string:
6461 *
6462 * Get a user-displayable string representing the count of all contained
6463 * items (only makes sense for directories). The caller
6464 * is responsible for g_free-ing this string.
6465 * @file: CajaFile representing the file in question.
6466 *
6467 * Returns: Newly allocated string ready to display to the user.
6468 *
6469 **/
6470static char *
6471caja_file_get_deep_total_count_as_string (CajaFile *file)
6472{
6473 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), TRUE(!(0)));
6474}
6475
6476/**
6477 * caja_file_get_deep_file_count_as_string:
6478 *
6479 * Get a user-displayable string representing the count of all contained
6480 * items, not including directories. It only makes sense to call this
6481 * function on a directory. The caller
6482 * is responsible for g_free-ing this string.
6483 * @file: CajaFile representing the file in question.
6484 *
6485 * Returns: Newly allocated string ready to display to the user.
6486 *
6487 **/
6488static char *
6489caja_file_get_deep_file_count_as_string (CajaFile *file)
6490{
6491 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), FALSE(0), TRUE(!(0)));
6492}
6493
6494/**
6495 * caja_file_get_deep_directory_count_as_string:
6496 *
6497 * Get a user-displayable string representing the count of all contained
6498 * directories. It only makes sense to call this
6499 * function on a directory. The caller
6500 * is responsible for g_free-ing this string.
6501 * @file: CajaFile representing the file in question.
6502 *
6503 * Returns: Newly allocated string ready to display to the user.
6504 *
6505 **/
6506static char *
6507caja_file_get_deep_directory_count_as_string (CajaFile *file)
6508{
6509 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), FALSE(0));
6510}
6511
6512/**
6513 * caja_file_get_string_attribute:
6514 *
6515 * Get a user-displayable string from a named attribute. Use g_free to
6516 * free this string. If the value is unknown, returns NULL. You can call
6517 * caja_file_get_string_attribute_with_default if you want a non-NULL
6518 * default.
6519 *
6520 * @file: CajaFile representing the file in question.
6521 * @attribute_name: The name of the desired attribute. The currently supported
6522 * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
6523 * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
6524 * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
6525 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
6526 *
6527 * Returns: Newly allocated string ready to display to the user, or NULL
6528 * if the value is unknown or @attribute_name is not supported.
6529 *
6530 **/
6531char *
6532caja_file_get_string_attribute_q (CajaFile *file, GQuark attribute_q)
6533{
6534 char *extension_attribute;
6535
6536 if (attribute_q == attribute_name_q) {
6537 return caja_file_get_display_name (file);
6538 }
6539 if (attribute_q == attribute_type_q) {
6540 return caja_file_get_type_as_string (file);
6541 }
6542 if (attribute_q == attribute_mime_type_q) {
6543 return caja_file_get_mime_type (file);
6544 }
6545 if (attribute_q == attribute_size_q) {
6546 return caja_file_get_size_as_string (file, FALSE(0));
6547 }
6548 if (attribute_q == attribute_size_on_disk_q) {
6549 return caja_file_get_size_as_string (file, TRUE(!(0)));
6550 }
6551 if (attribute_q == attribute_size_detail_q) {
6552 return caja_file_get_size_as_string_with_real_size (file, FALSE(0));
6553 }
6554 if (attribute_q == attribute_size_on_disk_detail_q) {
6555 return caja_file_get_size_as_string_with_real_size (file, TRUE(!(0)));
6556 }
6557 if (attribute_q == attribute_deep_size_q) {
6558 return caja_file_get_deep_size_as_string (file, FALSE(0));
6559 }
6560 if (attribute_q == attribute_deep_size_on_disk_q) {
6561 return caja_file_get_deep_size_as_string (file, TRUE(!(0)));
6562 }
6563 if (attribute_q == attribute_deep_file_count_q) {
6564 return caja_file_get_deep_file_count_as_string (file);
6565 }
6566 if (attribute_q == attribute_deep_directory_count_q) {
6567 return caja_file_get_deep_directory_count_as_string (file);
6568 }
6569 if (attribute_q == attribute_deep_total_count_q) {
6570 return caja_file_get_deep_total_count_as_string (file);
6571 }
6572 if (attribute_q == attribute_trash_orig_path_q) {
6573 return caja_file_get_trash_original_file_parent_as_string (file);
6574 }
6575 if (attribute_q == attribute_date_modified_q) {
6576 return caja_file_get_date_as_string (file,
6577 CAJA_DATE_TYPE_MODIFIED);
6578 }
6579 if (attribute_q == attribute_date_changed_q) {
6580 return caja_file_get_date_as_string (file,
6581 CAJA_DATE_TYPE_CHANGED);
6582 }
6583 if (attribute_q == attribute_date_accessed_q) {
6584 return caja_file_get_date_as_string (file,
6585 CAJA_DATE_TYPE_ACCESSED);
6586 }
6587 if (attribute_q == attribute_date_created_q) {
6588 return caja_file_get_date_as_string (file,
6589 CAJA_DATE_TYPE_CREATED);
6590 }
6591 if (attribute_q == attribute_trashed_on_q) {
6592 return caja_file_get_date_as_string (file,
6593 CAJA_DATE_TYPE_TRASHED);
6594 }
6595 if (attribute_q == attribute_date_permissions_q) {
6596 return caja_file_get_date_as_string (file,
6597 CAJA_DATE_TYPE_PERMISSIONS_CHANGED);
6598 }
6599 if (attribute_q == attribute_extension_q) {
6600 return caja_file_get_extension_as_string (file);
6601 }
6602 if (attribute_q == attribute_permissions_q) {
6603 return caja_file_get_permissions_as_string (file);
6604 }
6605 if (attribute_q == attribute_selinux_context_q) {
6606 return caja_file_get_selinux_context (file);
6607 }
6608 if (attribute_q == attribute_octal_permissions_q) {
6609 return caja_file_get_octal_permissions_as_string (file);
6610 }
6611 if (attribute_q == attribute_owner_q) {
6612 return caja_file_get_owner_as_string (file, TRUE(!(0)));
6613 }
6614 if (attribute_q == attribute_group_q) {
6615 return caja_file_get_group_name (file);
6616 }
6617 if (attribute_q == attribute_uri_q) {
6618 return caja_file_get_uri (file);
6619 }
6620 if (attribute_q == attribute_where_q) {
6621 return caja_file_get_where_string (file);
6622 }
6623 if (attribute_q == attribute_link_target_q) {
6624 return caja_file_get_symbolic_link_target_path (file);
6625 }
6626 if (attribute_q == attribute_volume_q) {
6627 return caja_file_get_volume_name (file);
6628 }
6629 if (attribute_q == attribute_free_space_q) {
6630 return caja_file_get_volume_free_space (file);
6631 }
6632
6633 extension_attribute = NULL((void*)0);
6634
6635 if (file->details->pending_extension_attributes) {
6636 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
6637 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6638 }
6639
6640 if (extension_attribute == NULL((void*)0) && file->details->extension_attributes) {
6641 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
6642 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6643 }
6644
6645 return g_strdup (extension_attribute)g_strdup_inline (extension_attribute);
6646}
6647
6648char *
6649caja_file_get_string_attribute (CajaFile *file, const char *attribute_name)
6650{
6651 return caja_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
6652}
6653
6654
6655/**
6656 * caja_file_get_string_attribute_with_default:
6657 *
6658 * Get a user-displayable string from a named attribute. Use g_free to
6659 * free this string. If the value is unknown, returns a string representing
6660 * the unknown value, which varies with attribute. You can call
6661 * caja_file_get_string_attribute if you want NULL instead of a default
6662 * result.
6663 *
6664 * @file: CajaFile representing the file in question.
6665 * @attribute_name: The name of the desired attribute. See the description of
6666 * caja_file_get_string for the set of available attributes.
6667 *
6668 * Returns: Newly allocated string ready to display to the user, or a string
6669 * such as "unknown" if the value is unknown or @attribute_name is not supported.
6670 *
6671 **/
6672char *
6673caja_file_get_string_attribute_with_default_q (CajaFile *file, GQuark attribute_q)
6674{
6675 char *result;
6676 guint item_count;
6677 gboolean count_unreadable;
6678 CajaRequestStatus status;
6679
6680 result = caja_file_get_string_attribute_q (file, attribute_q);
6681 if (result != NULL((void*)0)) {
6682 return result;
6683 }
6684
6685 /* Supply default values for the ones we know about. */
6686 /* FIXME bugzilla.gnome.org 40646:
6687 * Use hash table and switch statement or function pointers for speed?
6688 */
6689 if (attribute_q == attribute_size_q) {
6690 if (!caja_file_should_show_directory_item_count (file)) {
6691 return g_strdup ("--")g_strdup_inline ("--");
6692 }
6693 count_unreadable = FALSE(0);
6694 if (caja_file_is_directory (file)) {
6695 caja_file_get_directory_item_count (file, &item_count, &count_unreadable);
6696 }
6697 return g_strdup (count_unreadable ? _("? items") : "...")g_strdup_inline (count_unreadable ? dcgettext (((void*)0), "? items"
, 5) : "...")
;
6698 }
6699 if (attribute_q == attribute_deep_size_q) {
6700 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6701 if (status == CAJA_REQUEST_DONE) {
6702 /* This means no contents at all were readable */
6703 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6704 }
6705 return g_strdup ("...")g_strdup_inline ("...");
6706 }
6707 if (attribute_q == attribute_deep_size_on_disk_q) {
6708 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6709 if (status == CAJA_REQUEST_DONE) {
6710 /* This means no contents at all were readable */
6711 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6712 }
6713 return g_strdup ("...")g_strdup_inline ("...");
6714 }
6715 if (attribute_q == attribute_deep_file_count_q
6716 || attribute_q == attribute_deep_directory_count_q
6717 || attribute_q == attribute_deep_total_count_q) {
6718 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6719 if (status == CAJA_REQUEST_DONE) {
6720 /* This means no contents at all were readable */
6721 return g_strdup (_("? items"))g_strdup_inline (dcgettext (((void*)0), "? items", 5));
6722 }
6723 return g_strdup ("...")g_strdup_inline ("...");
6724 }
6725 if (attribute_q == attribute_type_q) {
6726 return g_strdup (_("unknown type"))g_strdup_inline (dcgettext (((void*)0), "unknown type", 5));
6727 }
6728 if (attribute_q == attribute_mime_type_q) {
6729 return g_strdup (_("unknown MIME type"))g_strdup_inline (dcgettext (((void*)0), "unknown MIME type", 5
))
;
6730 }
6731 if (attribute_q == attribute_trashed_on_q) {
6732 /* If n/a */
6733 return g_strdup ("")g_strdup_inline ("");
6734 }
6735 if (attribute_q == attribute_trash_orig_path_q) {
6736 /* If n/a */
6737 return g_strdup ("")g_strdup_inline ("");
6738 }
6739
6740 /* Fallback, use for both unknown attributes and attributes
6741 * for which we have no more appropriate default.
6742 */
6743 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
6744}
6745
6746char *
6747caja_file_get_string_attribute_with_default (CajaFile *file, const char *attribute_name)
6748{
6749 return caja_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
6750}
6751
6752gboolean
6753caja_file_is_date_sort_attribute_q (GQuark attribute_q)
6754{
6755 if (attribute_q == attribute_modification_date_q ||
6756 attribute_q == attribute_date_modified_q ||
6757 attribute_q == attribute_creation_date_q ||
6758 attribute_q == attribute_date_created_q ||
6759 attribute_q == attribute_accessed_date_q ||
6760 attribute_q == attribute_date_accessed_q ||
6761 attribute_q == attribute_date_changed_q ||
6762 attribute_q == attribute_trashed_on_q ||
6763 attribute_q == attribute_date_permissions_q) {
6764 return TRUE(!(0));
6765 }
6766
6767 return FALSE(0);
6768}
6769
6770/**
6771 * get_description:
6772 *
6773 * Get a user-displayable string representing a file type. The caller
6774 * is responsible for g_free-ing this string.
6775 * @file: CajaFile representing the file in question.
6776 *
6777 * Returns: Newly allocated string ready to display to the user.
6778 *
6779 **/
6780static char *
6781get_description (CajaFile *file)
6782{
6783 const char *mime_type;
6784 char *description;
6785
6786 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_395
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_395
= 1; else _g_boolean_var_395 = 0; _g_boolean_var_395; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6786, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6787
6788 mime_type = file->details->mime_type;
6789 if (eel_str_is_empty (mime_type)) {
6790 return NULL((void*)0);
6791 }
6792
6793 if (g_content_type_is_unknown (mime_type) &&
6794 caja_file_is_executable (file)) {
6795 return g_strdup (_("program"))g_strdup_inline (dcgettext (((void*)0), "program", 5));
6796 }
6797
6798 description = g_content_type_get_description (mime_type);
6799 if (!eel_str_is_empty (description)) {
6800 return description;
6801 }
6802
6803 return g_strdup (mime_type)g_strdup_inline (mime_type);
6804}
6805
6806/* Takes ownership of string */
6807static char *
6808update_description_for_link (CajaFile *file, char *string)
6809{
6810 if (caja_file_is_symbolic_link (file)) {
6811 char *res;
6812
6813 g_assert (!caja_file_is_broken_symbolic_link (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_396
; if (!caja_file_is_broken_symbolic_link (file)) _g_boolean_var_396
= 1; else _g_boolean_var_396 = 0; _g_boolean_var_396; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6813, ((const char*) (__func__)), "!caja_file_is_broken_symbolic_link (file)"
); } while (0)
;
6814 if (string == NULL((void*)0)) {
6815 return g_strdup (_("link"))g_strdup_inline (dcgettext (((void*)0), "link", 5));
6816 }
6817 /* Note to localizers: convert file type string for file
6818 * (e.g. "folder", "plain text") to file type for symbolic link
6819 * to that kind of file (e.g. "link to folder").
6820 */
6821 res = g_strdup_printf (_("Link to %s")dcgettext (((void*)0), "Link to %s", 5), string);
6822 g_free (string);
6823 return res;
6824 }
6825
6826 return string;
6827}
6828
6829static char *
6830caja_file_get_type_as_string (CajaFile *file)
6831{
6832 if (file == NULL((void*)0)) {
6833 return NULL((void*)0);
6834 }
6835
6836 if (caja_file_is_broken_symbolic_link (file)) {
6837 return g_strdup (_("link (broken)"))g_strdup_inline (dcgettext (((void*)0), "link (broken)", 5));
6838 }
6839
6840 return update_description_for_link (file, get_description (file));
6841}
6842
6843/**
6844 * caja_file_get_file_type
6845 *
6846 * Return this file's type.
6847 * @file: CajaFile representing the file in question.
6848 *
6849 * Returns: The type.
6850 *
6851 **/
6852GFileType
6853caja_file_get_file_type (CajaFile *file)
6854{
6855 if (file == NULL((void*)0)) {
6856 return G_FILE_TYPE_UNKNOWN;
6857 }
6858
6859 return file->details->type;
6860}
6861
6862/**
6863 * caja_file_get_mime_type
6864 *
6865 * Return this file's default mime type.
6866 * @file: CajaFile representing the file in question.
6867 *
6868 * Returns: The mime type.
6869 *
6870 **/
6871char *
6872caja_file_get_mime_type (CajaFile *file)
6873{
6874 if (file != NULL((void*)0)) {
6875 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_397
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_397
= 1; else _g_boolean_var_397 = 0; _g_boolean_var_397; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6876 if (file->details->mime_type != NULL((void*)0)) {
6877 return g_strdup (file->details->mime_type)g_strdup_inline (file->details->mime_type);
6878 }
6879 }
6880 return g_strdup ("application/octet-stream")g_strdup_inline ("application/octet-stream");
6881}
6882
6883/**
6884 * caja_file_is_mime_type
6885 *
6886 * Check whether a file is of a particular MIME type, or inherited
6887 * from it.
6888 * @file: CajaFile representing the file in question.
6889 * @mime_type: The MIME-type string to test (e.g. "text/plain")
6890 *
6891 * Return value: TRUE if @mime_type exactly matches the
6892 * file's MIME type.
6893 *
6894 **/
6895gboolean
6896caja_file_is_mime_type (CajaFile *file, const char *mime_type)
6897{
6898 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_398
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_398
= 1; else _g_boolean_var_398 = 0; _g_boolean_var_398; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
6899 g_return_val_if_fail (mime_type != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_399
; if (mime_type != ((void*)0)) _g_boolean_var_399 = 1; else _g_boolean_var_399
= 0; _g_boolean_var_399; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "mime_type != NULL"
); return ((0)); } } while (0)
;
6900
6901 if (file->details->mime_type == NULL((void*)0)) {
6902 return FALSE(0);
6903 }
6904 return g_content_type_is_a (file->details->mime_type,
6905 mime_type);
6906}
6907
6908gboolean
6909caja_file_is_launchable (CajaFile *file)
6910{
6911 gboolean type_can_be_executable;
6912
6913 type_can_be_executable = FALSE(0);
6914 if (file->details->mime_type != NULL((void*)0)) {
6915 type_can_be_executable =
6916 g_content_type_can_be_executable (file->details->mime_type);
6917 }
6918
6919 return type_can_be_executable &&
6920 caja_file_can_get_permissions (file) &&
6921 caja_file_can_execute (file) &&
6922 caja_file_is_executable (file) &&
6923 !caja_file_is_directory (file);
6924}
6925
6926
6927/**
6928 * caja_file_get_emblem_icons
6929 *
6930 * Return the list of names of emblems that this file should display,
6931 * in canonical order.
6932 * @file: CajaFile representing the file in question.
6933 *
6934 * Returns: A list of emblem names.
6935 *
6936 **/
6937GList *
6938caja_file_get_emblem_icons (CajaFile *file,
6939 char **exclude)
6940{
6941 GList *keywords, *l;
6942 GList *icons;
6943 char *icon_names[2];
6944 char *keyword;
6945 int i;
6946 GIcon *icon;
6947
6948 if (file == NULL((void*)0)) {
6949 return NULL((void*)0);
6950 }
6951
6952 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_400
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_400
= 1; else _g_boolean_var_400 = 0; _g_boolean_var_400; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6953
6954 keywords = caja_file_get_keywords (file);
6955 keywords = prepend_automatic_keywords (file, keywords);
6956
6957 icons = NULL((void*)0);
6958 for (l = keywords; l != NULL((void*)0); l = l->next) {
6959 keyword = l->data;
6960
6961#ifdef TRASH_IS_FAST_ENOUGH
6962 if (strcmp (keyword, CAJA_FILE_EMBLEM_NAME_TRASH"trash") == 0) {
6963 char *uri;
6964 gboolean file_is_trash;
6965 /* Leave out the trash emblem for the trash itself, since
6966 * putting a trash emblem on a trash icon is gilding the
6967 * lily.
6968 */
6969 uri = caja_file_get_uri (file);
6970 file_is_trash = strcmp (uri, EEL_TRASH_URI"trash:") == 0;
6971 g_free (uri);
6972 if (file_is_trash) {
6973 continue;
6974 }
6975 }
6976#endif
6977 if (exclude) {
6978 for (i = 0; exclude[i] != NULL((void*)0); i++) {
6979 if (strcmp (exclude[i], keyword) == 0) {
6980 continue;
6981 }
6982 }
6983 }
6984
6985
6986 icon_names[0] = g_strconcat ("emblem-", keyword, NULL((void*)0));
6987 icon_names[1] = keyword;
6988 icon = g_themed_icon_new_from_names (icon_names, 2);
6989 g_free (icon_names[0]);
6990
6991 icons = g_list_prepend (icons, icon);
6992 }
6993
6994 g_list_free_full (keywords, g_free);
6995
6996 return icons;
6997}
6998
6999GList *
7000caja_file_get_emblem_pixbufs (CajaFile *file,
7001 int size,
7002 gboolean force_size,
7003 char **exclude)
7004{
7005 GList *icons, *l;
7006 GList *pixbufs;
7007 GdkPixbuf *pixbuf;
7008 GIcon *icon = NULL((void*)0);
7009 CajaIconInfo *icon_info = NULL((void*)0);
7010
7011 icons = caja_file_get_emblem_icons (file, exclude);
7012 pixbufs = NULL((void*)0);
7013
7014 for (l = icons; l != NULL((void*)0); l = l->next) {
7015 icon = l->data;
7016
7017 icon_info = caja_icon_info_lookup (icon, size, 1);
7018 if (force_size) {
7019 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (icon_info, size);
7020 } else {
7021 pixbuf = caja_icon_info_get_pixbuf_nodefault (icon_info);
7022 }
7023
7024 if (pixbuf) {
7025 pixbufs = g_list_prepend (pixbufs, pixbuf);
7026 }
7027
7028
7029 g_object_unref (icon_info);
7030 g_object_unref (icon);
7031 }
7032 g_list_free (icons);
7033
7034 return g_list_reverse (pixbufs);
7035
7036
7037}
7038
7039static GList *
7040sort_keyword_list_and_remove_duplicates (GList *keywords)
7041{
7042 GList *p;
7043
7044 if (keywords != NULL((void*)0)) {
7045 GList *duplicate_link = NULL((void*)0);
7046
7047 keywords = eel_g_str_list_alphabetize (keywords);
7048
7049 p = keywords;
7050 while (p->next != NULL((void*)0)) {
7051 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) {
7052 duplicate_link = p->next;
7053 keywords = g_list_remove_link (keywords, duplicate_link);
7054 g_list_free_full (duplicate_link, g_free);
7055 } else {
7056 p = p->next;
7057 }
7058 }
7059 }
7060
7061 return keywords;
7062}
7063
7064/**
7065 * caja_file_get_keywords
7066 *
7067 * Return this file's keywords.
7068 * @file: CajaFile representing the file in question.
7069 *
7070 * Returns: A list of keywords.
7071 *
7072 **/
7073GList *
7074caja_file_get_keywords (CajaFile *file)
7075{
7076 GList *keywords;
7077
7078 if (file == NULL((void*)0)) {
7079 return NULL((void*)0);
7080 }
7081
7082 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_401
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_401
= 1; else _g_boolean_var_401 = 0; _g_boolean_var_401; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7083
7084 /* Put all the keywords into a list. */
7085 keywords = caja_file_get_metadata_list
7086 (file, CAJA_METADATA_KEY_EMBLEMS"emblems");
7087
7088 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7089 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7090
7091 return sort_keyword_list_and_remove_duplicates (keywords);
7092}
7093
7094/**
7095 * caja_file_set_keywords
7096 *
7097 * Change this file's keywords.
7098 * @file: CajaFile representing the file in question.
7099 * @keywords: New set of keywords (a GList of strings).
7100 *
7101 **/
7102void
7103caja_file_set_keywords (CajaFile *file, GList *keywords)
7104{
7105 GList *canonical_keywords;
7106
7107 /* Invalidate the emblem compare cache */
7108 g_free (file->details->compare_by_emblem_cache);
7109 file->details->compare_by_emblem_cache = NULL((void*)0);
7110
7111 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_402
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_402
= 1; else _g_boolean_var_402 = 0; _g_boolean_var_402; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7112
7113 canonical_keywords = sort_keyword_list_and_remove_duplicates
7114 (g_list_copy (keywords));
7115 caja_file_set_metadata_list
7116 (file, CAJA_METADATA_KEY_EMBLEMS"emblems", canonical_keywords);
7117 g_list_free (canonical_keywords);
7118}
7119
7120/**
7121 * caja_file_is_symbolic_link
7122 *
7123 * Check if this file is a symbolic link.
7124 * @file: CajaFile representing the file in question.
7125 *
7126 * Returns: True if the file is a symbolic link.
7127 *
7128 **/
7129gboolean
7130caja_file_is_symbolic_link (CajaFile *file)
7131{
7132 return file->details->is_symlink;
7133}
7134
7135gboolean
7136caja_file_is_mountpoint (CajaFile *file)
7137{
7138 return file->details->is_mountpoint;
7139}
7140
7141GMount *
7142caja_file_get_mount (CajaFile *file)
7143{
7144 if (file->details->mount) {
7145 return g_object_ref (file->details->mount)((__typeof__ (file->details->mount)) (g_object_ref) (file
->details->mount))
;
7146 }
7147 return NULL((void*)0);
7148}
7149
7150static void
7151file_mount_unmounted (GMount *mount,
7152 gpointer data)
7153{
7154 CajaFile *file;
7155
7156 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
7157
7158 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_MOUNT);
7159}
7160
7161void
7162caja_file_set_mount (CajaFile *file,
7163 GMount *mount)
7164{
7165 if (file->details->mount) {
7166 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
7167 g_object_unref (file->details->mount);
7168 file->details->mount = NULL((void*)0);
7169 }
7170
7171 if (mount) {
7172 file->details->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
7173 g_signal_connect (mount, "unmounted",g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
7174 G_CALLBACK (file_mount_unmounted), file)g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
;
7175 }
7176}
7177
7178/**
7179 * caja_file_is_broken_symbolic_link
7180 *
7181 * Check if this file is a symbolic link with a missing target.
7182 * @file: CajaFile representing the file in question.
7183 *
7184 * Returns: True if the file is a symbolic link with a missing target.
7185 *
7186 **/
7187gboolean
7188caja_file_is_broken_symbolic_link (CajaFile *file)
7189{
7190 if (file == NULL((void*)0)) {
7191 return FALSE(0);
7192 }
7193
7194 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_403
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_403
= 1; else _g_boolean_var_403 = 0; _g_boolean_var_403; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7195
7196 /* Non-broken symbolic links return the target's type for get_file_type. */
7197 return caja_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7198}
7199
7200static void
7201get_fs_free_cb (GObject *source_object,
7202 GAsyncResult *res,
7203 gpointer user_data)
7204{
7205 CajaDirectory *directory;
7206 guint64 free_space;
7207 GFileInfo *info;
7208
7209 directory = CAJA_DIRECTORY (user_data)((((CajaDirectory*) (void *) ((user_data)))));
7210
7211 free_space = (guint64)-1;
7212 info = g_file_query_filesystem_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
7213 res, NULL((void*)0));
7214 if (info) {
7215 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
7216 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
7217 }
7218 g_object_unref (info);
7219 }
7220
7221 if (directory->details->free_space != free_space) {
7222 CajaFile *file;
7223
7224 directory->details->free_space = free_space;
7225 file = caja_directory_get_existing_corresponding_file (directory);
7226 if (file) {
7227 caja_file_emit_changed (file);
7228 caja_file_unref (file);
7229 }
7230 }
7231 caja_directory_unref (directory);
7232}
7233
7234/**
7235 * caja_file_get_volume_free_space
7236 * Get a nicely formatted char with free space on the file's volume
7237 * @file: CajaFile representing the file in question.
7238 *
7239 * Returns: newly-allocated copy of file size in a formatted string
7240 */
7241char *
7242caja_file_get_volume_free_space (CajaFile *file)
7243{
7244 CajaDirectory *directory;
7245 char *res;
7246 time_t now;
7247
7248 directory = caja_directory_get_for_file (file);
7249
7250 now = time (NULL((void*)0));
7251 /* Update first time and then every 2 seconds */
7252 if (directory->details->free_space_read == 0 ||
7253 (now - directory->details->free_space_read) > 2) {
7254 GFile *location;
7255
7256 directory->details->free_space_read = now;
7257 location = caja_file_get_location (file);
7258 g_file_query_filesystem_info_async (location,
7259 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free",
7260 0, NULL((void*)0),
7261 get_fs_free_cb,
7262 directory); /* Inherits ref */
7263 g_object_unref (location);
7264 } else {
7265 caja_directory_unref (directory);
7266 }
7267
7268
7269 res = NULL((void*)0);
7270
7271 if (directory->details->free_space != (guint64) -1)
7272 {
7273 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
7274 res = g_format_size_full (directory->details->free_space, G_FORMAT_SIZE_IEC_UNITS);
7275 else
7276 res = g_format_size(directory->details->free_space);
7277 }
7278
7279 return res;
7280}
7281
7282/**
7283 * caja_file_get_volume_name
7284 * Get the path of the volume the file resides on
7285 * @file: CajaFile representing the file in question.
7286 *
7287 * Returns: newly-allocated copy of the volume name of the target file,
7288 * if the volume name isn't set, it returns the mount path of the volume
7289 */
7290char *
7291caja_file_get_volume_name (CajaFile *file)
7292{
7293 GFile *location;
7294 char *res;
7295 GMount *mount;
7296
7297 res = NULL((void*)0);
7298
7299 location = caja_file_get_location (file);
7300 mount = g_file_find_enclosing_mount (location, NULL((void*)0), NULL((void*)0));
7301 if (mount) {
7302 res = g_strdup (g_mount_get_name (mount))g_strdup_inline (g_mount_get_name (mount));
7303 g_object_unref (mount);
7304 }
7305 g_object_unref (location);
7306
7307 return res;
7308}
7309
7310/**
7311 * caja_file_get_symbolic_link_target_path
7312 *
7313 * Get the file path of the target of a symbolic link. It is an error
7314 * to call this function on a file that isn't a symbolic link.
7315 * @file: CajaFile representing the symbolic link in question.
7316 *
7317 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7318 */
7319char *
7320caja_file_get_symbolic_link_target_path (CajaFile *file)
7321{
7322 if (!caja_file_is_symbolic_link (file)) {
7323 g_warning ("File has symlink target, but is not marked as symlink");
7324 }
7325
7326 return g_strdup (file->details->symlink_name)g_strdup_inline (file->details->symlink_name);
7327}
7328
7329/**
7330 * caja_file_get_symbolic_link_target_uri
7331 *
7332 * Get the uri of the target of a symbolic link. It is an error
7333 * to call this function on a file that isn't a symbolic link.
7334 * @file: CajaFile representing the symbolic link in question.
7335 *
7336 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7337 */
7338char *
7339caja_file_get_symbolic_link_target_uri (CajaFile *file)
7340{
7341 if (!caja_file_is_symbolic_link (file)) {
7342 g_warning ("File has symlink target, but is not marked as symlink");
7343 }
7344
7345 if (file->details->symlink_name == NULL((void*)0)) {
7346 return NULL((void*)0);
7347 } else {
7348 GFile *location, *parent, *target;
7349 char *target_uri;
7350
7351 target = NULL((void*)0);
7352
7353 location = caja_file_get_location (file);
7354 parent = g_file_get_parent (location);
7355 g_object_unref (location);
7356 if (parent) {
7357 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7358 g_object_unref (parent);
7359 }
7360
7361 target_uri = NULL((void*)0);
7362 if (target) {
7363 target_uri = g_file_get_uri (target);
7364 g_object_unref (target);
7365 }
7366 return target_uri;
7367 }
7368}
7369
7370/**
7371 * caja_file_is_caja_link
7372 *
7373 * Check if this file is a "caja link", meaning a historical
7374 * caja xml link file or a desktop file.
7375 * @file: CajaFile representing the file in question.
7376 *
7377 * Returns: True if the file is a caja link.
7378 *
7379 **/
7380gboolean
7381caja_file_is_caja_link (CajaFile *file)
7382{
7383 if (file->details->mime_type == NULL((void*)0))
7384 {
7385 return FALSE(0);
7386 }
7387 return g_content_type_equals (file->details->mime_type,
7388 "application/x-desktop");
7389}
7390
7391/**
7392 * caja_file_is_directory
7393 *
7394 * Check if this file is a directory.
7395 * @file: CajaFile representing the file in question.
7396 *
7397 * Returns: TRUE if @file is a directory.
7398 *
7399 **/
7400gboolean
7401caja_file_is_directory (CajaFile *file)
7402{
7403 return caja_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
7404}
7405
7406/**
7407 * caja_file_is_user_special_directory
7408 *
7409 * Check if this file is a special platform directory.
7410 * @file: CajaFile representing the file in question.
7411 * @special_directory: GUserDirectory representing the type to test for
7412 *
7413 * Returns: TRUE if @file is a special directory of the given kind.
7414 */
7415gboolean
7416caja_file_is_user_special_directory (CajaFile *file,
7417 GUserDirectory special_directory)
7418{
7419 gboolean is_special_dir;
7420 const gchar *special_dir;
7421
7422 special_dir = g_get_user_special_dir (special_directory);
7423 is_special_dir = FALSE(0);
7424
7425 if (special_dir) {
7426 GFile *loc;
7427 GFile *special_gfile;
7428
7429 loc = caja_file_get_location (file);
7430 special_gfile = g_file_new_for_path (special_dir);
7431 is_special_dir = g_file_equal (loc, special_gfile);
7432 g_object_unref (special_gfile);
7433 g_object_unref (loc);
7434 }
7435
7436 return is_special_dir;
7437}
7438
7439gboolean
7440caja_file_is_archive (CajaFile *file)
7441{
7442 char *mime_type;
7443 int i;
7444 static const char * archive_mime_types[] = { "application/x-gtar",
7445 "application/x-zip",
7446 "application/x-zip-compressed",
7447 "application/zip",
7448 "application/x-zip",
7449 "application/x-tar",
7450 "application/x-7z-compressed",
7451 "application/x-rar",
7452 "application/x-rar-compressed",
7453 "application/x-jar",
7454 "application/x-java-archive",
7455 "application/x-war",
7456 "application/x-ear",
7457 "application/x-arj",
7458 "application/x-gzip",
7459 "application/x-bzip-compressed-tar",
7460 "application/x-compressed-tar" };
7461
7462 g_return_val_if_fail (file != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_404
; if (file != ((void*)0)) _g_boolean_var_404 = 1; else _g_boolean_var_404
= 0; _g_boolean_var_404; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file != NULL"); return
((0)); } } while (0)
;
7463
7464 mime_type = caja_file_get_mime_type (file);
7465 for (i = 0; i < G_N_ELEMENTS (archive_mime_types)(sizeof (archive_mime_types) / sizeof ((archive_mime_types)[0
]))
; i++) {
7466 if (!strcmp (mime_type, archive_mime_types[i])) {
7467 g_free (mime_type);
7468 return TRUE(!(0));
7469 }
7470 }
7471 g_free (mime_type);
7472
7473 return FALSE(0);
7474}
7475
7476
7477/**
7478 * caja_file_is_in_trash
7479 *
7480 * Check if this file is a file in trash.
7481 * @file: CajaFile representing the file in question.
7482 *
7483 * Returns: TRUE if @file is in a trash.
7484 *
7485 **/
7486gboolean
7487caja_file_is_in_trash (CajaFile *file)
7488{
7489 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_405
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_405
= 1; else _g_boolean_var_405 = 0; _g_boolean_var_405; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7489, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7490
7491 return caja_directory_is_in_trash (file->details->directory);
7492}
7493
7494GError *
7495caja_file_get_file_info_error (CajaFile *file)
7496{
7497 if (!file->details->get_info_failed) {
7498 return NULL((void*)0);
7499 }
7500
7501 return file->details->get_info_error;
7502}
7503
7504/**
7505 * caja_file_contains_text
7506 *
7507 * Check if this file contains text.
7508 * This is private and is used to decide whether or not to read the top left text.
7509 * @file: CajaFile representing the file in question.
7510 *
7511 * Returns: TRUE if @file has a text MIME type.
7512 *
7513 **/
7514gboolean
7515caja_file_contains_text (CajaFile *file)
7516{
7517 if (file == NULL((void*)0)) {
7518 return FALSE(0);
7519 }
7520
7521 /* All text files inherit from text/plain */
7522 return caja_file_is_mime_type (file, "text/plain");
7523}
7524
7525/**
7526 * caja_file_is_binary
7527 *
7528 * Check if this file is a binary file.
7529 * This is private and is used to decide whether or not to show the diff
7530 * button in the file conflict dialog.
7531 * @file: CajaFile representing the file in question.
7532 *
7533 * Returns: TRUE if @file is a binary file.
7534 *
7535 **/
7536gboolean
7537caja_file_is_binary (CajaFile *file)
7538{
7539 if (!caja_file_can_read(file))
7540 {
7541 return FALSE(0);
7542 }
7543
7544 gboolean is_binary = FALSE(0);
7545 int i = 0;
7546 FILE *fp;
7547
7548 /* Check the first 4096 bytes of the files. If these contains a 0,
7549 * we can assume the file is binary.
7550 * This idea is taken from python code of meld.
7551 */
7552
7553 fp = g_fopenfopen (g_file_get_path (caja_file_get_location (file)), "r");
7554 if (fp == NULL((void*)0))
7555 {
7556 return FALSE(0);
7557 }
7558
7559 while (!feof (fp)) {
7560 int c;
7561
7562 if (i > 4096) {
7563 break;
7564 }
7565 c = fgetc(fp);
7566 if (c == 0) {
7567 is_binary = TRUE(!(0));
7568 break;
7569 }
7570 i++;
7571 }
7572 fclose(fp);
7573
7574 return is_binary;
7575}
7576
7577/**
7578 * caja_file_is_executable
7579 *
7580 * Check if this file is executable at all.
7581 * @file: CajaFile representing the file in question.
7582 *
7583 * Returns: TRUE if any of the execute bits are set. FALSE if
7584 * not, or if the permissions are unknown.
7585 *
7586 **/
7587gboolean
7588caja_file_is_executable (CajaFile *file)
7589{
7590 if (!file->details->has_permissions) {
7591 /* File's permissions field is not valid.
7592 * Can't access specific permissions, so return FALSE.
7593 */
7594 return FALSE(0);
7595 }
7596
7597 return file->details->can_execute;
7598}
7599
7600/**
7601 * caja_file_peek_top_left_text
7602 *
7603 * Peek at the text from the top left of the file.
7604 * @file: CajaFile representing the file in question.
7605 *
7606 * Returns: NULL if there is no text readable, otherwise, the text.
7607 * This string is owned by the file object and should not
7608 * be kept around or freed.
7609 *
7610 **/
7611char *
7612caja_file_peek_top_left_text (CajaFile *file,
7613 gboolean need_large_text,
7614 gboolean *needs_loading)
7615{
7616 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_406
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_406
= 1; else _g_boolean_var_406 = 0; _g_boolean_var_406; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7617
7618 if (!caja_file_should_get_top_left_text (file)) {
7619 if (needs_loading) {
7620 *needs_loading = FALSE(0);
7621 }
7622 return NULL((void*)0);
7623 }
7624
7625 if (needs_loading) {
7626 *needs_loading = !file->details->top_left_text_is_up_to_date;
7627 if (need_large_text) {
7628 *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text;
7629 }
7630 }
7631
7632 /* Show " ..." in the file until we read the contents in. */
7633 if (!file->details->got_top_left_text) {
7634
7635 if (caja_file_contains_text (file)) {
7636 return " ...";
7637 }
7638 return NULL((void*)0);
7639 }
7640
7641 /* Show what we read in. */
7642 return file->details->top_left_text;
7643}
7644
7645/**
7646 * caja_file_get_top_left_text
7647 *
7648 * Get the text from the top left of the file.
7649 * @file: CajaFile representing the file in question.
7650 *
7651 * Returns: NULL if there is no text readable, otherwise, the text.
7652 *
7653 **/
7654char *
7655caja_file_get_top_left_text (CajaFile *file)
7656{
7657 return g_strdup (caja_file_peek_top_left_text (file, FALSE, NULL))g_strdup_inline (caja_file_peek_top_left_text (file, (0), ((void
*)0)))
;
7658}
7659
7660char *
7661caja_file_get_filesystem_id (CajaFile *file)
7662{
7663 return g_strdup (file->details->filesystem_id)g_strdup_inline (file->details->filesystem_id);
7664}
7665
7666CajaFile *
7667caja_file_get_trash_original_file (CajaFile *file)
7668{
7669 CajaFile *original_file;
7670
7671 original_file = NULL((void*)0);
7672
7673 if (file->details->trash_orig_path != NULL((void*)0)) {
7674 GFile *location;
7675
7676 location = g_file_new_for_path (file->details->trash_orig_path);
7677 original_file = caja_file_get (location);
7678 g_object_unref (location);
7679 }
7680
7681 return original_file;
7682
7683}
7684
7685void
7686caja_file_mark_gone (CajaFile *file)
7687{
7688 CajaDirectory *directory;
7689
7690 if (file->details->is_gone)
7691 return;
7692
7693 file->details->is_gone = TRUE(!(0));
7694
7695 update_links_if_target (file);
7696
7697 /* Drop it from the symlink hash ! */
7698 remove_from_link_hash_table (file);
7699
7700 /* Let the directory know it's gone. */
7701 directory = file->details->directory;
7702 if (!caja_file_is_self_owned (file)) {
7703 caja_directory_remove_file (directory, file);
7704 }
7705
7706 caja_file_clear_info (file);
7707
7708 /* FIXME bugzilla.gnome.org 42429:
7709 * Maybe we can get rid of the name too eventually, but
7710 * for now that would probably require too many if statements
7711 * everywhere anyone deals with the name. Maybe we can give it
7712 * a hard-coded "<deleted>" name or something.
7713 */
7714}
7715
7716/**
7717 * caja_file_changed
7718 *
7719 * Notify the user that this file has changed.
7720 * @file: CajaFile representing the file in question.
7721 **/
7722void
7723caja_file_changed (CajaFile *file)
7724{
7725 GList fake_list;
7726
7727 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_407
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_407
= 1; else _g_boolean_var_407 = 0; _g_boolean_var_407; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7728
7729 if (caja_file_is_self_owned (file)) {
7730 caja_file_emit_changed (file);
7731 } else {
7732 fake_list.data = file;
7733 fake_list.next = NULL((void*)0);
7734 fake_list.prev = NULL((void*)0);
7735 caja_directory_emit_change_signals
7736 (file->details->directory, &fake_list);
7737 }
7738}
7739
7740/**
7741 * caja_file_updated_deep_count_in_progress
7742 *
7743 * Notify clients that a newer deep count is available for
7744 * the directory in question.
7745 */
7746void
7747caja_file_updated_deep_count_in_progress (CajaFile *file) {
7748 GList *link_files, *node;
7749
7750 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_408
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_408
= 1; else _g_boolean_var_408 = 0; _g_boolean_var_408; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7750, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7751 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_409
; if (caja_file_is_directory (file)) _g_boolean_var_409 = 1; else
_g_boolean_var_409 = 0; _g_boolean_var_409; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 7751, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
7752
7753 /* Send out a signal. */
7754 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
7755
7756 /* Tell link files pointing to this object about the change. */
7757 link_files = get_link_files (file);
7758 for (node = link_files; node != NULL((void*)0); node = node->next) {
7759 caja_file_updated_deep_count_in_progress (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))));
7760 }
7761 caja_file_list_free (link_files);
7762}
7763
7764/**
7765 * caja_file_emit_changed
7766 *
7767 * Emit a file changed signal.
7768 * This can only be called by the directory, since the directory
7769 * also has to emit a files_changed signal.
7770 *
7771 * @file: CajaFile representing the file in question.
7772 **/
7773void
7774caja_file_emit_changed (CajaFile *file)
7775{
7776 GList *link_files, *p;
7777
7778 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_410
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_410
= 1; else _g_boolean_var_410 = 0; _g_boolean_var_410; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7778, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7779
7780
7781 /* Invalidate the emblem compare cache. -- This is not the cleanest
7782 * place to do it but it is the one guaranteed bottleneck through
7783 * which all change notifications pass.
7784 */
7785 g_free (file->details->compare_by_emblem_cache);
7786 file->details->compare_by_emblem_cache = NULL((void*)0);
7787
7788 /* Send out a signal. */
7789 g_signal_emit (file, signals[CHANGED], 0, file);
7790
7791 /* Tell link files pointing to this object about the change. */
7792 link_files = get_link_files (file);
7793 for (p = link_files; p != NULL((void*)0); p = p->next) {
7794 if (p->data != file) {
7795 caja_file_changed (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
7796 }
7797 }
7798 caja_file_list_free (link_files);
7799}
7800
7801/**
7802 * caja_file_is_gone
7803 *
7804 * Check if a file has already been deleted.
7805 * @file: CajaFile representing the file in question.
7806 *
7807 * Returns: TRUE if the file is already gone.
7808 **/
7809gboolean
7810caja_file_is_gone (CajaFile *file)
7811{
7812 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_411
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_411
= 1; else _g_boolean_var_411 = 0; _g_boolean_var_411; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7813
7814 return file->details->is_gone;
7815}
7816
7817/**
7818 * caja_file_is_not_yet_confirmed
7819 *
7820 * Check if we're in a state where we don't know if a file really
7821 * exists or not, before the initial I/O is complete.
7822 * @file: CajaFile representing the file in question.
7823 *
7824 * Returns: TRUE if the file is already gone.
7825 **/
7826gboolean
7827caja_file_is_not_yet_confirmed (CajaFile *file)
7828{
7829 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_412
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_412
= 1; else _g_boolean_var_412 = 0; _g_boolean_var_412; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7830
7831 return !file->details->got_file_info;
7832}
7833
7834/**
7835 * caja_file_check_if_ready
7836 *
7837 * Check whether the values for a set of file attributes are
7838 * currently available, without doing any additional work. This
7839 * is useful for callers that want to reflect updated information
7840 * when it is ready but don't want to force the work required to
7841 * obtain the information, which might be slow network calls, e.g.
7842 *
7843 * @file: The file being queried.
7844 * @file_attributes: A bit-mask with the desired information.
7845 *
7846 * Return value: TRUE if all of the specified attributes are currently readable.
7847 */
7848gboolean
7849caja_file_check_if_ready (CajaFile *file,
7850 CajaFileAttributes file_attributes)
7851{
7852 /* To be parallel with call_when_ready, return
7853 * TRUE for NULL file.
7854 */
7855 if (file == NULL((void*)0)) {
7856 return TRUE(!(0));
7857 }
7858
7859 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_413
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_413
= 1; else _g_boolean_var_413 = 0; _g_boolean_var_413; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7860
7861 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7862 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7863 check_if_ready, (file, file_attributes))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
;
7864}
7865
7866void
7867caja_file_call_when_ready (CajaFile *file,
7868 CajaFileAttributes file_attributes,
7869 CajaFileCallback callback,
7870 gpointer callback_data)
7871
7872{
7873 if (file == NULL((void*)0)) {
7874 (* callback) (file, callback_data);
7875 return;
7876 }
7877
7878 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_414
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_414
= 1; else _g_boolean_var_414 = 0; _g_boolean_var_414; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7879
7880 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7881 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7882 call_when_ready, (file, file_attributes,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7883 callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
;
7884}
7885
7886void
7887caja_file_cancel_call_when_ready (CajaFile *file,
7888 CajaFileCallback callback,
7889 gpointer callback_data)
7890{
7891 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_415
; if (callback != ((void*)0)) _g_boolean_var_415 = 1; else _g_boolean_var_415
= 0; _g_boolean_var_415; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
7892
7893 if (file == NULL((void*)0)) {
7894 return;
7895 }
7896
7897 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_416
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_416
= 1; else _g_boolean_var_416 = 0; _g_boolean_var_416; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7898
7899 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7900 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7901 cancel_call_when_ready, (file, callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
;
7902}
7903
7904static void
7905invalidate_directory_count (CajaFile *file)
7906{
7907 file->details->directory_count_is_up_to_date = FALSE(0);
7908}
7909
7910static void
7911invalidate_deep_counts (CajaFile *file)
7912{
7913 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
7914}
7915
7916static void
7917invalidate_mime_list (CajaFile *file)
7918{
7919 file->details->mime_list_is_up_to_date = FALSE(0);
7920}
7921
7922static void
7923invalidate_top_left_text (CajaFile *file)
7924{
7925 file->details->top_left_text_is_up_to_date = FALSE(0);
7926}
7927
7928static void
7929invalidate_file_info (CajaFile *file)
7930{
7931 file->details->file_info_is_up_to_date = FALSE(0);
7932}
7933
7934static void
7935invalidate_link_info (CajaFile *file)
7936{
7937 file->details->link_info_is_up_to_date = FALSE(0);
7938}
7939
7940static void
7941invalidate_thumbnail (CajaFile *file)
7942{
7943 file->details->thumbnail_is_up_to_date = FALSE(0);
7944}
7945
7946static void
7947invalidate_mount (CajaFile *file)
7948{
7949 file->details->mount_is_up_to_date = FALSE(0);
7950}
7951
7952void
7953caja_file_invalidate_extension_info_internal (CajaFile *file)
7954{
7955 if (file->details->pending_info_providers)
7956 g_list_free_full (file->details->pending_info_providers, g_object_unref);
7957
7958 file->details->pending_info_providers =
7959 caja_extensions_get_for_type (CAJA_TYPE_INFO_PROVIDER(caja_info_provider_get_type ()));
7960}
7961
7962void
7963caja_file_invalidate_attributes_internal (CajaFile *file,
7964 CajaFileAttributes file_attributes)
7965{
7966 Request request;
7967
7968 if (file == NULL((void*)0)) {
7969 return;
7970 }
7971
7972 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
7973 /* Desktop icon files are always up to date.
7974 * If we invalidate their attributes they
7975 * will lose data, so we just ignore them.
7976 */
7977 return;
7978 }
7979
7980 request = caja_directory_set_up_request (file_attributes);
7981
7982 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)((request) & (1<<(REQUEST_DIRECTORY_COUNT)))) {
7983 invalidate_directory_count (file);
7984 }
7985 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)((request) & (1<<(REQUEST_DEEP_COUNT)))) {
7986 invalidate_deep_counts (file);
7987 }
7988 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)((request) & (1<<(REQUEST_MIME_LIST)))) {
7989 invalidate_mime_list (file);
7990 }
7991 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)((request) & (1<<(REQUEST_FILE_INFO)))) {
7992 invalidate_file_info (file);
7993 }
7994 if (REQUEST_WANTS_TYPE (request, REQUEST_TOP_LEFT_TEXT)((request) & (1<<(REQUEST_TOP_LEFT_TEXT)))) {
7995 invalidate_top_left_text (file);
7996 }
7997 if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)((request) & (1<<(REQUEST_LINK_INFO)))) {
7998 invalidate_link_info (file);
7999 }
8000 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)((request) & (1<<(REQUEST_EXTENSION_INFO)))) {
8001 caja_file_invalidate_extension_info_internal (file);
8002 }
8003 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)((request) & (1<<(REQUEST_THUMBNAIL)))) {
8004 invalidate_thumbnail (file);
8005 }
8006 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)((request) & (1<<(REQUEST_MOUNT)))) {
8007 invalidate_mount (file);
8008 }
8009
8010 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
8011}
8012
8013gboolean
8014caja_file_has_open_window (CajaFile *file)
8015{
8016 return file->details->has_open_window;
8017}
8018
8019void
8020caja_file_set_has_open_window (CajaFile *file,
8021 gboolean has_open_window)
8022{
8023 has_open_window = (has_open_window != FALSE(0));
8024
8025 if (file->details->has_open_window != has_open_window) {
8026 file->details->has_open_window = has_open_window;
8027 caja_file_changed (file);
8028 }
8029}
8030
8031
8032gboolean
8033caja_file_is_thumbnailing (CajaFile *file)
8034{
8035 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_417
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_417
= 1; else _g_boolean_var_417 = 0; _g_boolean_var_417; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
8036
8037 return file->details->is_thumbnailing;
8038}
8039
8040void
8041caja_file_set_is_thumbnailing (CajaFile *file,
8042 gboolean is_thumbnailing)
8043{
8044 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_418
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_418
= 1; else _g_boolean_var_418 = 0; _g_boolean_var_418; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
8045
8046 file->details->is_thumbnailing = is_thumbnailing;
8047}
8048
8049
8050/**
8051 * caja_file_invalidate_attributes
8052 *
8053 * Invalidate the specified attributes and force a reload.
8054 * @file: CajaFile representing the file in question.
8055 * @file_attributes: attributes to froget.
8056 **/
8057
8058void
8059caja_file_invalidate_attributes (CajaFile *file,
8060 CajaFileAttributes file_attributes)
8061{
8062 /* Cancel possible in-progress loads of any of these attributes */
8063 caja_directory_cancel_loading_file_attributes (file->details->directory,
8064 file,
8065 file_attributes);
8066
8067 /* Actually invalidate the values */
8068 caja_file_invalidate_attributes_internal (file, file_attributes);
8069
8070 caja_directory_add_file_to_work_queue (file->details->directory, file);
8071
8072 /* Kick off I/O if necessary */
8073 caja_directory_async_state_changed (file->details->directory);
8074}
8075
8076CajaFileAttributes
8077caja_file_get_all_attributes (void)
8078{
8079 return CAJA_FILE_ATTRIBUTE_INFO |
8080 CAJA_FILE_ATTRIBUTE_LINK_INFO |
8081 CAJA_FILE_ATTRIBUTE_DEEP_COUNTS |
8082 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8083 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8084 CAJA_FILE_ATTRIBUTE_TOP_LEFT_TEXT |
8085 CAJA_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
8086 CAJA_FILE_ATTRIBUTE_EXTENSION_INFO |
8087 CAJA_FILE_ATTRIBUTE_THUMBNAIL |
8088 CAJA_FILE_ATTRIBUTE_MOUNT;
8089}
8090
8091void
8092caja_file_invalidate_all_attributes (CajaFile *file)
8093{
8094 CajaFileAttributes all_attributes;
8095
8096 all_attributes = caja_file_get_all_attributes ();
8097 caja_file_invalidate_attributes (file, all_attributes);
8098}
8099
8100
8101/**
8102 * caja_file_dump
8103 *
8104 * Debugging call, prints out the contents of the file
8105 * fields.
8106 *
8107 * @file: file to dump.
8108 **/
8109void
8110caja_file_dump (CajaFile *file)
8111{
8112 long size = file->details->deep_size;
8113 long size_on_disk = file->details->deep_size_on_disk;
8114 char *uri;
8115 const char *file_kind;
8116
8117 uri = caja_file_get_uri (file);
8118 g_print ("uri: %s \n", uri);
8119 if (!file->details->got_file_info) {
8120 g_print ("no file info \n");
8121 } else if (file->details->get_info_failed) {
8122 g_print ("failed to get file info \n");
8123 } else {
8124 g_print ("size: %ld \n", size);
8125 g_print ("disk size: %ld \n", size_on_disk);
8126 switch (file->details->type) {
8127 case G_FILE_TYPE_REGULAR:
8128 file_kind = "regular file";
8129 break;
8130 case G_FILE_TYPE_DIRECTORY:
8131 file_kind = "folder";
8132 break;
8133 case G_FILE_TYPE_SPECIAL:
8134 file_kind = "special";
8135 break;
8136 case G_FILE_TYPE_SYMBOLIC_LINK:
8137 file_kind = "symbolic link";
8138 break;
8139 case G_FILE_TYPE_UNKNOWN:
8140 default:
8141 file_kind = "unknown";
8142 break;
8143 }
8144 g_print ("kind: %s \n", file_kind);
8145 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) {
8146 g_print ("link to %s \n", file->details->symlink_name);
8147 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8148 }
8149 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8150 }
8151 g_free (uri);
8152}
8153
8154/**
8155 * caja_file_list_ref
8156 *
8157 * Ref all the files in a list.
8158 * @list: GList of files.
8159 **/
8160GList *
8161caja_file_list_ref (GList *list)
8162{
8163 g_list_foreach (list, (GFunc) caja_file_ref, NULL((void*)0));
8164 return list;
8165}
8166
8167/**
8168 * caja_file_list_unref
8169 *
8170 * Unref all the files in a list.
8171 * @list: GList of files.
8172 **/
8173void
8174caja_file_list_unref (GList *list)
8175{
8176 g_list_foreach (list, (GFunc) caja_file_unref, NULL((void*)0));
8177}
8178
8179/**
8180 * caja_file_list_free
8181 *
8182 * Free a list of files after unrefing them.
8183 * @list: GList of files.
8184 **/
8185void
8186caja_file_list_free (GList *list)
8187{
8188 caja_file_list_unref (list);
8189 g_list_free (list);
8190}
8191
8192/**
8193 * caja_file_list_copy
8194 *
8195 * Copy the list of files, making a new ref of each,
8196 * @list: GList of files.
8197 **/
8198GList *
8199caja_file_list_copy (GList *list)
8200{
8201 return g_list_copy (caja_file_list_ref (list));
8202}
8203
8204static gboolean
8205get_attributes_for_default_sort_type (CajaFile *file,
8206 gboolean *is_download,
8207 gboolean *is_trash)
8208{
8209 gboolean is_download_dir, is_desktop_dir, is_trash_dir, retval;
8210
8211 *is_download = FALSE(0);
8212 *is_trash = FALSE(0);
8213 retval = FALSE(0);
8214
8215 /* special handling for certain directories */
8216 if (file && caja_file_is_directory (file)) {
8217 is_download_dir =
8218 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8219 is_desktop_dir =
8220 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP);
8221 is_trash_dir =
8222 caja_file_is_in_trash (file);
8223
8224 if (is_download_dir && !is_desktop_dir) {
8225 *is_download = TRUE(!(0));
8226 retval = TRUE(!(0));
8227 } else if (is_trash_dir) {
8228 *is_trash = TRUE(!(0));
8229 retval = TRUE(!(0));
8230 }
8231 }
8232
8233 return retval;
8234}
8235
8236CajaFileSortType
8237caja_file_get_default_sort_type (CajaFile *file,
8238 gboolean *reversed)
8239{
8240 CajaFileSortType retval;
8241 gboolean is_download, is_trash, res;
8242
8243 retval = CAJA_FILE_SORT_NONE;
8244 is_download = is_trash = FALSE(0);
8245 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8246
8247 if (res) {
8248 if (is_download) {
8249 retval = CAJA_FILE_SORT_BY_MTIME;
8250 } else if (is_trash) {
8251 retval = CAJA_FILE_SORT_BY_TRASHED_TIME;
8252 }
8253
8254 if (reversed != NULL((void*)0)) {
8255 *reversed = res;
8256 }
8257 }
8258
8259 return retval;
8260}
8261
8262const gchar *
8263caja_file_get_default_sort_attribute (CajaFile *file,
8264 gboolean *reversed)
8265{
8266 const gchar *retval;
8267 gboolean is_download, is_trash, res;
8268
8269 retval = NULL((void*)0);
8270 is_download = is_trash = FALSE(0);
8271 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8272
8273 if (res) {
8274 if (is_download) {
8275 retval = g_quark_to_string (attribute_date_modified_q);
8276 } else if (is_trash) {
8277 retval = g_quark_to_string (attribute_trashed_on_q);
8278 }
8279
8280 if (reversed != NULL((void*)0)) {
8281 *reversed = res;
8282 }
8283 }
8284
8285 return retval;
8286}
8287
8288static int
8289compare_by_display_name_cover (gconstpointer a, gconstpointer b)
8290{
8291 return compare_by_display_name (CAJA_FILE (a)((((CajaFile*) (void *) ((a))))), CAJA_FILE (b)((((CajaFile*) (void *) ((b))))));
8292}
8293
8294/**
8295 * caja_file_list_sort_by_display_name
8296 *
8297 * Sort the list of files by file name.
8298 * @list: GList of files.
8299 **/
8300GList *
8301caja_file_list_sort_by_display_name (GList *list)
8302{
8303 return g_list_sort (list, compare_by_display_name_cover);
8304}
8305
8306static GList *ready_data_list = NULL((void*)0);
8307
8308typedef struct
8309{
8310 GList *file_list;
8311 GList *remaining_files;
8312 CajaFileListCallback callback;
8313 gpointer callback_data;
8314} FileListReadyData;
8315
8316static void
8317file_list_ready_data_free (FileListReadyData *data)
8318{
8319 GList *l;
8320
8321 l = g_list_find (ready_data_list, data);
8322 if (l != NULL((void*)0)) {
8323 ready_data_list = g_list_delete_link (ready_data_list, l);
8324
8325 caja_file_list_free (data->file_list);
8326 g_list_free (data->remaining_files);
8327 g_free (data);
8328 }
8329}
8330
8331static FileListReadyData *
8332file_list_ready_data_new (GList *file_list,
8333 CajaFileListCallback callback,
8334 gpointer callback_data)
8335{
8336 FileListReadyData *data;
8337
8338 data = g_new0 (FileListReadyData, 1)(FileListReadyData *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (FileListReadyData); 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; }))
;
8339 data->file_list = caja_file_list_copy (file_list);
8340 data->remaining_files = g_list_copy (file_list);
8341 data->callback = callback;
8342 data->callback_data = callback_data;
8343
8344 ready_data_list = g_list_prepend (ready_data_list, data);
8345
8346 return data;
8347}
8348
8349static void
8350file_list_file_ready_callback (CajaFile *file,
8351 gpointer user_data)
8352{
8353 FileListReadyData *data;
8354
8355 data = user_data;
8356 data->remaining_files = g_list_remove (data->remaining_files, file);
8357
8358 if (data->remaining_files == NULL((void*)0)) {
8359 if (data->callback) {
8360 (*data->callback) (data->file_list, data->callback_data);
8361 }
8362
8363 file_list_ready_data_free (data);
8364 }
8365}
8366
8367void
8368caja_file_list_call_when_ready (GList *file_list,
8369 CajaFileAttributes attributes,
8370 CajaFileListHandle **handle,
8371 CajaFileListCallback callback,
8372 gpointer callback_data)
8373{
8374 GList *l;
8375 FileListReadyData *data;
8376 CajaFile *file = NULL((void*)0);
8377
8378 g_return_if_fail (file_list != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_419
; if (file_list != ((void*)0)) _g_boolean_var_419 = 1; else _g_boolean_var_419
= 0; _g_boolean_var_419; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_list != NULL"
); return; } } while (0)
;
8379
8380 data = file_list_ready_data_new
8381 (file_list, callback, callback_data);
8382
8383 if (handle) {
8384 *handle = (CajaFileListHandle *) data;
8385 }
8386
8387
8388 l = file_list;
8389 while (l != NULL((void*)0)) {
8390 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8391 /* Need to do this here, as the list can be modified by this call */
8392 l = l->next;
8393
8394 if (file)
8395 caja_file_call_when_ready (file,
8396 attributes,
8397 file_list_file_ready_callback,
8398 data);
8399 }
8400}
8401
8402void
8403caja_file_list_cancel_call_when_ready (CajaFileListHandle *handle)
8404{
8405 GList *l;
8406 FileListReadyData *data;
8407
8408 g_return_if_fail (handle != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_420
; if (handle != ((void*)0)) _g_boolean_var_420 = 1; else _g_boolean_var_420
= 0; _g_boolean_var_420; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "handle != NULL")
; return; } } while (0)
;
8409
8410 data = (FileListReadyData *) handle;
8411
8412 l = g_list_find (ready_data_list, data);
8413 if (l != NULL((void*)0)) {
8414 CajaFile *file = NULL((void*)0);
8415
8416 for (l = data->remaining_files; l != NULL((void*)0); l = l->next) {
8417 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8418
8419 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8420 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8421 cancel_call_when_ready, (file, file_list_file_ready_callback, data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
;
8422 }
8423
8424 file_list_ready_data_free (data);
8425 }
8426}
8427
8428static char *
8429try_to_make_utf8 (const char *text, int *length)
8430{
8431 static const char *encodings_to_try[2];
8432 static int n_encodings_to_try = 0;
8433 gsize converted_length;
8434 GError *conversion_error;
8435 char *utf8_text;
8436 int i;
8437
8438 if (n_encodings_to_try == 0) {
8439 const char *charset;
8440 gboolean charset_is_utf8;
8441
8442 charset_is_utf8 = g_get_charset (&charset);
8443 if (!charset_is_utf8) {
8444 encodings_to_try[n_encodings_to_try++] = charset;
8445 }
8446
8447 if (g_ascii_strcasecmp (charset, "ISO-8859-1") != 0) {
8448 encodings_to_try[n_encodings_to_try++] = "ISO-8859-1";
8449 }
8450 }
8451
8452 utf8_text = NULL((void*)0);
8453 for (i = 0; i < n_encodings_to_try; i++) {
8454 conversion_error = NULL((void*)0);
8455 utf8_text = g_convert (text, *length,
8456 "UTF-8", encodings_to_try[i],
8457 NULL((void*)0), &converted_length, &conversion_error);
8458 if (utf8_text != NULL((void*)0)) {
8459 *length = converted_length;
8460 break;
8461 }
8462 g_error_free (conversion_error);
8463 }
8464
8465 return utf8_text;
8466}
8467
8468
8469
8470/* Extract the top left part of the read-in text. */
8471char *
8472caja_extract_top_left_text (const char *text,
8473 gboolean large,
8474 int length)
8475{
8476 GString* buffer;
8477 const gchar *in;
8478 const gchar *end;
8479 int line, i;
8480 gunichar c;
8481 char *text_copy;
8482 const char *utf8_end;
8483 gboolean validated;
8484 int max_bytes, max_lines, max_cols;
8485
8486 if (large) {
8487 max_bytes = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES10000;
8488 max_lines = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES24;
8489 max_cols = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE80;
8490 } else {
8491 max_bytes = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES1024;
8492 max_lines = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES5;
8493 max_cols = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE10;
8494 }
8495
8496
8497
8498 text_copy = NULL((void*)0);
8499 if (text != NULL((void*)0)) {
8500 /* Might be a partial utf8 character at the end if we didn't read whole file */
8501 validated = g_utf8_validate (text, length, &utf8_end);
8502 if (!validated &&
8503 !(length >= max_bytes &&
8504 text + length - utf8_end < 6)) {
8505 text_copy = try_to_make_utf8 (text, &length);
8506 text = text_copy;
8507 } else if (!validated) {
8508 length = utf8_end - text;
8509 }
8510 }
8511
8512 if (text == NULL((void*)0) || length == 0) {
8513 return NULL((void*)0);
8514 }
8515
8516 buffer = g_string_new ("");
8517 end = text + length; in = text;
8518
8519 for (line = 0; line < max_lines; line++) {
8520 /* Extract one line. */
8521 for (i = 0; i < max_cols; ) {
8522 if (*in == '\n') {
8523 break;
8524 }
8525
8526 c = g_utf8_get_char (in);
8527
8528 if (g_unichar_isprint (c)) {
8529 g_string_append_unichar (buffer, c);
8530 i++;
8531 }
8532
8533 in = g_utf8_next_char (in)(char *)((in) + g_utf8_skip[*(const guchar *)(in)]);
8534 if (in == end) {
8535 goto done;
8536 }
8537 }
8538
8539 /* Skip the rest of the line. */
8540 while (*in != '\n') {
8541 if (++in == end) {
8542 goto done;
8543 }
8544 }
8545 if (++in == end) {
8546 goto done;
8547 }
8548
8549 /* Put a new-line separator in. */
8550 g_string_append_c(buffer, '\n')g_string_append_c_inline (buffer, '\n');
8551 }
8552 done:
8553 g_free (text_copy);
8554
8555 return g_string_free(buffer, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((buffer
), ((0))) : g_string_free_and_steal (buffer)) : (g_string_free
) ((buffer), ((0))))
;
8556}
8557
8558static void
8559thumbnail_limit_changed_callback (gpointer user_data)
8560{
8561 g_settings_get (caja_preferences,
8562 CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT"thumbnail-limit",
8563 "t", &cached_thumbnail_limit);
8564
8565 /* Tell the world that icons might have changed. We could invent a narrower-scope
8566 * signal to mean only "thumbnails might have changed" if this ends up being slow
8567 * for some reason.
8568 */
8569 emit_change_signals_for_all_files_in_all_directories ();
8570}
8571
8572static void
8573thumbnail_size_changed_callback (gpointer user_data)
8574{
8575 cached_thumbnail_size = g_settings_get_int (caja_icon_view_preferences, CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE"thumbnail-size");
8576
8577 /* Tell the world that icons might have changed. We could invent a narrower-scope
8578 * signal to mean only "thumbnails might have changed" if this ends up being slow
8579 * for some reason.
8580 */
8581 emit_change_signals_for_all_files_in_all_directories ();
8582}
8583
8584static void
8585show_thumbnails_changed_callback (gpointer user_data)
8586{
8587 show_image_thumbs = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS"show-image-thumbnails");
8588
8589 /* Tell the world that icons might have changed. We could invent a narrower-scope
8590 * signal to mean only "thumbnails might have changed" if this ends up being slow
8591 * for some reason.
8592 */
8593 emit_change_signals_for_all_files_in_all_directories ();
8594}
8595
8596static void
8597mime_type_data_changed_callback (GObject *signaller, gpointer user_data)
8598{
8599 /* Tell the world that icons might have changed. We could invent a narrower-scope
8600 * signal to mean only "thumbnails might have changed" if this ends up being slow
8601 * for some reason.
8602 */
8603 emit_change_signals_for_all_files_in_all_directories ();
8604}
8605
8606static void
8607icon_theme_changed_callback (GtkIconTheme *icon_theme,
8608 gpointer user_data)
8609{
8610 /* Clear all pixmap caches as the icon => pixmap lookup changed */
8611 caja_icon_info_clear_caches ();
8612
8613 /* Tell the world that icons might have changed. We could invent a narrower-scope
8614 * signal to mean only "thumbnails might have changed" if this ends up being slow
8615 * for some reason.
8616 */
8617 emit_change_signals_for_all_files_in_all_directories ();
8618}
8619
8620static void
8621caja_file_class_init (CajaFileClass *class)
8622{
8623 GtkIconTheme *icon_theme;
8624
8625 caja_file_info_getter = caja_file_get_internal;
8626
8627 attribute_name_q = g_quark_from_static_string ("name");
8628 attribute_size_q = g_quark_from_static_string ("size");
8629 attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
8630 attribute_type_q = g_quark_from_static_string ("type");
8631 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
8632 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
8633 attribute_creation_date_q = g_quark_from_static_string ("creation_date");
8634 attribute_date_created_q = g_quark_from_static_string ("date_created");
8635 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
8636 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
8637 attribute_emblems_q = g_quark_from_static_string ("emblems");
8638 attribute_extension_q = g_quark_from_static_string ("extension");
8639 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
8640 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
8641 attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
8642 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
8643 attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
8644 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
8645 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
8646 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
8647 attribute_date_changed_q = g_quark_from_static_string ("date_changed");
8648 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
8649 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
8650 attribute_date_permissions_q = g_quark_from_static_string ("date_permissions");
8651 attribute_permissions_q = g_quark_from_static_string ("permissions");
8652 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
8653 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
8654 attribute_owner_q = g_quark_from_static_string ("owner");
8655 attribute_group_q = g_quark_from_static_string ("group");
8656 attribute_uri_q = g_quark_from_static_string ("uri");
8657 attribute_where_q = g_quark_from_static_string ("where");
8658 attribute_link_target_q = g_quark_from_static_string ("link_target");
8659 attribute_volume_q = g_quark_from_static_string ("volume");
8660 attribute_free_space_q = g_quark_from_static_string ("free_space");
8661
8662 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = finalize;
8663 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->constructor = caja_file_constructor;
8664
8665 signals[CHANGED] =
8666 g_signal_new ("changed",
8667 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8668 G_SIGNAL_RUN_LAST,
8669 G_STRUCT_OFFSET (CajaFileClass, changed)((glong) __builtin_offsetof(CajaFileClass, changed)),
8670 NULL((void*)0), NULL((void*)0),
8671 g_cclosure_marshal_VOID__VOID,
8672 G_TYPE_NONE((GType) ((1) << (2))), 0);
8673
8674 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
8675 g_signal_new ("updated_deep_count_in_progress",
8676 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8677 G_SIGNAL_RUN_LAST,
8678 G_STRUCT_OFFSET (CajaFileClass, updated_deep_count_in_progress)((glong) __builtin_offsetof(CajaFileClass, updated_deep_count_in_progress
))
,
8679 NULL((void*)0), NULL((void*)0),
8680 g_cclosure_marshal_VOID__VOID,
8681 G_TYPE_NONE((GType) ((1) << (2))), 0);
8682
8683 eel_g_settings_add_auto_enum (caja_preferences,
8684 CAJA_PREFERENCES_DATE_FORMAT"date-format",
8685 &date_format_pref);
8686
8687 thumbnail_limit_changed_callback (NULL((void*)0));
8688 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8689 "changed::" CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8690 G_CALLBACK (thumbnail_limit_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8691 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8692 thumbnail_size_changed_callback (NULL((void*)0));
8693 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8694 "changed::" CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8695 G_CALLBACK (thumbnail_size_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8696 NULL)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8697 show_thumbnails_changed_callback (NULL((void*)0));
8698 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8699 "changed::" CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8700 G_CALLBACK (show_thumbnails_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8701 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8702
8703 icon_theme = gtk_icon_theme_get_default ();
8704 g_signal_connect_object (icon_theme,
8705 "changed",
8706 G_CALLBACK (icon_theme_changed_callback)((GCallback) (icon_theme_changed_callback)),
8707 NULL((void*)0), 0);
8708
8709 g_signal_connect (caja_signaller_get_current (),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8710 "mime_data_changed",g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8711 G_CALLBACK (mime_type_data_changed_callback),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8712 NULL)g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
8713}
8714
8715static void
8716caja_file_add_emblem (CajaFile *file,
8717 const char *emblem_name)
8718{
8719 if (file->details->pending_info_providers) {
8720 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
8721 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8722 } else {
8723 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
8724 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8725 }
8726
8727 caja_file_changed (file);
8728}
8729
8730static void
8731caja_file_add_string_attribute (CajaFile *file,
8732 const char *attribute_name,
8733 const char *value)
8734{
8735 if (file->details->pending_info_providers) {
8736 /* Lazily create hashtable */
8737 if (!file->details->pending_extension_attributes) {
8738 file->details->pending_extension_attributes =
8739 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8740 NULL((void*)0),
8741 (GDestroyNotify)g_free);
8742 }
8743 g_hash_table_insert (file->details->pending_extension_attributes,
8744 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8745 g_strdup (value)g_strdup_inline (value));
8746 } else {
8747 if (!file->details->extension_attributes) {
8748 file->details->extension_attributes =
8749 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8750 NULL((void*)0),
8751 (GDestroyNotify)g_free);
8752 }
8753 g_hash_table_insert (file->details->extension_attributes,
8754 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8755 g_strdup (value)g_strdup_inline (value));
8756 }
8757
8758 caja_file_changed (file);
8759}
8760
8761static void
8762caja_file_invalidate_extension_info (CajaFile *file)
8763{
8764 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_EXTENSION_INFO);
8765}
8766
8767void
8768caja_file_info_providers_done (CajaFile *file)
8769{
8770 g_list_free_full (file->details->extension_emblems, g_free);
8771 file->details->extension_emblems = file->details->pending_extension_emblems;
8772 file->details->pending_extension_emblems = NULL((void*)0);
8773
8774 if (file->details->extension_attributes) {
8775 g_hash_table_destroy (file->details->extension_attributes);
8776 }
8777
8778 file->details->extension_attributes = file->details->pending_extension_attributes;
8779 file->details->pending_extension_attributes = NULL((void*)0);
8780
8781 caja_file_changed (file);
8782}
8783
8784static void
8785caja_file_info_iface_init (CajaFileInfoIface *iface)
8786{
8787 iface->is_gone = caja_file_is_gone;
8788 iface->get_name = caja_file_get_name;
8789 iface->get_file_type = caja_file_get_file_type;
8790 iface->get_location = caja_file_get_location;
8791 iface->get_uri = caja_file_get_uri;
8792 iface->get_parent_location = caja_file_get_parent_location;
8793 iface->get_parent_uri = caja_file_get_parent_uri;
8794 iface->get_parent_info = caja_file_get_parent;
8795 iface->get_mount = caja_file_get_mount;
8796 iface->get_uri_scheme = caja_file_get_uri_scheme;
8797 iface->get_activation_uri = caja_file_get_activation_uri;
8798 iface->get_mime_type = caja_file_get_mime_type;
8799 iface->is_mime_type = caja_file_is_mime_type;
8800 iface->is_directory = caja_file_is_directory;
8801 iface->can_write = caja_file_can_write;
8802 iface->add_emblem = caja_file_add_emblem;
8803 iface->get_string_attribute = caja_file_get_string_attribute;
8804 iface->add_string_attribute = caja_file_add_string_attribute;
8805 iface->invalidate_extension_info = caja_file_invalidate_extension_info;
8806}
8807
8808#if !defined (CAJA_OMIT_SELF_CHECK)
8809
8810void
8811caja_self_check_file (void)
8812{
8813 CajaFile *file_1;
8814 CajaFile *file_2;
8815 GList *list;
8816
8817 /* refcount checks */
8818
8819 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8819); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8820
8821 file_1 = caja_file_get_by_uri ("file:///home/");
8822
8823 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8823); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8824 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1->details->directory)))))->ref_count"
, "caja-file.c", 8824); eel_check_integer_result (((((GObject
*) (void *) ((file_1->details->directory)))))->ref_count
, 1); } while (0)
;
8825 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 1)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8825); eel_check_integer_result (caja_directory_number_outstanding
(), 1); } while (0)
;
8826
8827 caja_file_unref (file_1);
8828
8829 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8829); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8830
8831 file_1 = caja_file_get_by_uri ("file:///etc");
8832 file_2 = caja_file_get_by_uri ("file:///usr");
8833
8834 list = NULL((void*)0);
8835 list = g_list_prepend (list, file_1);
8836 list = g_list_prepend (list, file_2);
8837
8838 caja_file_list_ref (list);
8839
8840 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8840); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 2); } while (0)
;
8841 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8841); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 2); } while (0)
;
8842
8843 caja_file_list_unref (list);
8844
8845 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8845); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8846 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8846); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8847
8848 caja_file_list_free (list);
8849
8850 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8850); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8851
8852
8853 /* name checks */
8854 file_1 = caja_file_get_by_uri ("file:///home/");
8855
8856 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8856); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8857
8858 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home/") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home/\") == file_1"
, "caja-file.c", 8858); eel_check_boolean_result (caja_file_get_by_uri
("file:///home/") == file_1, (!(0))); } while (0)
;
8859 caja_file_unref (file_1);
8860
8861 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home\") == file_1"
, "caja-file.c", 8861); eel_check_boolean_result (caja_file_get_by_uri
("file:///home") == file_1, (!(0))); } while (0)
;
8862 caja_file_unref (file_1);
8863
8864 caja_file_unref (file_1);
8865
8866 file_1 = caja_file_get_by_uri ("file:///home");
8867 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8867); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8868 caja_file_unref (file_1);
8869
8870#if 0
8871 /* ALEX: I removed this, because it was breaking distchecks.
8872 * It used to work, but when canonical uris changed from
8873 * foo: to foo:/// it broke. I don't expect it to matter
8874 * in real life */
8875 file_1 = caja_file_get_by_uri (":");
8876 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), ":")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8876); eel_check_string_result (caja_file_get_name (file_1)
, ":"); } while (0)
;
8877 caja_file_unref (file_1);
8878#endif
8879
8880 file_1 = caja_file_get_by_uri ("eazel:");
8881 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "eazel")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8881); eel_check_string_result (caja_file_get_name (file_1)
, "eazel"); } while (0)
;
8882 caja_file_unref (file_1);
8883
8884 /* sorting */
8885 file_1 = caja_file_get_by_uri ("file:///etc");
8886 file_2 = caja_file_get_by_uri ("file:///usr");
8887
8888 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8888); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8889 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8889); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8890
8891 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) < 0"
, "caja-file.c", 8891); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) <
0, (!(0))); } while (0)
;
8892 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) > 0"
, "caja-file.c", 8892); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) > 0, (!(0))); } while (0)
;
8893 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) == 0"
, "caja-file.c", 8893); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) ==
0, (!(0))); } while (0)
;
8894 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)) == 0"
, "caja-file.c", 8894); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)
) == 0, (!(0))); } while (0)
;
8895 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) == 0"
, "caja-file.c", 8895); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) == 0, (!(0))); } while (0)
;
8896 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(0))) == 0"
, "caja-file.c", 8896); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(
0))) == 0, (!(0))); } while (0)
;
8897
8898 caja_file_unref (file_1);
8899 caja_file_unref (file_2);
8900}
8901
8902#endif /* !CAJA_OMIT_SELF_CHECK */
diff --git a/2024-07-29-023715-6438-1/report-c08216.html b/2024-07-29-023715-6438-1/report-c08216.html new file mode 100644 index 000000000..6eb73e838 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-c08216.html @@ -0,0 +1,1479 @@ + + + +caja-vfs-file.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-vfs-file.c
Warning:line 400, column 12
This statement is never executed
+ +

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 caja-vfs-file.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-vfs-file.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-vfs-file.c: Subclass of CajaFile to help implement the
4 virtual trash directory.
5
6 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (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 GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public
19 License along with this program; if not, write to the
20 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 Author: Darin Adler <darin@bentspoon.com>
24*/
25
26#include <config.h>
27
28#include <glib/gi18n.h>
29
30#include <eel/eel-gtk-macros.h>
31
32#include "caja-vfs-file.h"
33#include "caja-directory-notify.h"
34#include "caja-directory-private.h"
35#include "caja-file-private.h"
36#include "caja-autorun.h"
37
38static void caja_vfs_file_init (gpointer object,
39 gpointer klass);
40static void caja_vfs_file_class_init (gpointer klass);
41
42EEL_CLASS_BOILERPLATE (CajaVFSFile,static gpointer parent_class; GType caja_vfs_file_get_type (void
) { GType parent_type; static GType type; if (type == 0) { static
GTypeInfo info = { sizeof (CajaVFSFileClass), ((void*)0), ((
void*)0), (GClassInitFunc) caja_vfs_file_class_init, ((void*)
0), ((void*)0), sizeof (CajaVFSFile), 0, (GInstanceInitFunc) caja_vfs_file_init
, ((void*)0) }; parent_type = (caja_file_get_type()); type = g_type_register_static
(parent_type, "CajaVFSFile", &info, 0); parent_class = g_type_class_ref
(parent_type); } return type; }
43 caja_vfs_file,static gpointer parent_class; GType caja_vfs_file_get_type (void
) { GType parent_type; static GType type; if (type == 0) { static
GTypeInfo info = { sizeof (CajaVFSFileClass), ((void*)0), ((
void*)0), (GClassInitFunc) caja_vfs_file_class_init, ((void*)
0), ((void*)0), sizeof (CajaVFSFile), 0, (GInstanceInitFunc) caja_vfs_file_init
, ((void*)0) }; parent_type = (caja_file_get_type()); type = g_type_register_static
(parent_type, "CajaVFSFile", &info, 0); parent_class = g_type_class_ref
(parent_type); } return type; }
44 CAJA_TYPE_FILE)static gpointer parent_class; GType caja_vfs_file_get_type (void
) { GType parent_type; static GType type; if (type == 0) { static
GTypeInfo info = { sizeof (CajaVFSFileClass), ((void*)0), ((
void*)0), (GClassInitFunc) caja_vfs_file_class_init, ((void*)
0), ((void*)0), sizeof (CajaVFSFile), 0, (GInstanceInitFunc) caja_vfs_file_init
, ((void*)0) }; parent_type = (caja_file_get_type()); type = g_type_register_static
(parent_type, "CajaVFSFile", &info, 0); parent_class = g_type_class_ref
(parent_type); } return type; }
45
46static void
47vfs_file_monitor_add (CajaFile *file,
48 gconstpointer client,
49 CajaFileAttributes attributes)
50{
51 caja_directory_monitor_add_internal
52 (file->details->directory, file,
53 client, TRUE(!(0)), attributes, NULL((void*)0), NULL((void*)0));
54}
55
56static void
57vfs_file_monitor_remove (CajaFile *file,
58 gconstpointer client)
59{
60 caja_directory_monitor_remove_internal
61 (file->details->directory, file, client);
62}
63
64static void
65vfs_file_call_when_ready (CajaFile *file,
66 CajaFileAttributes file_attributes,
67 CajaFileCallback callback,
68 gpointer callback_data)
69
70{
71 caja_directory_call_when_ready_internal
72 (file->details->directory, file,
73 file_attributes, FALSE(0), NULL((void*)0), callback, callback_data);
74}
75
76static void
77vfs_file_cancel_call_when_ready (CajaFile *file,
78 CajaFileCallback callback,
79 gpointer callback_data)
80{
81 caja_directory_cancel_callback_internal
82 (file->details->directory, file,
83 NULL((void*)0), callback, callback_data);
84}
85
86static gboolean
87vfs_file_check_if_ready (CajaFile *file,
88 CajaFileAttributes file_attributes)
89{
90 return caja_directory_check_if_ready_internal
91 (file->details->directory, file,
92 file_attributes);
93}
94
95static void
96set_metadata_get_info_callback (GObject *source_object,
97 GAsyncResult *res,
98 gpointer callback_data)
99{
100 CajaFile *file;
101 GFileInfo *new_info;
102 GError *error;
103
104 file = callback_data;
105
106 error = NULL((void*)0);
107 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
108 if (new_info != NULL((void*)0))
109 {
110 if (caja_file_update_info (file, new_info))
111 {
112 caja_file_changed (file);
113 }
114 g_object_unref (new_info);
115 }
116 caja_file_unref (file);
117 if (error)
118 {
119 g_error_free (error);
120 }
121}
122
123static void
124set_metadata_callback (GObject *source_object,
125 GAsyncResult *result,
126 gpointer callback_data)
127{
128 CajaFile *file;
129 GError *error;
130 gboolean res;
131
132 file = callback_data;
133
134 error = NULL((void*)0);
135 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
136 result,
137 NULL((void*)0),
138 &error);
139
140 if (res)
141 {
142 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
143 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
144 0,
145 G_PRIORITY_DEFAULT0,
146 NULL((void*)0),
147 set_metadata_get_info_callback, file);
148 }
149 else
150 {
151 caja_file_unref (file);
152 g_error_free (error);
153 }
154}
155
156static void
157vfs_file_set_metadata (CajaFile *file,
158 const char *key,
159 const char *value)
160{
161 GFileInfo *info;
162 GFile *location;
163 char *gio_key;
164
165 info = g_file_info_new ();
166
167 gio_key = g_strconcat ("metadata::", key, NULL((void*)0));
168 if (value != NULL((void*)0))
169 {
170 g_file_info_set_attribute_string (info, gio_key, value);
171 }
172 else
173 {
174 /* Unset the key */
175 g_file_info_set_attribute (info, gio_key,
176 G_FILE_ATTRIBUTE_TYPE_INVALID,
177 NULL((void*)0));
178 }
179 g_free (gio_key);
180
181 location = caja_file_get_location (file);
182 g_file_set_attributes_async (location,
183 info,
184 0,
185 G_PRIORITY_DEFAULT0,
186 NULL((void*)0),
187 set_metadata_callback,
188 caja_file_ref (file));
189 g_object_unref (location);
190 g_object_unref (info);
191}
192
193static void
194vfs_file_set_metadata_as_list (CajaFile *file,
195 const char *key,
196 char **value)
197{
198 GFile *location;
199 GFileInfo *info;
200 char *gio_key;
201
202 info = g_file_info_new ();
203
204 gio_key = g_strconcat ("metadata::", key, NULL((void*)0));
205 g_file_info_set_attribute_stringv (info, gio_key, value);
206 g_free (gio_key);
207
208 location = caja_file_get_location (file);
209 g_file_set_attributes_async (location,
210 info,
211 0,
212 G_PRIORITY_DEFAULT0,
213 NULL((void*)0),
214 set_metadata_callback,
215 caja_file_ref (file));
216 g_object_unref (info);
217 g_object_unref (location);
218}
219
220static gboolean
221vfs_file_get_item_count (CajaFile *file,
222 guint *count,
223 gboolean *count_unreadable)
224{
225 if (count_unreadable != NULL((void*)0))
226 {
227 *count_unreadable = file->details->directory_count_failed;
228 }
229 if (!file->details->got_directory_count)
230 {
231 if (count != NULL((void*)0))
232 {
233 *count = 0;
234 }
235 return FALSE(0);
236 }
237 if (count != NULL((void*)0))
238 {
239 *count = file->details->directory_count;
240 }
241 return TRUE(!(0));
242}
243
244static CajaRequestStatus
245vfs_file_get_deep_counts (CajaFile *file,
246 guint *directory_count,
247 guint *file_count,
248 guint *unreadable_directory_count,
249 goffset *total_size,
250 goffset *total_size_on_disk)
251{
252 GFileType type;
253
254 if (directory_count != NULL((void*)0))
255 {
256 *directory_count = 0;
257 }
258 if (file_count != NULL((void*)0))
259 {
260 *file_count = 0;
261 }
262 if (unreadable_directory_count != NULL((void*)0))
263 {
264 *unreadable_directory_count = 0;
265 }
266 if (total_size != NULL((void*)0))
267 {
268 *total_size = 0;
269 }
270 if (total_size_on_disk != NULL((void*)0))
271 {
272 *total_size_on_disk = 0;
273 }
274
275 if (!caja_file_is_directory (file))
276 {
277 return CAJA_REQUEST_DONE;
278 }
279
280 if (file->details->deep_counts_status != CAJA_REQUEST_NOT_STARTED)
281 {
282 if (directory_count != NULL((void*)0))
283 {
284 *directory_count = file->details->deep_directory_count;
285 }
286 if (file_count != NULL((void*)0))
287 {
288 *file_count = file->details->deep_file_count;
289 }
290 if (unreadable_directory_count != NULL((void*)0))
291 {
292 *unreadable_directory_count = file->details->deep_unreadable_count;
293 }
294 if (total_size != NULL((void*)0))
295 {
296 *total_size = file->details->deep_size;
297 }
298 if (total_size_on_disk != NULL((void*)0))
299 {
300 *total_size_on_disk = file->details->deep_size_on_disk;
301 }
302 return file->details->deep_counts_status;
303 }
304
305 /* For directories, or before we know the type, we haven't started. */
306 type = caja_file_get_file_type (file);
307 if (type == G_FILE_TYPE_UNKNOWN
308 || type == G_FILE_TYPE_DIRECTORY)
309 {
310 return CAJA_REQUEST_NOT_STARTED;
311 }
312
313 /* For other types, we are done, and the zeros are permanent. */
314 return CAJA_REQUEST_DONE;
315}
316
317static gboolean
318vfs_file_get_date (CajaFile *file,
319 CajaDateType date_type,
320 time_t *date)
321{
322 switch (date_type)
323 {
324 case CAJA_DATE_TYPE_CHANGED:
325 /* Before we have info on a file, the date is unknown. */
326 if (file->details->ctime == 0)
327 {
328 return FALSE(0);
329 }
330 if (date != NULL((void*)0))
331 {
332 *date = file->details->ctime;
333 }
334 return TRUE(!(0));
335 case CAJA_DATE_TYPE_ACCESSED:
336 /* Before we have info on a file, the date is unknown. */
337 if (file->details->atime == 0)
338 {
339 return FALSE(0);
340 }
341 if (date != NULL((void*)0))
342 {
343 *date = file->details->atime;
344 }
345 return TRUE(!(0));
346 case CAJA_DATE_TYPE_MODIFIED:
347 /* Before we have info on a file, the date is unknown. */
348 if (file->details->mtime == 0)
349 {
350 return FALSE(0);
351 }
352 if (date != NULL((void*)0))
353 {
354 *date = file->details->mtime;
355 }
356 return TRUE(!(0));
357 case CAJA_DATE_TYPE_CREATED:
358 /* Before we have info on a file, the date is unknown. */
359 if (file->details->btime == 0)
360 {
361 return FALSE(0);
362 }
363 if (date != NULL((void*)0))
364 {
365 *date = file->details->btime;
366 }
367 return TRUE(!(0));
368 case CAJA_DATE_TYPE_TRASHED:
369 /* Before we have info on a file, the date is unknown. */
370 if (file->details->trash_time == 0)
371 {
372 return FALSE(0);
373 }
374 if (date != NULL((void*)0))
375 {
376 *date = file->details->trash_time;
377 }
378 return TRUE(!(0));
379 case CAJA_DATE_TYPE_PERMISSIONS_CHANGED:
380 /* Before we have info on a file, the date is unknown. */
381 if (file->details->mtime == 0 || file->details->ctime == 0)
382 {
383 return FALSE(0);
384 }
385 /* mtime is when the contents changed; ctime is when the
386 * contents or the permissions (inc. owner/group) changed.
387 * So we can only know when the permissions changed if mtime
388 * and ctime are different.
389 */
390 if (file->details->mtime == file->details->ctime)
391 {
392 return FALSE(0);
393 }
394 if (date != NULL((void*)0))
395 {
396 *date = file->details->ctime;
397 }
398 return TRUE(!(0));
399 }
400 return FALSE(0);
This statement is never executed
401}
402
403static char *
404vfs_file_get_where_string (CajaFile *file)
405{
406 return caja_file_get_parent_uri_for_display (file);
407}
408
409static void
410vfs_file_mount_callback (GObject *source_object,
411 GAsyncResult *res,
412 gpointer callback_data)
413{
414 CajaFileOperation *op;
415 GFile *mounted_on;
416 GError *error;
417
418 op = callback_data;
419
420 error = NULL((void*)0);
421 mounted_on = g_file_mount_mountable_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
422 res, &error);
423 caja_file_operation_complete (op, mounted_on, error);
424 if (mounted_on)
425 {
426 g_object_unref (mounted_on);
427 }
428 if (error)
429 {
430 g_error_free (error);
431 }
432}
433
434
435static void
436vfs_file_mount (CajaFile *file,
437 GMountOperation *mount_op,
438 GCancellable *cancellable,
439 CajaFileOperationCallback callback,
440 gpointer callback_data)
441{
442 CajaFileOperation *op;
443 GError *error;
444 GFile *location;
445
446 if (file->details->type != G_FILE_TYPE_MOUNTABLE)
447 {
448 if (callback)
449 {
450 error = NULL((void*)0);
451 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
452 _("This file cannot be mounted")dcgettext (((void*)0), "This file cannot be mounted", 5));
453 callback (file, NULL((void*)0), error, callback_data);
454 g_error_free (error);
455 }
456 return;
457 }
458
459 op = caja_file_operation_new (file, callback, callback_data);
460 if (cancellable)
461 {
462 g_object_unref (op->cancellable);
463 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
464 }
465
466 location = caja_file_get_location (file);
467 g_file_mount_mountable (location,
468 0,
469 mount_op,
470 op->cancellable,
471 vfs_file_mount_callback,
472 op);
473 g_object_unref (location);
474}
475
476static void
477vfs_file_unmount_callback (GObject *source_object,
478 GAsyncResult *res,
479 gpointer callback_data)
480{
481 CajaFileOperation *op;
482 gboolean unmounted;
483 GError *error;
484
485 op = callback_data;
486
487 error = NULL((void*)0);
488 unmounted = g_file_unmount_mountable_with_operation_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
489 res, &error);
490
491 if (!unmounted &&
492 error->domain == G_IO_ERRORg_io_error_quark() &&
493 (error->code == G_IO_ERROR_FAILED_HANDLED ||
494 error->code == G_IO_ERROR_CANCELLED))
495 {
496 g_error_free (error);
497 error = NULL((void*)0);
498 }
499
500 caja_file_operation_complete (op, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), error);
501 if (error)
502 {
503 g_error_free (error);
504 }
505}
506
507static void
508vfs_file_unmount (CajaFile *file,
509 GMountOperation *mount_op,
510 GCancellable *cancellable,
511 CajaFileOperationCallback callback,
512 gpointer callback_data)
513{
514 CajaFileOperation *op;
515 GFile *location;
516
517 op = caja_file_operation_new (file, callback, callback_data);
518 if (cancellable)
519 {
520 g_object_unref (op->cancellable);
521 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
522 }
523
524 location = caja_file_get_location (file);
525 g_file_unmount_mountable_with_operation (location,
526 G_MOUNT_UNMOUNT_NONE,
527 mount_op,
528 op->cancellable,
529 vfs_file_unmount_callback,
530 op);
531 g_object_unref (location);
532}
533
534static void
535vfs_file_eject_callback (GObject *source_object,
536 GAsyncResult *res,
537 gpointer callback_data)
538{
539 CajaFileOperation *op;
540 gboolean ejected;
541 GError *error;
542
543 op = callback_data;
544
545 error = NULL((void*)0);
546 ejected = g_file_eject_mountable_with_operation_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
547 res, &error);
548
549 if (!ejected &&
550 error->domain == G_IO_ERRORg_io_error_quark() &&
551 (error->code == G_IO_ERROR_FAILED_HANDLED ||
552 error->code == G_IO_ERROR_CANCELLED))
553 {
554 g_error_free (error);
555 error = NULL((void*)0);
556 }
557
558 caja_file_operation_complete (op, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), error);
559 if (error)
560 {
561 g_error_free (error);
562 }
563}
564
565static void
566vfs_file_eject (CajaFile *file,
567 GMountOperation *mount_op,
568 GCancellable *cancellable,
569 CajaFileOperationCallback callback,
570 gpointer callback_data)
571{
572 CajaFileOperation *op;
573 GFile *location;
574
575 op = caja_file_operation_new (file, callback, callback_data);
576 if (cancellable)
577 {
578 g_object_unref (op->cancellable);
579 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
580 }
581
582 location = caja_file_get_location (file);
583 g_file_eject_mountable_with_operation (location,
584 G_MOUNT_UNMOUNT_NONE,
585 mount_op,
586 op->cancellable,
587 vfs_file_eject_callback,
588 op);
589 g_object_unref (location);
590}
591
592static void
593vfs_file_start_callback (GObject *source_object,
594 GAsyncResult *res,
595 gpointer callback_data)
596{
597 CajaFileOperation *op;
598 gboolean started;
599 GError *error;
600
601 op = callback_data;
602
603 error = NULL((void*)0);
604 started = g_file_start_mountable_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
605 res, &error);
606
607 if (!started &&
608 error->domain == G_IO_ERRORg_io_error_quark() &&
609 (error->code == G_IO_ERROR_FAILED_HANDLED ||
610 error->code == G_IO_ERROR_CANCELLED))
611 {
612 g_error_free (error);
613 error = NULL((void*)0);
614 }
615
616 caja_file_operation_complete (op, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), error);
617 if (error)
618 {
619 g_error_free (error);
620 }
621}
622
623
624static void
625vfs_file_start (CajaFile *file,
626 GMountOperation *mount_op,
627 GCancellable *cancellable,
628 CajaFileOperationCallback callback,
629 gpointer callback_data)
630{
631 CajaFileOperation *op;
632 GError *error;
633 GFile *location;
634
635 if (file->details->type != G_FILE_TYPE_MOUNTABLE)
636 {
637 if (callback)
638 {
639 error = NULL((void*)0);
640 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
641 _("This file cannot be started")dcgettext (((void*)0), "This file cannot be started", 5));
642 callback (file, NULL((void*)0), error, callback_data);
643 g_error_free (error);
644 }
645 return;
646 }
647
648 op = caja_file_operation_new (file, callback, callback_data);
649 if (cancellable)
650 {
651 g_object_unref (op->cancellable);
652 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
653 }
654
655 location = caja_file_get_location (file);
656 g_file_start_mountable (location,
657 0,
658 mount_op,
659 op->cancellable,
660 vfs_file_start_callback,
661 op);
662 g_object_unref (location);
663}
664
665static void
666vfs_file_stop_callback (GObject *source_object,
667 GAsyncResult *res,
668 gpointer callback_data)
669{
670 CajaFileOperation *op;
671 gboolean stopped;
672 GError *error;
673
674 op = callback_data;
675
676 error = NULL((void*)0);
677 stopped = g_file_stop_mountable_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
678 res, &error);
679
680 if (!stopped &&
681 error->domain == G_IO_ERRORg_io_error_quark() &&
682 (error->code == G_IO_ERROR_FAILED_HANDLED ||
683 error->code == G_IO_ERROR_CANCELLED))
684 {
685 g_error_free (error);
686 error = NULL((void*)0);
687 }
688
689 caja_file_operation_complete (op, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), error);
690 if (error)
691 {
692 g_error_free (error);
693 }
694}
695
696static void
697vfs_file_stop (CajaFile *file,
698 GMountOperation *mount_op,
699 GCancellable *cancellable,
700 CajaFileOperationCallback callback,
701 gpointer callback_data)
702{
703 CajaFileOperation *op;
704 GFile *location;
705
706 op = caja_file_operation_new (file, callback, callback_data);
707 if (cancellable)
708 {
709 g_object_unref (op->cancellable);
710 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
711 }
712
713 location = caja_file_get_location (file);
714 g_file_stop_mountable (location,
715 G_MOUNT_UNMOUNT_NONE,
716 mount_op,
717 op->cancellable,
718 vfs_file_stop_callback,
719 op);
720 g_object_unref (location);
721}
722
723static void
724vfs_file_poll_callback (GObject *source_object,
725 GAsyncResult *res,
726 gpointer callback_data)
727{
728 CajaFileOperation *op;
729 gboolean stopped;
730 GError *error;
731
732 op = callback_data;
733
734 error = NULL((void*)0);
735 stopped = g_file_poll_mountable_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
736 res, &error);
737
738 if (!stopped &&
739 error->domain == G_IO_ERRORg_io_error_quark() &&
740 (error->code == G_IO_ERROR_FAILED_HANDLED ||
741 error->code == G_IO_ERROR_CANCELLED))
742 {
743 g_error_free (error);
744 error = NULL((void*)0);
745 }
746
747 caja_file_operation_complete (op, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), error);
748 if (error)
749 {
750 g_error_free (error);
751 }
752}
753
754static void
755vfs_file_poll_for_media (CajaFile *file)
756{
757 CajaFileOperation *op;
758 GFile *location;
759
760 op = caja_file_operation_new (file, NULL((void*)0), NULL((void*)0));
761
762 location = caja_file_get_location (file);
763 g_file_poll_mountable (location,
764 op->cancellable,
765 vfs_file_poll_callback,
766 op);
767 g_object_unref (location);
768}
769
770static void
771caja_vfs_file_init (gpointer object, gpointer klass)
772{
773}
774
775static void
776caja_vfs_file_class_init (gpointer klass)
777{
778 CajaFileClass *file_class;
779
780 file_class = CAJA_FILE_CLASS (klass)((((CajaFileClass*) (void *) ((klass)))));
781
782 file_class->monitor_add = vfs_file_monitor_add;
783 file_class->monitor_remove = vfs_file_monitor_remove;
784 file_class->call_when_ready = vfs_file_call_when_ready;
785 file_class->cancel_call_when_ready = vfs_file_cancel_call_when_ready;
786 file_class->check_if_ready = vfs_file_check_if_ready;
787 file_class->get_item_count = vfs_file_get_item_count;
788 file_class->get_deep_counts = vfs_file_get_deep_counts;
789 file_class->get_date = vfs_file_get_date;
790 file_class->get_where_string = vfs_file_get_where_string;
791 file_class->set_metadata = vfs_file_set_metadata;
792 file_class->set_metadata_as_list = vfs_file_set_metadata_as_list;
793 file_class->mount = vfs_file_mount;
794 file_class->unmount = vfs_file_unmount;
795 file_class->eject = vfs_file_eject;
796 file_class->start = vfs_file_start;
797 file_class->stop = vfs_file_stop;
798 file_class->poll_for_media = vfs_file_poll_for_media;
799}
diff --git a/2024-07-29-023715-6438-1/report-c2fd27.html b/2024-07-29-023715-6438-1/report-c2fd27.html new file mode 100644 index 000000000..7fd4e1f39 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-c2fd27.html @@ -0,0 +1,1723 @@ + + + +eel-string.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-string.c
Warning:line 585, column 9
Access of the heap area at index 1, while it holds only a single 'ConversionInfo' element
+ +

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 eel-string.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-string.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 eel-string.c: String routines to augment <string.h>.
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Darin Adler <darin@eazel.com>
23*/
24
25#include <config.h>
26#include "eel-glib-extensions.h"
27#include "eel-string.h"
28
29#include <errno(*__errno_location ()).h>
30#include <locale.h>
31#include <stdlib.h>
32#include <string.h>
33
34#if !defined (EEL_OMIT_SELF_CHECK)
35#include "eel-lib-self-check-functions.h"
36#endif
37
38size_t
39eel_strlen (const char *string)
40{
41 return string == NULL((void*)0) ? 0 : strlen (string);
42}
43
44char *
45eel_strchr (const char *haystack, char needle)
46{
47 return haystack == NULL((void*)0) ? NULL((void*)0) : strchr (haystack, needle);
48}
49
50int
51eel_strcmp (const char *string_a, const char *string_b)
52{
53 /* FIXME bugzilla.eazel.com 5450: Maybe we need to make this
54 * treat 'NULL < ""', or have a flavor that does that. If we
55 * didn't have code that already relies on 'NULL == ""', I
56 * would change it right now.
57 */
58 return strcmp (string_a == NULL((void*)0) ? "" : string_a,
59 string_b == NULL((void*)0) ? "" : string_b);
60}
61
62gboolean
63eel_str_is_empty (const char *string_or_null)
64{
65 return eel_strcmp (string_or_null, NULL((void*)0)) == 0;
66}
67
68gboolean
69eel_str_has_prefix (const char *haystack, const char *needle)
70{
71 return g_str_has_prefix (haystack == NULL ? "" : haystack,(__builtin_constant_p (needle == ((void*)0) ? "" : needle)? __extension__
({ const char * const __str = (haystack == ((void*)0) ? "" :
haystack); const char * const __prefix = (needle == ((void*)
0) ? "" : needle); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_23; if (__str == ((void
*)0) || __prefix == ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (haystack == ((void
*)0) ? "" : haystack, needle == ((void*)0) ? "" : needle) )
72 needle == NULL ? "" : needle)(__builtin_constant_p (needle == ((void*)0) ? "" : needle)? __extension__
({ const char * const __str = (haystack == ((void*)0) ? "" :
haystack); const char * const __prefix = (needle == ((void*)
0) ? "" : needle); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_23; if (__str == ((void
*)0) || __prefix == ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (haystack == ((void
*)0) ? "" : haystack, needle == ((void*)0) ? "" : needle) )
;
73}
74
75gboolean
76eel_istr_has_prefix (const char *haystack, const char *needle)
77{
78 const char *h, *n;
79 char hc, nc;
80
81 /* Eat one character at a time. */
82 h = haystack == NULL((void*)0) ? "" : haystack;
83 n = needle == NULL((void*)0) ? "" : needle;
84 do
85 {
86 if (*n == '\0')
87 {
88 return TRUE(!(0));
89 }
90 if (*h == '\0')
91 {
92 return FALSE(0);
93 }
94 hc = *h++;
95 nc = *n++;
96 hc = g_ascii_tolower (hc);
97 nc = g_ascii_tolower (nc);
98 }
99 while (hc == nc);
100 return FALSE(0);
101}
102
103/**
104 * eel_str_get_prefix:
105 * Get a new string containing the first part of an existing string.
106 *
107 * @source: The string whose prefix should be extracted.
108 * @delimiter: The string that marks the end of the prefix.
109 *
110 * Return value: A newly-allocated string that that matches the first part
111 * of @source, up to but not including the first occurrence of
112 * @delimiter. If @source is NULL, returns NULL. If
113 * @delimiter is NULL, returns a copy of @source.
114 * If @delimiter does not occur in @source, returns
115 * a copy of @source.
116 **/
117char *
118eel_str_get_prefix (const char *source,
119 const char *delimiter)
120{
121 char *prefix_start;
122
123 if (source == NULL((void*)0))
124 {
125 return NULL((void*)0);
126 }
127
128 if (delimiter == NULL((void*)0))
129 {
130 return g_strdup (source)g_strdup_inline (source);
131 }
132
133 prefix_start = strstr (source, delimiter);
134
135 if (prefix_start == NULL((void*)0))
136 {
137 return g_strdup ("")g_strdup_inline ("");
138 }
139
140 return g_strndup (source, prefix_start - source);
141}
142
143char *
144eel_str_double_underscores (const char *string)
145{
146 int underscores;
147 const char *p;
148 char *q;
149 char *escaped;
150
151 if (string == NULL((void*)0))
152 {
153 return NULL((void*)0);
154 }
155
156 underscores = 0;
157 for (p = string; *p != '\0'; p++)
158 {
159 underscores += (*p == '_');
160 }
161
162 if (underscores == 0)
163 {
164 return g_strdup (string)g_strdup_inline (string);
165 }
166
167 escaped = g_new (char, strlen (string) + underscores + 1)(char *) (__extension__ ({ gsize __n = (gsize) (strlen (string
) + underscores + 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; }))
;
168 for (p = string, q = escaped; *p != '\0'; p++, q++)
169 {
170 /* Add an extra underscore. */
171 if (*p == '_')
172 {
173 *q++ = '_';
174 }
175 *q = *p;
176 }
177 *q = '\0';
178
179 return escaped;
180}
181
182char *
183eel_str_capitalize (const char *string)
184{
185 char *capitalized;
186
187 if (string == NULL((void*)0))
188 {
189 return NULL((void*)0);
190 }
191
192 capitalized = g_strdup (string)g_strdup_inline (string);
193
194 capitalized[0] = g_ascii_toupper (capitalized[0]);
195
196 return capitalized;
197}
198
199/* Note: eel_string_ellipsize_* that use a length in pixels
200 * rather than characters can be found in eel_gdk_extensions.h
201 *
202 * FIXME bugzilla.eazel.com 5089:
203 * we should coordinate the names of eel_string_ellipsize_*
204 * and eel_str_*_truncate so that they match better and reflect
205 * their different behavior.
206 */
207char *
208eel_str_middle_truncate (const char *string,
209 guint truncate_length)
210{
211 char *truncated;
212 guint length;
213 guint num_left_chars;
214 guint num_right_chars;
215
216 const char delimter[] = "...";
217 const guint delimter_length = strlen (delimter);
218 const guint min_truncate_length = delimter_length + 2;
219
220 if (string == NULL((void*)0))
221 {
222 return NULL((void*)0);
223 }
224
225 /* It doesnt make sense to truncate strings to less than
226 * the size of the delimiter plus 2 characters (one on each
227 * side)
228 */
229 if (truncate_length < min_truncate_length)
230 {
231 return g_strdup (string)g_strdup_inline (string);
232 }
233
234 length = g_utf8_strlen (string, -1);
235
236 /* Make sure the string is not already small enough. */
237 if (length <= truncate_length)
238 {
239 return g_strdup (string)g_strdup_inline (string);
240 }
241
242 /* Find the 'middle' where the truncation will occur. */
243 num_left_chars = (truncate_length - delimter_length) / 2;
244 num_right_chars = truncate_length - num_left_chars - delimter_length;
245
246 truncated = g_new (char, strlen (string) + 1)(char *) (__extension__ ({ gsize __n = (gsize) (strlen (string
) + 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; }))
;
247
248 g_utf8_strncpy (truncated, string, num_left_chars);
249 g_strlcat (truncated, delimter, (truncate_length + 1));
250 g_strlcat (truncated, g_utf8_offset_to_pointer (string, length - num_right_chars), (truncate_length + 1));
251
252 return truncated;
253}
254
255char *
256eel_str_strip_substring_and_after (const char *string,
257 const char *substring)
258{
259 const char *substring_position;
260
261 g_return_val_if_fail (substring != NULL, g_strdup (string))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (substring != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "substring != NULL"); return
(g_strdup_inline (string)); } } while (0)
;
262 g_return_val_if_fail (substring[0] != '\0', g_strdup (string))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (substring[0] != '\0') _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "substring[0] != '\\0'")
; return (g_strdup_inline (string)); } } while (0)
;
263
264 if (string == NULL((void*)0))
265 {
266 return NULL((void*)0);
267 }
268
269 substring_position = strstr (string, substring);
270 if (substring_position == NULL((void*)0))
271 {
272 return g_strdup (string)g_strdup_inline (string);
273 }
274
275 return g_strndup (string,
276 substring_position - string);
277}
278
279char *
280eel_str_replace_substring (const char *string,
281 const char *substring,
282 const char *replacement)
283{
284 int substring_length, replacement_length, result_length, remaining_length;
285 const char *p, *substring_position;
286 char *result, *result_position;
287
288 g_return_val_if_fail (substring != NULL, g_strdup (string))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if (substring != ((void*)0)) _g_boolean_var_26 = 1; else _g_boolean_var_26
= 0; _g_boolean_var_26; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "substring != NULL"); return
(g_strdup_inline (string)); } } while (0)
;
289 g_return_val_if_fail (substring[0] != '\0', g_strdup (string))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if (substring[0] != '\0') _g_boolean_var_27 = 1; else _g_boolean_var_27
= 0; _g_boolean_var_27; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "substring[0] != '\\0'")
; return (g_strdup_inline (string)); } } while (0)
;
290
291 if (string == NULL((void*)0))
292 {
293 return NULL((void*)0);
294 }
295
296 if (replacement == NULL((void*)0))
297 {
298 replacement = "";
299 }
300
301 substring_length = strlen (substring);
302 replacement_length = eel_strlen (replacement);
303
304 result_length = strlen (string);
305 for (p = string; ; p = substring_position + substring_length)
306 {
307 substring_position = strstr (p, substring);
308 if (substring_position == NULL((void*)0))
309 {
310 break;
311 }
312 if (replacement_length > substring_length)
313 result_length += replacement_length - substring_length;
314 }
315
316 result = g_malloc (result_length + 1);
317
318 result_position = result;
319 for (p = string; ; p = substring_position + substring_length)
320 {
321 substring_position = strstr (p, substring);
322 if (substring_position == NULL((void*)0))
323 {
324 remaining_length = strlen (p);
325 memcpy (result_position, p, remaining_length);
326 result_position += remaining_length;
327 break;
328 }
329 memcpy (result_position, p, substring_position - p);
330 result_position += substring_position - p;
331 memcpy (result_position, replacement, replacement_length);
332 result_position += replacement_length;
333 }
334
335 result_position[0] = '\0';
336
337 return result;
338}
339
340/**************** Custom printf ***********/
341
342typedef struct
343{
344 const char *start;
345 const char *end;
346 GString *format;
347 int arg_pos;
348 int width_pos;
349 int width_format_index;
350 int precision_pos;
351 int precision_format_index;
352} ConversionInfo;
353
354enum
355{
356 ARG_TYPE_INVALID,
357 ARG_TYPE_INT,
358 ARG_TYPE_LONG,
359 ARG_TYPE_LONG_LONG,
360 ARG_TYPE_SIZE,
361 ARG_TYPE_LONG_DOUBLE,
362 ARG_TYPE_DOUBLE,
363 ARG_TYPE_POINTER
364};
365
366typedef int ArgType; /* An int, because custom are < 0 */
367
368
369static const char *
370get_position (const char *format, int *i)
371{
372 const char *p;
373
374 p = format;
375
376 if (g_ascii_isdigit (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_DIGIT) != 0))
377 {
378 p++;
379
380 while (g_ascii_isdigit (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_DIGIT) != 0))
381 {
382 p++;
383 }
384
385 if (*p == '$')
386 {
387 if (i != NULL((void*)0))
388 {
389 *i = atoi (format) - 1;
390 }
391 return p + 1;
392 }
393 }
394
395 return format;
396}
397
398static gboolean
399is_flag (char c)
400{
401 return strchr ("#0- +'I", c) != NULL((void*)0);
402}
403
404static gboolean
405is_length_modifier (char c)
406{
407 return strchr ("hlLjzt", c) != NULL((void*)0);
408}
409
410
411static ArgType
412get_arg_type_from_format (EelPrintfHandler *custom_handlers,
413 const char *format,
414 int len)
415{
416 char c;
417
418 c = format[len-1];
419
420 if (custom_handlers != NULL((void*)0))
421 {
422 int i;
423
424 for (i = 0; custom_handlers[i].character != 0; i++)
425 {
426 if (custom_handlers[i].character == c)
427 {
428 return -(i + 1);
429 }
430 }
431 }
432
433 switch (c)
434 {
435 case 'd':
436 case 'i':
437 case 'o':
438 case 'u':
439 case 'x':
440 case 'X':
441 if (g_str_has_prefix (format, "ll")(__builtin_constant_p ("ll")? __extension__ ({ const char * const
__str = (format); const char * const __prefix = ("ll"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_28
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_28
= 1; else _g_boolean_var_28 = 0; _g_boolean_var_28; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
format, "ll") )
)
442 {
443 return ARG_TYPE_LONG_LONG;
444 }
445 if (g_str_has_prefix (format, "l")(__builtin_constant_p ("l")? __extension__ ({ const char * const
__str = (format); const char * const __prefix = ("l"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_29
= 1; else _g_boolean_var_29 = 0; _g_boolean_var_29; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
format, "l") )
)
446 {
447 return ARG_TYPE_LONG;
448 }
449 if (g_str_has_prefix (format, "l")(__builtin_constant_p ("l")? __extension__ ({ const char * const
__str = (format); const char * const __prefix = ("l"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_30
= 1; else _g_boolean_var_30 = 0; _g_boolean_var_30; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
format, "l") )
)
450 {
451 return ARG_TYPE_LONG;
452 }
453 if (g_str_has_prefix (format, "z")(__builtin_constant_p ("z")? __extension__ ({ const char * const
__str = (format); const char * const __prefix = ("z"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_31
= 1; else _g_boolean_var_31 = 0; _g_boolean_var_31; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
format, "z") )
)
454 {
455 return ARG_TYPE_SIZE;
456 }
457 return ARG_TYPE_INT;
458 case 'e':
459 case 'E':
460 case 'f':
461 case 'F':
462 case 'g':
463 case 'G':
464 case 'a':
465 case 'A':
466 if (g_str_has_prefix (format, "L")(__builtin_constant_p ("L")? __extension__ ({ const char * const
__str = (format); const char * const __prefix = ("L"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_32
= 1; else _g_boolean_var_32 = 0; _g_boolean_var_32; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
format, "L") )
)
467 {
468 return ARG_TYPE_LONG_DOUBLE;
469 }
470 return ARG_TYPE_DOUBLE;
471 case 'c':
472 return ARG_TYPE_INT;
473 case 's':
474 case 'p':
475 case 'n':
476 return ARG_TYPE_POINTER;
477 }
478 return ARG_TYPE_INVALID;
479}
480
481static void
482skip_argv (va_list *va,
483 ArgType type,
484 EelPrintfHandler *custom_handlers)
485{
486 if (type < 0)
487 {
488 custom_handlers[-type - 1].skip (va);
489 return;
490 }
491
492 switch (type)
493 {
494 default:
495 case ARG_TYPE_INVALID:
496 return;
497
498 case ARG_TYPE_INT:
499 (void) va_arg (*va, int)__builtin_va_arg(*va, int);
500 break;
501 case ARG_TYPE_LONG:
502 (void) va_arg (*va, long int)__builtin_va_arg(*va, long int);
503 break;
504 case ARG_TYPE_LONG_LONG:
505 (void) va_arg (*va, long long int)__builtin_va_arg(*va, long long int);
506 break;
507 case ARG_TYPE_SIZE:
508 (void) va_arg (*va, gsize)__builtin_va_arg(*va, gsize);
509 break;
510 case ARG_TYPE_LONG_DOUBLE:
511 (void) va_arg (*va, long double)__builtin_va_arg(*va, long double);
512 break;
513 case ARG_TYPE_DOUBLE:
514 (void) va_arg (*va, double)__builtin_va_arg(*va, double);
515 break;
516 case ARG_TYPE_POINTER:
517 (void) va_arg (*va, void *)__builtin_va_arg(*va, void *);
518 break;
519 }
520}
521
522static void
523skip_to_arg (va_list *va,
524 ArgType *types,
525 EelPrintfHandler *custom_handlers,
526 int n)
527{
528 int i;
529 for (i = 0; i < n; i++)
530 {
531 skip_argv (va, types[i], custom_handlers);
532 }
533}
534
535char *
536eel_strdup_vprintf_with_custom (EelPrintfHandler *custom,
537 const char *format,
538 va_list va_orig)
539{
540 va_list va;
541 const char *p;
542 int num_args, i, j;
543 ArgType *args;
544 ConversionInfo *conversions;
545 GString *f, *str;
546 const char *flags, *width, *prec, *mod, *pos;
547 char *s;
548
549 num_args = 0;
550 for (p = format; *p != 0; p++)
1
Assuming the condition is true
2
Loop condition is true. Entering loop body
7
Assuming the condition is false
8
Loop condition is false. Execution continues on line 562
551 {
552 if (*p == '%')
3
Assuming the condition is true
4
Taking true branch
553 {
554 p++;
555 if (*p != '%')
5
Assuming the condition is true
6
Taking true branch
556 {
557 num_args++;
558 }
559 }
560 }
561
562 args = g_new0 (ArgType, num_args * 3 + 1)(ArgType *) (__extension__ ({ gsize __n = (gsize) (num_args *
3 + 1); gsize __s = sizeof (ArgType); 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; }))
;
9
Taking false branch
563 conversions = g_new0 (ConversionInfo, num_args)(ConversionInfo *) (__extension__ ({ gsize __n = (gsize) (num_args
); gsize __s = sizeof (ConversionInfo); 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; }))
;
10
Taking false branch
564
565 /* i indexes conversions, j indexes args */
566 i = 0;
567 j = 0;
568 p = format;
569 while (*p != 0)
11
Loop condition is true. Entering loop body
20
Assuming the condition is true
21
Loop condition is true. Entering loop body
570 {
571 if (*p != '%')
12
Taking false branch
22
Assuming the condition is false
23
Taking false branch
572 {
573 p++;
574 continue;
575 }
576 p++;
577 if (*p == '%')
13
Taking false branch
24
Assuming the condition is false
25
Taking false branch
578 {
579 p++;
580 continue;
581 }
582
583 /* We got a real conversion: */
584 f = g_string_new ("%");
585 conversions[i].start = p - 1;
26
Access of the heap area at index 1, while it holds only a single 'ConversionInfo' element
586
587 /* First comes the positional arg */
588
589 pos = p;
590 p = get_position (p, NULL((void*)0));
591
592 /* Then flags */
593 flags = p;
594 while (is_flag (*p))
14
Loop condition is false. Execution continues on line 598
595 {
596 p++;
597 }
598 g_string_append_len (f, flags, p - flags)g_string_append_len_inline (f, flags, p - flags);
599
600 /* Field width */
601
602 if (*p == '*')
15
Assuming the condition is true
16
Taking true branch
603 {
604 p++;
605 p = get_position (p, &j);
606 args[j] = ARG_TYPE_INT;
607 conversions[i].width_pos = j++;
608 conversions[i].width_format_index = f->len;
609 }
610 else
611 {
612 conversions[i].width_pos = -1;
613 conversions[i].width_format_index = -1;
614 width = p;
615 while (g_ascii_isdigit (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_DIGIT) != 0))
616 {
617 p++;
618 }
619 g_string_append_len (f, width, p - width)g_string_append_len_inline (f, width, p - width);
620 }
621
622 /* Precision */
623 conversions[i].precision_pos = -1;
624 conversions[i].precision_format_index = -1;
625 if (*p == '.')
17
Taking false branch
626 {
627 g_string_append_c (f, '.')g_string_append_c_inline (f, '.');
628 p++;
629
630 if (*p == '*')
631 {
632 p++;
633 p = get_position (p, &j);
634 args[j] = ARG_TYPE_INT;
635 conversions[i].precision_pos = j++;
636 conversions[i].precision_format_index = f->len;
637 }
638 else
639 {
640 prec = p;
641 while (g_ascii_isdigit (*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_DIGIT) != 0) || *p == '-')
642 {
643 p++;
644 }
645 g_string_append_len (f, prec, p - prec)g_string_append_len_inline (f, prec, p - prec);
646 }
647 }
648
649 /* length modifier */
650
651 mod = p;
652
653 while (is_length_modifier (*p))
18
Loop condition is false. Execution continues on line 659
654 {
655 p++;
656 }
657
658 /* conversion specifier */
659 if (*p != 0)
19
Taking false branch
660 p++;
661
662 g_string_append_len (f, mod, p - mod)g_string_append_len_inline (f, mod, p - mod);
663
664 get_position (pos, &j);
665 args[j] = get_arg_type_from_format (custom, mod, p - mod);
666 conversions[i].arg_pos = j++;
667 conversions[i].format = f;
668 conversions[i].end = p;
669
670 i++;
671 }
672
673 g_assert (i == num_args)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if (i == num_args) _g_boolean_var_33 = 1; else _g_boolean_var_33
= 0; _g_boolean_var_33; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-string.c", 673, ((const char*) (__func__)), "i == num_args"
); } while (0)
;
674
675 str = g_string_new ("");
676
677 p = format;
678 for (i = 0; i < num_args; i++)
679 {
680 ArgType type;
681
682 g_string_append_len (str, p, conversions[i].start - p)g_string_append_len_inline (str, p, conversions[i].start - p);
683 p = conversions[i].end;
684
685 if (conversions[i].precision_pos != -1)
686 {
687 char *val;
688
689 va_copy (va, va_orig)__builtin_va_copy(va, va_orig);
690 skip_to_arg (&va, args, custom, conversions[i].precision_pos);
691 val = g_strdup_vprintf ("%d", va);
692 va_end (va)__builtin_va_end(va);
693
694 g_string_insert (conversions[i].format,
695 conversions[i].precision_format_index,
696 val);
697
698 g_free (val);
699 }
700
701 if (conversions[i].width_pos != -1)
702 {
703 char *val;
704
705 va_copy (va, va_orig)__builtin_va_copy(va, va_orig);
706 skip_to_arg (&va, args, custom, conversions[i].width_pos);
707 val = g_strdup_vprintf ("%d", va);
708 va_end (va)__builtin_va_end(va);
709
710 g_string_insert (conversions[i].format,
711 conversions[i].width_format_index,
712 val);
713
714 g_free (val);
715 }
716
717 va_copy (va, va_orig)__builtin_va_copy(va, va_orig);
718 skip_to_arg (&va, args, custom, conversions[i].arg_pos);
719 type = args[conversions[i].arg_pos];
720 if (type < 0)
721 {
722 s = custom[-type - 1].to_string (conversions[i].format->str, va);
723 g_string_append (str, s)(__builtin_constant_p (s) ? __extension__ ({ const char * const
__val = (s); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_34; if (__val != ((void
*)0)) _g_boolean_var_34 = 1; else _g_boolean_var_34 = 0; _g_boolean_var_34
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, s, (gssize) -1))
;
724 g_free (s);
725 }
726 else
727 {
728 g_string_append_vprintf (str, conversions[i].format->str, va);
729 }
730 va_end (va)__builtin_va_end(va);
731
732 g_string_free (conversions[i].format, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(conversions[i].format), ((!(0)))) : g_string_free_and_steal (
conversions[i].format)) : (g_string_free) ((conversions[i].format
), ((!(0)))))
;
733 }
734 g_string_append (str, p)(__builtin_constant_p (p) ? __extension__ ({ const char * const
__val = (p); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_35; if (__val != ((void
*)0)) _g_boolean_var_35 = 1; else _g_boolean_var_35 = 0; _g_boolean_var_35
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, p, (gssize) -1))
;
735
736 g_free (args);
737 g_free (conversions);
738
739 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))))
;
740}
741
742char *
743eel_strdup_printf_with_custom (EelPrintfHandler *handlers,
744 const char *format,
745 ...)
746{
747 va_list va;
748 char *res;
749
750 va_start (va, format)__builtin_va_start(va, format);
751 res = eel_strdup_vprintf_with_custom (handlers, format, va);
752 va_end (va)__builtin_va_end(va);
753
754 return res;
755}
756
757#if !defined (EEL_OMIT_SELF_CHECK)
758
759static void
760verify_printf (const char *format, ...)
761{
762 va_list va;
763 char *orig, *new;
764
765 va_start (va, format)__builtin_va_start(va, format);
766 orig = g_strdup_vprintf (format, va);
767 va_end (va)__builtin_va_end(va);
768
769 va_start (va, format)__builtin_va_start(va, format);
770 new = eel_strdup_vprintf_with_custom (NULL((void*)0), format, va);
771 va_end (va)__builtin_va_end(va);
772
773 EEL_CHECK_STRING_RESULT (new, orig)do { eel_before_check ("new", "eel-string.c", 773); eel_check_string_result
(new, orig); } while (0)
;
774
775 g_free (orig);
776}
777
778static char *
779custom1_to_string (char *format, va_list va)
780{
781 int i;
782
783 i = va_arg (va, int)__builtin_va_arg(va, int);
784
785 return g_strdup_printf ("c1-%d-", i);
786}
787
788static void
789custom1_skip (va_list *va)
790{
791 (void) va_arg (*va, int)__builtin_va_arg(*va, int);
792}
793
794static char *
795custom2_to_string (char *format, va_list va)
796{
797 char *s;
798
799 s = va_arg (va, char *)__builtin_va_arg(va, char *);
800
801 return g_strdup_printf ("c2-%s-", s);
802}
803
804static void
805custom2_skip (va_list *va)
806{
807 (void) va_arg (*va, char *)__builtin_va_arg(*va, char *);
808}
809
810static EelPrintfHandler handlers[] =
811{
812 { 'N', custom1_to_string, custom1_skip },
813 { 'Y', custom2_to_string, custom2_skip },
814 { 0 }
815};
816
817static void
818verify_custom (const char *orig, const char *format, ...)
819{
820 char *new;
821 va_list va;
822
823 va_start (va, format)__builtin_va_start(va, format);
824 new = eel_strdup_vprintf_with_custom (handlers, format, va);
825 va_end (va)__builtin_va_end(va);
826
827 EEL_CHECK_STRING_RESULT (new, orig)do { eel_before_check ("new", "eel-string.c", 827); eel_check_string_result
(new, orig); } while (0)
;
828}
829
830void
831eel_self_check_string (void)
832{
833 EEL_CHECK_INTEGER_RESULT (eel_strlen (NULL), 0)do { eel_before_check ("eel_strlen (((void*)0))", "eel-string.c"
, 833); eel_check_integer_result (eel_strlen (((void*)0)), 0)
; } while (0)
;
834 EEL_CHECK_INTEGER_RESULT (eel_strlen (""), 0)do { eel_before_check ("eel_strlen (\"\")", "eel-string.c", 834
); eel_check_integer_result (eel_strlen (""), 0); } while (0)
;
835 EEL_CHECK_INTEGER_RESULT (eel_strlen ("abc"), 3)do { eel_before_check ("eel_strlen (\"abc\")", "eel-string.c"
, 835); eel_check_integer_result (eel_strlen ("abc"), 3); } while
(0)
;
836
837 EEL_CHECK_INTEGER_RESULT (eel_strcmp (NULL, NULL), 0)do { eel_before_check ("eel_strcmp (((void*)0), ((void*)0))",
"eel-string.c", 837); eel_check_integer_result (eel_strcmp (
((void*)0), ((void*)0)), 0); } while (0)
;
838 EEL_CHECK_INTEGER_RESULT (eel_strcmp (NULL, ""), 0)do { eel_before_check ("eel_strcmp (((void*)0), \"\")", "eel-string.c"
, 838); eel_check_integer_result (eel_strcmp (((void*)0), "")
, 0); } while (0)
;
839 EEL_CHECK_INTEGER_RESULT (eel_strcmp ("", NULL), 0)do { eel_before_check ("eel_strcmp (\"\", ((void*)0))", "eel-string.c"
, 839); eel_check_integer_result (eel_strcmp ("", ((void*)0))
, 0); } while (0)
;
840 EEL_CHECK_INTEGER_RESULT (eel_strcmp ("a", "a"), 0)do { eel_before_check ("eel_strcmp (\"a\", \"a\")", "eel-string.c"
, 840); eel_check_integer_result (eel_strcmp ("a", "a"), 0); }
while (0)
;
841 EEL_CHECK_INTEGER_RESULT (eel_strcmp ("aaab", "aaab"), 0)do { eel_before_check ("eel_strcmp (\"aaab\", \"aaab\")", "eel-string.c"
, 841); eel_check_integer_result (eel_strcmp ("aaab", "aaab")
, 0); } while (0)
;
842 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp (NULL, "a") < 0, TRUE)do { eel_before_check ("eel_strcmp (((void*)0), \"a\") < 0"
, "eel-string.c", 842); eel_check_boolean_result (eel_strcmp (
((void*)0), "a") < 0, (!(0))); } while (0)
;
843 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("a", NULL) > 0, TRUE)do { eel_before_check ("eel_strcmp (\"a\", ((void*)0)) > 0"
, "eel-string.c", 843); eel_check_boolean_result (eel_strcmp (
"a", ((void*)0)) > 0, (!(0))); } while (0)
;
844 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("", "a") < 0, TRUE)do { eel_before_check ("eel_strcmp (\"\", \"a\") < 0", "eel-string.c"
, 844); eel_check_boolean_result (eel_strcmp ("", "a") < 0
, (!(0))); } while (0)
;
845 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("a", "") > 0, TRUE)do { eel_before_check ("eel_strcmp (\"a\", \"\") > 0", "eel-string.c"
, 845); eel_check_boolean_result (eel_strcmp ("a", "") > 0
, (!(0))); } while (0)
;
846 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("a", "b") < 0, TRUE)do { eel_before_check ("eel_strcmp (\"a\", \"b\") < 0", "eel-string.c"
, 846); eel_check_boolean_result (eel_strcmp ("a", "b") < 0
, (!(0))); } while (0)
;
847 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("a", "ab") < 0, TRUE)do { eel_before_check ("eel_strcmp (\"a\", \"ab\") < 0", "eel-string.c"
, 847); eel_check_boolean_result (eel_strcmp ("a", "ab") <
0, (!(0))); } while (0)
;
848 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("ab", "a") > 0, TRUE)do { eel_before_check ("eel_strcmp (\"ab\", \"a\") > 0", "eel-string.c"
, 848); eel_check_boolean_result (eel_strcmp ("ab", "a") >
0, (!(0))); } while (0)
;
849 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("aaa", "aaab") < 0, TRUE)do { eel_before_check ("eel_strcmp (\"aaa\", \"aaab\") < 0"
, "eel-string.c", 849); eel_check_boolean_result (eel_strcmp (
"aaa", "aaab") < 0, (!(0))); } while (0)
;
850 EEL_CHECK_BOOLEAN_RESULT (eel_strcmp ("aaab", "aaa") > 0, TRUE)do { eel_before_check ("eel_strcmp (\"aaab\", \"aaa\") > 0"
, "eel-string.c", 850); eel_check_boolean_result (eel_strcmp (
"aaab", "aaa") > 0, (!(0))); } while (0)
;
851
852 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix (NULL, NULL), TRUE)do { eel_before_check ("eel_str_has_prefix (((void*)0), ((void*)0))"
, "eel-string.c", 852); eel_check_boolean_result (eel_str_has_prefix
(((void*)0), ((void*)0)), (!(0))); } while (0)
;
853 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix (NULL, ""), TRUE)do { eel_before_check ("eel_str_has_prefix (((void*)0), \"\")"
, "eel-string.c", 853); eel_check_boolean_result (eel_str_has_prefix
(((void*)0), ""), (!(0))); } while (0)
;
854 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("", NULL), TRUE)do { eel_before_check ("eel_str_has_prefix (\"\", ((void*)0))"
, "eel-string.c", 854); eel_check_boolean_result (eel_str_has_prefix
("", ((void*)0)), (!(0))); } while (0)
;
855 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("a", "a"), TRUE)do { eel_before_check ("eel_str_has_prefix (\"a\", \"a\")", "eel-string.c"
, 855); eel_check_boolean_result (eel_str_has_prefix ("a", "a"
), (!(0))); } while (0)
;
856 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("aaab", "aaab"), TRUE)do { eel_before_check ("eel_str_has_prefix (\"aaab\", \"aaab\")"
, "eel-string.c", 856); eel_check_boolean_result (eel_str_has_prefix
("aaab", "aaab"), (!(0))); } while (0)
;
857 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix (NULL, "a"), FALSE)do { eel_before_check ("eel_str_has_prefix (((void*)0), \"a\")"
, "eel-string.c", 857); eel_check_boolean_result (eel_str_has_prefix
(((void*)0), "a"), (0)); } while (0)
;
858 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("a", NULL), TRUE)do { eel_before_check ("eel_str_has_prefix (\"a\", ((void*)0))"
, "eel-string.c", 858); eel_check_boolean_result (eel_str_has_prefix
("a", ((void*)0)), (!(0))); } while (0)
;
859 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("", "a"), FALSE)do { eel_before_check ("eel_str_has_prefix (\"\", \"a\")", "eel-string.c"
, 859); eel_check_boolean_result (eel_str_has_prefix ("", "a"
), (0)); } while (0)
;
860 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("a", ""), TRUE)do { eel_before_check ("eel_str_has_prefix (\"a\", \"\")", "eel-string.c"
, 860); eel_check_boolean_result (eel_str_has_prefix ("a", ""
), (!(0))); } while (0)
;
861 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("a", "b"), FALSE)do { eel_before_check ("eel_str_has_prefix (\"a\", \"b\")", "eel-string.c"
, 861); eel_check_boolean_result (eel_str_has_prefix ("a", "b"
), (0)); } while (0)
;
862 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("a", "ab"), FALSE)do { eel_before_check ("eel_str_has_prefix (\"a\", \"ab\")", "eel-string.c"
, 862); eel_check_boolean_result (eel_str_has_prefix ("a", "ab"
), (0)); } while (0)
;
863 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("ab", "a"), TRUE)do { eel_before_check ("eel_str_has_prefix (\"ab\", \"a\")", "eel-string.c"
, 863); eel_check_boolean_result (eel_str_has_prefix ("ab", "a"
), (!(0))); } while (0)
;
864 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("aaa", "aaab"), FALSE)do { eel_before_check ("eel_str_has_prefix (\"aaa\", \"aaab\")"
, "eel-string.c", 864); eel_check_boolean_result (eel_str_has_prefix
("aaa", "aaab"), (0)); } while (0)
;
865 EEL_CHECK_BOOLEAN_RESULT (eel_str_has_prefix ("aaab", "aaa"), TRUE)do { eel_before_check ("eel_str_has_prefix (\"aaab\", \"aaa\")"
, "eel-string.c", 865); eel_check_boolean_result (eel_str_has_prefix
("aaab", "aaa"), (!(0))); } while (0)
;
866
867 EEL_CHECK_STRING_RESULT (eel_str_get_prefix (NULL, NULL), NULL)do { eel_before_check ("eel_str_get_prefix (((void*)0), ((void*)0))"
, "eel-string.c", 867); eel_check_string_result (eel_str_get_prefix
(((void*)0), ((void*)0)), ((void*)0)); } while (0)
;
868 EEL_CHECK_STRING_RESULT (eel_str_get_prefix (NULL, "foo"), NULL)do { eel_before_check ("eel_str_get_prefix (((void*)0), \"foo\")"
, "eel-string.c", 868); eel_check_string_result (eel_str_get_prefix
(((void*)0), "foo"), ((void*)0)); } while (0)
;
869 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("foo", NULL), "foo")do { eel_before_check ("eel_str_get_prefix (\"foo\", ((void*)0))"
, "eel-string.c", 869); eel_check_string_result (eel_str_get_prefix
("foo", ((void*)0)), "foo"); } while (0)
;
870 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("", ""), "")do { eel_before_check ("eel_str_get_prefix (\"\", \"\")", "eel-string.c"
, 870); eel_check_string_result (eel_str_get_prefix ("", ""),
""); } while (0)
;
871 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("", "foo"), "")do { eel_before_check ("eel_str_get_prefix (\"\", \"foo\")", "eel-string.c"
, 871); eel_check_string_result (eel_str_get_prefix ("", "foo"
), ""); } while (0)
;
872 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("foo", ""), "")do { eel_before_check ("eel_str_get_prefix (\"foo\", \"\")", "eel-string.c"
, 872); eel_check_string_result (eel_str_get_prefix ("foo", ""
), ""); } while (0)
;
873 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("foo", "foo"), "")do { eel_before_check ("eel_str_get_prefix (\"foo\", \"foo\")"
, "eel-string.c", 873); eel_check_string_result (eel_str_get_prefix
("foo", "foo"), ""); } while (0)
;
874 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("foo:", ":"), "foo")do { eel_before_check ("eel_str_get_prefix (\"foo:\", \":\")"
, "eel-string.c", 874); eel_check_string_result (eel_str_get_prefix
("foo:", ":"), "foo"); } while (0)
;
875 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("foo:bar", ":"), "foo")do { eel_before_check ("eel_str_get_prefix (\"foo:bar\", \":\")"
, "eel-string.c", 875); eel_check_string_result (eel_str_get_prefix
("foo:bar", ":"), "foo"); } while (0)
;
876 EEL_CHECK_STRING_RESULT (eel_str_get_prefix ("footle:bar", "tle:"), "foo")do { eel_before_check ("eel_str_get_prefix (\"footle:bar\", \"tle:\")"
, "eel-string.c", 876); eel_check_string_result (eel_str_get_prefix
("footle:bar", "tle:"), "foo"); } while (0)
;
877
878 EEL_CHECK_STRING_RESULT (eel_str_double_underscores (NULL), NULL)do { eel_before_check ("eel_str_double_underscores (((void*)0))"
, "eel-string.c", 878); eel_check_string_result (eel_str_double_underscores
(((void*)0)), ((void*)0)); } while (0)
;
879 EEL_CHECK_STRING_RESULT (eel_str_double_underscores (""), "")do { eel_before_check ("eel_str_double_underscores (\"\")", "eel-string.c"
, 879); eel_check_string_result (eel_str_double_underscores (
""), ""); } while (0)
;
880 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_"), "__")do { eel_before_check ("eel_str_double_underscores (\"_\")", "eel-string.c"
, 880); eel_check_string_result (eel_str_double_underscores (
"_"), "__"); } while (0)
;
881 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo"), "foo")do { eel_before_check ("eel_str_double_underscores (\"foo\")"
, "eel-string.c", 881); eel_check_string_result (eel_str_double_underscores
("foo"), "foo"); } while (0)
;
882 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar"), "foo__bar")do { eel_before_check ("eel_str_double_underscores (\"foo_bar\")"
, "eel-string.c", 882); eel_check_string_result (eel_str_double_underscores
("foo_bar"), "foo__bar"); } while (0)
;
883 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar_2"), "foo__bar__2")do { eel_before_check ("eel_str_double_underscores (\"foo_bar_2\")"
, "eel-string.c", 883); eel_check_string_result (eel_str_double_underscores
("foo_bar_2"), "foo__bar__2"); } while (0)
;
884 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_foo"), "__foo")do { eel_before_check ("eel_str_double_underscores (\"_foo\")"
, "eel-string.c", 884); eel_check_string_result (eel_str_double_underscores
("_foo"), "__foo"); } while (0)
;
885 EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_"), "foo__")do { eel_before_check ("eel_str_double_underscores (\"foo_\")"
, "eel-string.c", 885); eel_check_string_result (eel_str_double_underscores
("foo_"), "foo__"); } while (0)
;
886
887 EEL_CHECK_STRING_RESULT (eel_str_capitalize (NULL), NULL)do { eel_before_check ("eel_str_capitalize (((void*)0))", "eel-string.c"
, 887); eel_check_string_result (eel_str_capitalize (((void*)
0)), ((void*)0)); } while (0)
;
888 EEL_CHECK_STRING_RESULT (eel_str_capitalize (""), "")do { eel_before_check ("eel_str_capitalize (\"\")", "eel-string.c"
, 888); eel_check_string_result (eel_str_capitalize (""), "")
; } while (0)
;
889 EEL_CHECK_STRING_RESULT (eel_str_capitalize ("foo"), "Foo")do { eel_before_check ("eel_str_capitalize (\"foo\")", "eel-string.c"
, 889); eel_check_string_result (eel_str_capitalize ("foo"), "Foo"
); } while (0)
;
890 EEL_CHECK_STRING_RESULT (eel_str_capitalize ("Foo"), "Foo")do { eel_before_check ("eel_str_capitalize (\"Foo\")", "eel-string.c"
, 890); eel_check_string_result (eel_str_capitalize ("Foo"), "Foo"
); } while (0)
;
891
892 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 0), "foo")do { eel_before_check ("eel_str_middle_truncate (\"foo\", 0)"
, "eel-string.c", 892); eel_check_string_result (eel_str_middle_truncate
("foo", 0), "foo"); } while (0)
;
893 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 1), "foo")do { eel_before_check ("eel_str_middle_truncate (\"foo\", 1)"
, "eel-string.c", 893); eel_check_string_result (eel_str_middle_truncate
("foo", 1), "foo"); } while (0)
;
894 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 3), "foo")do { eel_before_check ("eel_str_middle_truncate (\"foo\", 3)"
, "eel-string.c", 894); eel_check_string_result (eel_str_middle_truncate
("foo", 3), "foo"); } while (0)
;
895 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 4), "foo")do { eel_before_check ("eel_str_middle_truncate (\"foo\", 4)"
, "eel-string.c", 895); eel_check_string_result (eel_str_middle_truncate
("foo", 4), "foo"); } while (0)
;
896 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 5), "foo")do { eel_before_check ("eel_str_middle_truncate (\"foo\", 5)"
, "eel-string.c", 896); eel_check_string_result (eel_str_middle_truncate
("foo", 5), "foo"); } while (0)
;
897 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 6), "foo")do { eel_before_check ("eel_str_middle_truncate (\"foo\", 6)"
, "eel-string.c", 897); eel_check_string_result (eel_str_middle_truncate
("foo", 6), "foo"); } while (0)
;
898 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 7), "foo")do { eel_before_check ("eel_str_middle_truncate (\"foo\", 7)"
, "eel-string.c", 898); eel_check_string_result (eel_str_middle_truncate
("foo", 7), "foo"); } while (0)
;
899 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 0), "a_much_longer_foo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 0)"
, "eel-string.c", 899); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 0), "a_much_longer_foo"); } while (0)
;
900 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 1), "a_much_longer_foo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 1)"
, "eel-string.c", 900); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 1), "a_much_longer_foo"); } while (0)
;
901 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 2), "a_much_longer_foo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 2)"
, "eel-string.c", 901); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 2), "a_much_longer_foo"); } while (0)
;
902 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 3), "a_much_longer_foo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 3)"
, "eel-string.c", 902); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 3), "a_much_longer_foo"); } while (0)
;
903 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 4), "a_much_longer_foo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 4)"
, "eel-string.c", 903); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 4), "a_much_longer_foo"); } while (0)
;
904 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 5), "a...o")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 5)"
, "eel-string.c", 904); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 5), "a...o"); } while (0)
;
905 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 6), "a...oo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 6)"
, "eel-string.c", 905); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 6), "a...oo"); } while (0)
;
906 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 7), "a_...oo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 7)"
, "eel-string.c", 906); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 7), "a_...oo"); } while (0)
;
907 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 8), "a_...foo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 8)"
, "eel-string.c", 907); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 8), "a_...foo"); } while (0)
;
908 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 9), "a_m...foo")do { eel_before_check ("eel_str_middle_truncate (\"a_much_longer_foo\", 9)"
, "eel-string.c", 908); eel_check_string_result (eel_str_middle_truncate
("a_much_longer_foo", 9), "a_m...foo"); } while (0)
;
909 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 8), "so...ven")do { eel_before_check ("eel_str_middle_truncate (\"something_even\", 8)"
, "eel-string.c", 909); eel_check_string_result (eel_str_middle_truncate
("something_even", 8), "so...ven"); } while (0)
;
910 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 8), "so...odd")do { eel_before_check ("eel_str_middle_truncate (\"something_odd\", 8)"
, "eel-string.c", 910); eel_check_string_result (eel_str_middle_truncate
("something_odd", 8), "so...odd"); } while (0)
;
911 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 9), "som...ven")do { eel_before_check ("eel_str_middle_truncate (\"something_even\", 9)"
, "eel-string.c", 911); eel_check_string_result (eel_str_middle_truncate
("something_even", 9), "som...ven"); } while (0)
;
912 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 9), "som...odd")do { eel_before_check ("eel_str_middle_truncate (\"something_odd\", 9)"
, "eel-string.c", 912); eel_check_string_result (eel_str_middle_truncate
("something_odd", 9), "som...odd"); } while (0)
;
913 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 10), "som...even")do { eel_before_check ("eel_str_middle_truncate (\"something_even\", 10)"
, "eel-string.c", 913); eel_check_string_result (eel_str_middle_truncate
("something_even", 10), "som...even"); } while (0)
;
914 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 10), "som..._odd")do { eel_before_check ("eel_str_middle_truncate (\"something_odd\", 10)"
, "eel-string.c", 914); eel_check_string_result (eel_str_middle_truncate
("something_odd", 10), "som..._odd"); } while (0)
;
915 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 11), "some...even")do { eel_before_check ("eel_str_middle_truncate (\"something_even\", 11)"
, "eel-string.c", 915); eel_check_string_result (eel_str_middle_truncate
("something_even", 11), "some...even"); } while (0)
;
916 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 11), "some..._odd")do { eel_before_check ("eel_str_middle_truncate (\"something_odd\", 11)"
, "eel-string.c", 916); eel_check_string_result (eel_str_middle_truncate
("something_odd", 11), "some..._odd"); } while (0)
;
917 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 12), "some..._even")do { eel_before_check ("eel_str_middle_truncate (\"something_even\", 12)"
, "eel-string.c", 917); eel_check_string_result (eel_str_middle_truncate
("something_even", 12), "some..._even"); } while (0)
;
918 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 12), "some...g_odd")do { eel_before_check ("eel_str_middle_truncate (\"something_odd\", 12)"
, "eel-string.c", 918); eel_check_string_result (eel_str_middle_truncate
("something_odd", 12), "some...g_odd"); } while (0)
;
919 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 13), "somet..._even")do { eel_before_check ("eel_str_middle_truncate (\"something_even\", 13)"
, "eel-string.c", 919); eel_check_string_result (eel_str_middle_truncate
("something_even", 13), "somet..._even"); } while (0)
;
920 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd")do { eel_before_check ("eel_str_middle_truncate (\"something_odd\", 13)"
, "eel-string.c", 920); eel_check_string_result (eel_str_middle_truncate
("something_odd", 13), "something_odd"); } while (0)
;
921 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 14), "something_even")do { eel_before_check ("eel_str_middle_truncate (\"something_even\", 14)"
, "eel-string.c", 921); eel_check_string_result (eel_str_middle_truncate
("something_even", 14), "something_even"); } while (0)
;
922 EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd")do { eel_before_check ("eel_str_middle_truncate (\"something_odd\", 13)"
, "eel-string.c", 922); eel_check_string_result (eel_str_middle_truncate
("something_odd", 13), "something_odd"); } while (0)
;
923
924 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after (NULL, "bar"), NULL)do { eel_before_check ("eel_str_strip_substring_and_after (((void*)0), \"bar\")"
, "eel-string.c", 924); eel_check_string_result (eel_str_strip_substring_and_after
(((void*)0), "bar"), ((void*)0)); } while (0)
;
925 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("", "bar"), "")do { eel_before_check ("eel_str_strip_substring_and_after (\"\", \"bar\")"
, "eel-string.c", 925); eel_check_string_result (eel_str_strip_substring_and_after
("", "bar"), ""); } while (0)
;
926 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo", "bar"), "foo")do { eel_before_check ("eel_str_strip_substring_and_after (\"foo\", \"bar\")"
, "eel-string.c", 926); eel_check_string_result (eel_str_strip_substring_and_after
("foo", "bar"), "foo"); } while (0)
;
927 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar", "bar"), "foo ")do { eel_before_check ("eel_str_strip_substring_and_after (\"foo bar\", \"bar\")"
, "eel-string.c", 927); eel_check_string_result (eel_str_strip_substring_and_after
("foo bar", "bar"), "foo "); } while (0)
;
928 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar xxx", "bar"), "foo ")do { eel_before_check ("eel_str_strip_substring_and_after (\"foo bar xxx\", \"bar\")"
, "eel-string.c", 928); eel_check_string_result (eel_str_strip_substring_and_after
("foo bar xxx", "bar"), "foo "); } while (0)
;
929 EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("bar", "bar"), "")do { eel_before_check ("eel_str_strip_substring_and_after (\"bar\", \"bar\")"
, "eel-string.c", 929); eel_check_string_result (eel_str_strip_substring_and_after
("bar", "bar"), ""); } while (0)
;
930
931 EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", NULL), NULL)do { eel_before_check ("eel_str_replace_substring (((void*)0), \"foo\", ((void*)0))"
, "eel-string.c", 931); eel_check_string_result (eel_str_replace_substring
(((void*)0), "foo", ((void*)0)), ((void*)0)); } while (0)
;
932 EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", "bar"), NULL)do { eel_before_check ("eel_str_replace_substring (((void*)0), \"foo\", \"bar\")"
, "eel-string.c", 932); eel_check_string_result (eel_str_replace_substring
(((void*)0), "foo", "bar"), ((void*)0)); } while (0)
;
933 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", NULL), "bar")do { eel_before_check ("eel_str_replace_substring (\"bar\", \"foo\", ((void*)0))"
, "eel-string.c", 933); eel_check_string_result (eel_str_replace_substring
("bar", "foo", ((void*)0)), "bar"); } while (0)
;
934 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", ""), "")do { eel_before_check ("eel_str_replace_substring (\"\", \"foo\", \"\")"
, "eel-string.c", 934); eel_check_string_result (eel_str_replace_substring
("", "foo", ""), ""); } while (0)
;
935 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", "bar"), "")do { eel_before_check ("eel_str_replace_substring (\"\", \"foo\", \"bar\")"
, "eel-string.c", 935); eel_check_string_result (eel_str_replace_substring
("", "foo", "bar"), ""); } while (0)
;
936 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", ""), "bar")do { eel_before_check ("eel_str_replace_substring (\"bar\", \"foo\", \"\")"
, "eel-string.c", 936); eel_check_string_result (eel_str_replace_substring
("bar", "foo", ""), "bar"); } while (0)
;
937 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("xxx", "x", "foo"), "foofoofoo")do { eel_before_check ("eel_str_replace_substring (\"xxx\", \"x\", \"foo\")"
, "eel-string.c", 937); eel_check_string_result (eel_str_replace_substring
("xxx", "x", "foo"), "foofoofoo"); } while (0)
;
938 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("fff", "f", "foo"), "foofoofoo")do { eel_before_check ("eel_str_replace_substring (\"fff\", \"f\", \"foo\")"
, "eel-string.c", 938); eel_check_string_result (eel_str_replace_substring
("fff", "f", "foo"), "foofoofoo"); } while (0)
;
939 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "foo", "f"), "fff")do { eel_before_check ("eel_str_replace_substring (\"foofoofoo\", \"foo\", \"f\")"
, "eel-string.c", 939); eel_check_string_result (eel_str_replace_substring
("foofoofoo", "foo", "f"), "fff"); } while (0)
;
940 EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "f", ""), "oooooo")do { eel_before_check ("eel_str_replace_substring (\"foofoofoo\", \"f\", \"\")"
, "eel-string.c", 940); eel_check_string_result (eel_str_replace_substring
("foofoofoo", "f", ""), "oooooo"); } while (0)
;
941
942 verify_printf ("%.*s", 2, "foo");
943 verify_printf ("%*.*s", 2, 4, "foo");
944 verify_printf ("before %5$*1$.*2$s between %6$*3$.*4$d after",
945 4, 5, 6, 7, "foo", G_PI3.1415926535897932384626433832795028841971693993751);
946 verify_custom ("c1-42- c2-foo-","%N %Y", 42 ,"foo");
947 verify_custom ("c1-42- bar c2-foo-","%N %s %Y", 42, "bar" ,"foo");
948 verify_custom ("c1-42- bar c2-foo-","%3$N %2$s %1$Y","foo", "bar", 42);
949
950}
951
952#endif /* !EEL_OMIT_SELF_CHECK */
diff --git a/2024-07-29-023715-6438-1/report-c35402.html b/2024-07-29-023715-6438-1/report-c35402.html new file mode 100644 index 000000000..a1ba6eda9 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-c35402.html @@ -0,0 +1,9582 @@ + + + +caja-file.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file.c
Warning:line 1192, column 2
Value stored to 'ret' 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 caja-file.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 caja-file.c: Caja file model.
4
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Author: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <grp.h>
27#include <gtk/gtk.h>
28#include <glib/gi18n.h>
29#include <glib/gstdio.h>
30#include <gio/gio.h>
31#include <glib.h>
32#include <libxml/parser.h>
33#include <pwd.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <sys/time.h>
37#include <time.h>
38#include <unistd.h>
39#include <sys/stat.h>
40
41#include <eel/eel-debug.h>
42#include <eel/eel-glib-extensions.h>
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-vfs-extensions.h>
45#include <eel/eel-gtk-macros.h>
46#include <eel/eel-string.h>
47
48#include <libcaja-extension/caja-file-info.h>
49#include <libcaja-extension/caja-extension-private.h>
50#include <libcaja-private/caja-extensions.h>
51
52#include "caja-file.h"
53#include "caja-directory-notify.h"
54#include "caja-directory-private.h"
55#include "caja-signaller.h"
56#include "caja-desktop-directory.h"
57#include "caja-desktop-directory-file.h"
58#include "caja-desktop-icon-file.h"
59#include "caja-file-attributes.h"
60#include "caja-file-private.h"
61#include "caja-file-operations.h"
62#include "caja-file-utilities.h"
63#include "caja-global-preferences.h"
64#include "caja-lib-self-check-functions.h"
65#include "caja-link.h"
66#include "caja-metadata.h"
67#include "caja-module.h"
68#include "caja-search-directory.h"
69#include "caja-search-directory-file.h"
70#include "caja-thumbnails.h"
71#include "caja-ui-utilities.h"
72#include "caja-vfs-file.h"
73#include "caja-saved-search-file.h"
74
75#ifdef HAVE_SELINUX1
76#include <selinux/selinux.h>
77#endif
78
79#define ICON_NAME_THUMBNAIL_LOADING"image-loading" "image-loading"
80
81#undef CAJA_FILE_DEBUG_REF
82#undef CAJA_FILE_DEBUG_REF_VALGRIND
83
84#ifdef CAJA_FILE_DEBUG_REF_VALGRIND
85#include <valgrind/valgrind.h>
86#define DEBUG_REF_PRINTFprintf VALGRIND_PRINTF_BACKTRACE
87#else
88#define DEBUG_REF_PRINTFprintf printf
89#endif
90
91/* Files that start with these characters sort after files that don't. */
92#define SORT_LAST_CHAR1'.' '.'
93#define SORT_LAST_CHAR2'#' '#'
94
95#define METADATA_ID_IS_LIST_MASK(1U<<31) (1U<<31)
96
97#define SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3 3
98#define SORT_BY_EXTENSION_MAX_SEGMENTS3 3
99
100typedef enum {
101 SHOW_HIDDEN = 1 << 0,
102 SHOW_BACKUP = 1 << 1,
103} FilterOptions;
104
105typedef void (* ModifyListFunction) (GList **list, CajaFile *file);
106
107enum {
108 CHANGED,
109 UPDATED_DEEP_COUNT_IN_PROGRESS,
110 LAST_SIGNAL
111};
112
113static int date_format_pref;
114
115static guint signals[LAST_SIGNAL] = { 0 };
116
117static GHashTable *symbolic_links;
118
119static GQuark attribute_name_q,
120 attribute_size_q,
121 attribute_size_on_disk_q,
122 attribute_type_q,
123 attribute_creation_date_q,
124 attribute_date_created_q,
125 attribute_modification_date_q,
126 attribute_date_modified_q,
127 attribute_accessed_date_q,
128 attribute_date_accessed_q,
129 attribute_emblems_q,
130 attribute_extension_q,
131 attribute_mime_type_q,
132 attribute_size_detail_q,
133 attribute_size_on_disk_detail_q,
134 attribute_deep_size_q,
135 attribute_deep_size_on_disk_q,
136 attribute_deep_file_count_q,
137 attribute_deep_directory_count_q,
138 attribute_deep_total_count_q,
139 attribute_date_changed_q,
140 attribute_trashed_on_q,
141 attribute_trash_orig_path_q,
142 attribute_date_permissions_q,
143 attribute_permissions_q,
144 attribute_selinux_context_q,
145 attribute_octal_permissions_q,
146 attribute_owner_q,
147 attribute_group_q,
148 attribute_uri_q,
149 attribute_where_q,
150 attribute_link_target_q,
151 attribute_volume_q,
152 attribute_free_space_q;
153
154static void caja_file_info_iface_init (CajaFileInfoIface *iface);
155static char * caja_file_get_owner_as_string (CajaFile *file,
156 gboolean include_real_name);
157static char * caja_file_get_type_as_string (CajaFile *file);
158static gboolean update_info_and_name (CajaFile *file,
159 GFileInfo *info);
160static const char * caja_file_peek_display_name (CajaFile *file);
161static const char * caja_file_peek_display_name_collation_key (CajaFile *file);
162static void file_mount_unmounted (GMount *mount, gpointer data);
163static void metadata_hash_free (GHashTable *hash);
164
165G_DEFINE_TYPE_WITH_CODE (CajaFile, caja_file, G_TYPE_OBJECT,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
166 G_ADD_PRIVATE (CajaFile)static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
167 G_IMPLEMENT_INTERFACE (CAJA_TYPE_FILE_INFO,static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
168 caja_file_info_iface_init))static void caja_file_init (CajaFile *self); static void caja_file_class_init
(CajaFileClass *klass); static GType caja_file_get_type_once
(void); static gpointer caja_file_parent_class = ((void*)0);
static gint CajaFile_private_offset; static void caja_file_class_intern_init
(gpointer klass) { caja_file_parent_class = g_type_class_peek_parent
(klass); if (CajaFile_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaFile_private_offset); caja_file_class_init (
(CajaFileClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer caja_file_get_instance_private (CajaFile *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CajaFile_private_offset
)))); } GType caja_file_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_file_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_file_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple (((GType
) ((20) << (2))), g_intern_static_string ("CajaFile"), sizeof
(CajaFileClass), (GClassInitFunc)(void (*)(void)) caja_file_class_intern_init
, sizeof (CajaFile), (GInstanceInitFunc)(void (*)(void)) caja_file_init
, (GTypeFlags) 0); { {{ CajaFile_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaFilePrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) caja_file_info_iface_init, ((void*)0), ((void*)0) }; g_type_add_interface_static
(g_define_type_id, (caja_file_info_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
;
169
170static void
171caja_file_init (CajaFile *file)
172{
173 file->details = caja_file_get_instance_private (file);
174
175 caja_file_clear_info (file);
176 caja_file_invalidate_extension_info_internal (file);
177}
178
179static GObject*
180caja_file_constructor (GType type,
181 guint n_construct_properties,
182 GObjectConstructParam *construct_params)
183{
184 GObject *object;
185 CajaFile *file;
186
187 object = (* G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->constructor) (type,
188 n_construct_properties,
189 construct_params);
190
191 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
192
193 /* Set to default type after full construction */
194 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type != G_FILE_TYPE_UNKNOWN) {
195 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
196 }
197
198 return object;
199}
200
201gboolean
202caja_file_set_display_name (CajaFile *file,
203 const char *display_name,
204 const char *edit_name,
205 gboolean custom)
206{
207 gboolean changed;
208
209 if (custom && display_name == NULL((void*)0)) {
210 /* We're re-setting a custom display name, invalidate it if
211 we already set it so that the old one is re-read */
212 if (file->details->got_custom_display_name) {
213 file->details->got_custom_display_name = FALSE(0);
214 caja_file_invalidate_attributes (file,
215 CAJA_FILE_ATTRIBUTE_INFO);
216 }
217 return FALSE(0);
218 }
219
220 if (display_name == NULL((void*)0) || *display_name == 0) {
221 return FALSE(0);
222 }
223
224 if (!custom && file->details->got_custom_display_name) {
225 return FALSE(0);
226 }
227
228 if (edit_name == NULL((void*)0)) {
229 edit_name = display_name;
230 }
231
232 changed = FALSE(0);
233
234 if (eel_strcmp (file->details->display_name, display_name) != 0) {
235 changed = TRUE(!(0));
236
237 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
238
239 if (eel_strcmp (file->details->name, display_name) == 0) {
240 file->details->display_name = g_ref_string_acquire (file->details->name);
241 } else {
242 file->details->display_name = g_ref_string_new (display_name);
243 }
244
245 g_free (file->details->display_name_collation_key);
246 file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1);
247 }
248
249 if (eel_strcmp (file->details->edit_name, edit_name) != 0) {
250 changed = TRUE(!(0));
251
252 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
253 if (eel_strcmp (file->details->display_name, edit_name) == 0) {
254 file->details->edit_name = g_ref_string_acquire (file->details->display_name);
255 } else {
256 file->details->edit_name = g_ref_string_new (edit_name);
257 }
258 }
259
260 file->details->got_custom_display_name = custom;
261 return changed;
262}
263
264static void
265caja_file_clear_display_name (CajaFile *file)
266{
267 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
268 file->details->display_name = NULL((void*)0);
269 g_free (file->details->display_name_collation_key);
270 file->details->display_name_collation_key = NULL((void*)0);
271 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
272 file->details->edit_name = NULL((void*)0);
273}
274
275static gboolean
276foreach_metadata_free (gpointer key,
277 gpointer value,
278 gpointer user_data)
279{
280 guint id;
281
282 id = GPOINTER_TO_UINT (key)((guint) (gulong) (key));
283
284 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
285 g_strfreev ((char **)value);
286 } else {
287 g_free ((char *)value);
288 }
289 return TRUE(!(0));
290}
291
292
293static void
294metadata_hash_free (GHashTable *hash)
295{
296 g_hash_table_foreach_remove (hash,
297 foreach_metadata_free,
298 NULL((void*)0));
299 g_hash_table_destroy (hash);
300}
301
302static gboolean
303metadata_hash_equal (GHashTable *hash1,
304 GHashTable *hash2)
305{
306 GHashTableIter iter;
307 gpointer key1, value1, value2;
308 guint id;
309
310 if (hash1 == NULL((void*)0) && hash2 == NULL((void*)0)) {
311 return TRUE(!(0));
312 }
313
314 if (hash1 == NULL((void*)0) || hash2 == NULL((void*)0)) {
315 return FALSE(0);
316 }
317
318 if (g_hash_table_size (hash1) !=
319 g_hash_table_size (hash2)) {
320 return FALSE(0);
321 }
322
323 g_hash_table_iter_init (&iter, hash1);
324 while (g_hash_table_iter_next (&iter, &key1, &value1)) {
325 value2 = g_hash_table_lookup (hash2, key1);
326 if (value2 == NULL((void*)0)) {
327 return FALSE(0);
328 }
329 id = GPOINTER_TO_UINT (key1)((guint) (gulong) (key1));
330 if (id & METADATA_ID_IS_LIST_MASK(1U<<31)) {
331 if (!eel_g_strv_equal ((char **)value1, (char **)value2)) {
332 return FALSE(0);
333 }
334 } else {
335 if (strcmp ((char *)value1, (char *)value2) != 0) {
336 return FALSE(0);
337 }
338 }
339 }
340
341 return TRUE(!(0));
342}
343
344static void
345clear_metadata (CajaFile *file)
346{
347 if (file->details->metadata) {
348 metadata_hash_free (file->details->metadata);
349 file->details->metadata = NULL((void*)0);
350 }
351}
352
353static GHashTable *
354get_metadata_from_info (GFileInfo *info)
355{
356 GHashTable *metadata;
357 char **attrs;
358 guint id;
359 int i;
360 GFileAttributeType type;
361 gpointer value;
362
363 attrs = g_file_info_list_attributes (info, "metadata");
364
365 metadata = g_hash_table_new (NULL((void*)0), NULL((void*)0));
366
367 for (i = 0; attrs[i] != NULL((void*)0); i++) {
368 id = caja_metadata_get_id (attrs[i] + strlen ("metadata::"));
369 if (id == 0) {
370 continue;
371 }
372
373 if (!g_file_info_get_attribute_data (info, attrs[i],
374 &type, &value, NULL((void*)0))) {
375 continue;
376 }
377
378 if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
379 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
380 g_strdup ((char *)value)g_strdup_inline ((char *)value));
381 } else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) {
382 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
383 g_hash_table_insert (metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)),
384 g_strdupv ((char **)value));
385 }
386 }
387
388 g_strfreev (attrs);
389
390 return metadata;
391}
392
393gboolean
394caja_file_update_metadata_from_info (CajaFile *file,
395 GFileInfo *info)
396{
397 gboolean changed = FALSE(0);
398
399 if (g_file_info_has_namespace (info, "metadata")) {
400 GHashTable *metadata;
401
402 metadata = get_metadata_from_info (info);
403 if (!metadata_hash_equal (metadata,
404 file->details->metadata)) {
405 changed = TRUE(!(0));
406 clear_metadata (file);
407 file->details->metadata = metadata;
408 } else {
409 metadata_hash_free (metadata);
410 }
411 } else if (file->details->metadata) {
412 changed = TRUE(!(0));
413 clear_metadata (file);
414 }
415 return changed;
416}
417
418void
419caja_file_clear_info (CajaFile *file)
420{
421 file->details->got_file_info = FALSE(0);
422 if (file->details->get_info_error) {
423 g_error_free (file->details->get_info_error);
424 file->details->get_info_error = NULL((void*)0);
425 }
426 /* Reset to default type, which might be other than unknown for
427 special kinds of files like the desktop or a search directory */
428 file->details->type = CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->default_file_type;
429
430 if (!file->details->got_custom_display_name) {
431 caja_file_clear_display_name (file);
432 }
433
434 if (!file->details->got_custom_activation_uri &&
435 file->details->activation_uri != NULL((void*)0)) {
436 g_free (file->details->activation_uri);
437 file->details->activation_uri = NULL((void*)0);
438 }
439
440 if (file->details->icon != NULL((void*)0)) {
441 g_object_unref (file->details->icon);
442 file->details->icon = NULL((void*)0);
443 }
444
445 g_free (file->details->thumbnail_path);
446 file->details->thumbnail_path = NULL((void*)0);
447 file->details->thumbnailing_failed = FALSE(0);
448
449 file->details->is_launcher = FALSE(0);
450 file->details->is_foreign_link = FALSE(0);
451 file->details->is_trusted_link = FALSE(0);
452 file->details->is_symlink = FALSE(0);
453 file->details->is_hidden = FALSE(0);
454 file->details->is_backup = FALSE(0);
455 file->details->is_mountpoint = FALSE(0);
456 file->details->uid = -1;
457 file->details->gid = -1;
458 file->details->can_read = TRUE(!(0));
459 file->details->can_write = TRUE(!(0));
460 file->details->can_execute = TRUE(!(0));
461 file->details->can_delete = TRUE(!(0));
462 file->details->can_trash = TRUE(!(0));
463 file->details->can_rename = TRUE(!(0));
464 file->details->can_mount = FALSE(0);
465 file->details->can_unmount = FALSE(0);
466 file->details->can_eject = FALSE(0);
467 file->details->can_start = FALSE(0);
468 file->details->can_start_degraded = FALSE(0);
469 file->details->can_stop = FALSE(0);
470 file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
471 file->details->can_poll_for_media = FALSE(0);
472 file->details->is_media_check_automatic = FALSE(0);
473 file->details->has_permissions = FALSE(0);
474 file->details->permissions = 0;
475 file->details->size = -1;
476 file->details->size_on_disk = -1;
477 file->details->sort_order = 0;
478 file->details->mtime = 0;
479 file->details->atime = 0;
480 file->details->ctime = 0;
481 file->details->btime = 0;
482 file->details->trash_time = 0;
483 g_free (file->details->symlink_name);
484 file->details->symlink_name = NULL((void*)0);
485 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
486 file->details->mime_type = NULL((void*)0);
487 g_free (file->details->selinux_context);
488 file->details->selinux_context = NULL((void*)0);
489 g_free (file->details->description);
490 file->details->description = NULL((void*)0);
491 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
492 file->details->owner = NULL((void*)0);
493 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
494 file->details->owner_real = NULL((void*)0);
495 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
496 file->details->group = NULL((void*)0);
497
498 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
499 file->details->filesystem_id = NULL((void*)0);
500
501 clear_metadata (file);
502}
503
504static CajaFile *
505caja_file_new_from_filename (CajaDirectory *directory,
506 const char *filename,
507 gboolean self_owned)
508{
509 CajaFile *file;
510
511 g_assert (CAJA_IS_DIRECTORY (directory))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 511, ((const char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"
); } while (0)
;
512 g_assert (filename != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_148
; if (filename != ((void*)0)) _g_boolean_var_148 = 1; else _g_boolean_var_148
= 0; _g_boolean_var_148; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 512, ((const char*) (__func__)
), "filename != NULL"); } while (0)
;
513 g_assert (filename[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if (filename[0] != '\0') _g_boolean_var_149 = 1; else _g_boolean_var_149
= 0; _g_boolean_var_149; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 513, ((const char*) (__func__)
), "filename[0] != '\\0'"); } while (0)
;
514
515 if (CAJA_IS_DESKTOP_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_desktop_directory_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; }
))))
) {
516 if (self_owned) {
517 file = CAJA_FILE (g_object_new (CAJA_TYPE_DESKTOP_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_desktop_directory_file_get_type
(), ((void*)0)))))))
;
518 } else {
519 /* This doesn't normally happen, unless the user somehow types in a uri
520 * that references a file like this. (See #349840) */
521 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
522 }
523 } else if (CAJA_IS_SEARCH_DIRECTORY (directory)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(directory)); GType __t = (caja_search_directory_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; }
))))
) {
524 if (self_owned) {
525 file = CAJA_FILE (g_object_new (CAJA_TYPE_SEARCH_DIRECTORY_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_search_directory_file_get_type
(), ((void*)0)))))))
;
526 } else {
527 /* This doesn't normally happen, unless the user somehow types in a uri
528 * that references a file like this. (See #349840) */
529 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
530 }
531 } else if (g_str_has_suffix (filename, CAJA_SAVED_SEARCH_EXTENSION)(__builtin_constant_p (".savedSearch")? __extension__ ({ const
char * const __str = (filename); const char * const __suffix
= (".savedSearch"); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_150; if (__str == ((void
*)0) || __suffix == ((void*)0)) _g_boolean_var_150 = 1; else _g_boolean_var_150
= 0; _g_boolean_var_150; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (filename, ".savedSearch") )
) {
532 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
533 } else {
534 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
535 }
536
537 file->details->directory = caja_directory_ref (directory);
538
539 file->details->name = g_ref_string_new (filename);
540
541#ifdef CAJA_FILE_DEBUG_REF
542 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
543#endif
544
545 return file;
546}
547
548static void
549modify_link_hash_table (CajaFile *file,
550 ModifyListFunction modify_function)
551{
552 char *target_uri;
553 gboolean found;
554 gpointer original_key;
555 GList **list_ptr;
556
557 /* Check if there is a symlink name. If none, we are OK. */
558 if (file->details->symlink_name == NULL((void*)0) || !caja_file_is_symbolic_link (file)) {
559 return;
560 }
561
562 /* Create the hash table first time through. */
563 if (symbolic_links == NULL((void*)0)) {
564 symbolic_links = g_hash_table_new (g_str_hash, g_str_equal);
565 }
566
567 target_uri = caja_file_get_symbolic_link_target_uri (file);
568
569 /* Find the old contents of the hash table. */
570 found = g_hash_table_lookup_extended
571 (symbolic_links, target_uri,
572 &original_key, (gpointer *)&list_ptr);
573 if (!found) {
574 list_ptr = g_new0 (GList *, 1)(GList * *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (GList *); 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
; }))
;
575 original_key = g_strdup (target_uri)g_strdup_inline (target_uri);
576 g_hash_table_insert (symbolic_links, original_key, list_ptr);
577 }
578 (* modify_function) (list_ptr, file);
579 if (*list_ptr == NULL((void*)0)) {
580 g_hash_table_remove (symbolic_links, target_uri);
581 g_free (list_ptr);
582 g_free (original_key);
583 }
584 g_free (target_uri);
585}
586
587static void
588symbolic_link_weak_notify (gpointer data,
589 GObject *where_the_object_was)
590{
591 GList **list = data;
592 /* This really shouldn't happen, but we're seeing some strange things in
593 bug #358172 where the symlink hashtable isn't correctly updated. */
594 *list = g_list_remove (*list, where_the_object_was);
595}
596
597static void
598add_to_link_hash_table_list (GList **list, CajaFile *file)
599{
600 if (g_list_find (*list, file) != NULL((void*)0)) {
601 g_warning ("Adding file to symlink_table multiple times. "
602 "Please add feedback of what you were doing at https://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
603 return;
604 }
605 g_object_weak_ref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
606 *list = g_list_prepend (*list, file);
607}
608
609static void
610add_to_link_hash_table (CajaFile *file)
611{
612 modify_link_hash_table (file, add_to_link_hash_table_list);
613}
614
615static void
616remove_from_link_hash_table_list (GList **list, CajaFile *file)
617{
618 if (g_list_find (*list, file) != NULL((void*)0)) {
619 g_object_weak_unref (G_OBJECT (file)((((GObject*) (void *) ((file))))), symbolic_link_weak_notify, list);
620 *list = g_list_remove (*list, file);
621 }
622}
623
624static void
625remove_from_link_hash_table (CajaFile *file)
626{
627 modify_link_hash_table (file, remove_from_link_hash_table_list);
628}
629
630CajaFile *
631caja_file_new_from_info (CajaDirectory *directory,
632 GFileInfo *info)
633{
634 CajaFile *file;
635 const char *mime_type;
636
637 g_return_val_if_fail (CAJA_IS_DIRECTORY (directory), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((directory)); GType __t = (caja_directory_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_151
= 1; else _g_boolean_var_151 = 0; _g_boolean_var_151; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_DIRECTORY (directory)"); return
(((void*)0)); } } while (0)
;
638 g_return_val_if_fail (info != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if (info != ((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__)), "info != NULL"); return
(((void*)0)); } } while (0)
;
639
640 mime_type = g_file_info_get_content_type (info);
641 if (mime_type &&
642 strcmp (mime_type, CAJA_SAVED_SEARCH_MIMETYPE"application/x-mate-saved-search") == 0) {
643 g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
644 file = CAJA_FILE (g_object_new (CAJA_TYPE_SAVED_SEARCH_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_saved_search_file_get_type
(), ((void*)0)))))))
;
645 } else {
646 file = CAJA_FILE (g_object_new (CAJA_TYPE_VFS_FILE, NULL))((((CajaFile*) (void *) ((g_object_new (caja_vfs_file_get_type
(), ((void*)0)))))))
;
647 }
648
649 file->details->directory = caja_directory_ref (directory);
650
651 update_info_and_name (file, info);
652
653#ifdef CAJA_FILE_DEBUG_REF
654 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
655#endif
656
657 return file;
658}
659
660static CajaFile *
661caja_file_get_internal (GFile *location, gboolean create)
662{
663 gboolean self_owned;
664 CajaDirectory *directory;
665 CajaFile *file;
666 GFile *parent;
667 char *basename;
668
669 g_assert (location != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if (location != ((void*)0)) _g_boolean_var_153 = 1; else _g_boolean_var_153
= 0; _g_boolean_var_153; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 669, ((const char*) (__func__)
), "location != NULL"); } while (0)
;
670
671 parent = g_file_get_parent (location);
672
673 self_owned = FALSE(0);
674 if (parent == NULL((void*)0)) {
675 self_owned = TRUE(!(0));
676 parent = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
677 }
678
679 /* Get object that represents the directory. */
680 directory = caja_directory_get_internal (parent, create);
681
682 g_object_unref (parent);
683
684 /* Get the name for the file. */
685 if (self_owned && directory != NULL((void*)0)) {
686 basename = caja_directory_get_name_for_self_as_new_file (directory);
687 } else {
688 basename = g_file_get_basename (location);
689 }
690 /* Check to see if it's a file that's already known. */
691 if (directory == NULL((void*)0)) {
692 file = NULL((void*)0);
693 } else if (self_owned) {
694 file = directory->details->as_file;
695 } else {
696 file = caja_directory_find_file_by_name (directory, basename);
697 }
698
699 /* Ref or create the file. */
700 if (file != NULL((void*)0)) {
701 caja_file_ref (file);
702 } else if (create && directory != NULL((void*)0)) {
703 file = caja_file_new_from_filename (directory, basename, self_owned);
704 if (self_owned) {
705 g_assert (directory->details->as_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if (directory->details->as_file == ((void*)0)) _g_boolean_var_154
= 1; else _g_boolean_var_154 = 0; _g_boolean_var_154; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 705, ((const char*) (__func__)), "directory->details->as_file == NULL"
); } while (0)
;
706 directory->details->as_file = file;
707 } else {
708 caja_directory_add_file (directory, file);
709 }
710 }
711
712 g_free (basename);
713 caja_directory_unref (directory);
714
715 return file;
716}
717
718CajaFile *
719caja_file_get (GFile *location)
720{
721 return caja_file_get_internal (location, TRUE(!(0)));
722}
723
724CajaFile *
725caja_file_get_existing (GFile *location)
726{
727 return caja_file_get_internal (location, FALSE(0));
728}
729
730CajaFile *
731caja_file_get_existing_by_uri (const char *uri)
732{
733 GFile *location;
734 CajaFile *file;
735
736 location = g_file_new_for_uri (uri);
737 file = caja_file_get_internal (location, FALSE(0));
738 g_object_unref (location);
739
740 return file;
741}
742
743CajaFile *
744caja_file_get_by_uri (const char *uri)
745{
746 GFile *location;
747 CajaFile *file;
748
749 location = g_file_new_for_uri (uri);
750 file = caja_file_get_internal (location, TRUE(!(0)));
751 g_object_unref (location);
752
753 return file;
754}
755
756gboolean
757caja_file_is_self_owned (CajaFile *file)
758{
759 return file->details->directory->details->as_file == file;
760}
761
762static void
763finalize (GObject *object)
764{
765 CajaDirectory *directory;
766 CajaFile *file;
767
768 file = CAJA_FILE (object)((((CajaFile*) (void *) ((object)))));
769
770 g_assert (file->details->operations_in_progress == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if (file->details->operations_in_progress == ((void*)
0)) _g_boolean_var_155 = 1; else _g_boolean_var_155 = 0; _g_boolean_var_155
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 770, ((const char*) (__func__)), "file->details->operations_in_progress == NULL"
); } while (0)
;
771
772 if (file->details->is_thumbnailing) {
773 char *uri;
774
775 uri = caja_file_get_uri (file);
776 caja_thumbnail_remove_from_queue (uri);
777 g_free (uri);
778 }
779
780 caja_async_destroying_file (file);
781
782 remove_from_link_hash_table (file);
783
784 directory = file->details->directory;
785
786 if (caja_file_is_self_owned (file)) {
787 directory->details->as_file = NULL((void*)0);
788 } else {
789 if (!file->details->is_gone) {
790 caja_directory_remove_file (directory, file);
791 }
792 }
793
794 if (file->details->get_info_error) {
795 g_error_free (file->details->get_info_error);
796 }
797
798 caja_directory_unref (directory);
799 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
800 g_clear_pointer (&file->details->display_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->display_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->display_name)) _pp = (&file->
details->display_name); __typeof__ (*(&file->details
->display_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr)
(g_ref_string_release) (_ptr); } while (0)
;
801 g_free (file->details->display_name_collation_key);
802 g_clear_pointer (&file->details->edit_name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->edit_name
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->edit_name)) _pp = (&file->
details->edit_name); __typeof__ (*(&file->details->
edit_name)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
803 if (file->details->icon) {
804 g_object_unref (file->details->icon);
805 }
806 g_free (file->details->thumbnail_path);
807 g_free (file->details->symlink_name);
808 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
809 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
810 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
811 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
812 g_free (file->details->selinux_context);
813 g_free (file->details->description);
814 g_free (file->details->top_left_text);
815 g_free (file->details->custom_icon);
816 g_free (file->details->activation_uri);
817 g_free (file->details->compare_by_emblem_cache);
818
819 if (file->details->thumbnail) {
820 g_object_unref (file->details->thumbnail);
821 }
822 if (file->details->mount) {
823 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
824 g_object_unref (file->details->mount);
825 }
826
827 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
828
829 g_list_free_full (file->details->mime_list, g_free);
830 g_list_free_full (file->details->pending_extension_emblems, g_free);
831 g_list_free_full (file->details->extension_emblems, g_free);
832 g_list_free_full (file->details->pending_info_providers, g_object_unref);
833
834 if (file->details->pending_extension_attributes) {
835 g_hash_table_destroy (file->details->pending_extension_attributes);
836 }
837
838 if (file->details->extension_attributes) {
839 g_hash_table_destroy (file->details->extension_attributes);
840 }
841
842 if (file->details->metadata) {
843 metadata_hash_free (file->details->metadata);
844 }
845
846 G_OBJECT_CLASS (caja_file_parent_class)((((GObjectClass*) (void *) ((caja_file_parent_class)))))->finalize (object);
847}
848
849CajaFile *
850caja_file_ref (CajaFile *file)
851{
852 if (file == NULL((void*)0)) {
853 return NULL((void*)0);
854 }
855 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_156
= 1; else _g_boolean_var_156 = 0; _g_boolean_var_156; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
856
857#ifdef CAJA_FILE_DEBUG_REF
858 DEBUG_REF_PRINTFprintf("%10p ref'd", file);
859#endif
860
861 return g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
862}
863
864void
865caja_file_unref (CajaFile *file)
866{
867 if (file == NULL((void*)0)) {
868 return;
869 }
870
871 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_157
= 1; else _g_boolean_var_157 = 0; _g_boolean_var_157; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
872
873#ifdef CAJA_FILE_DEBUG_REF
874 DEBUG_REF_PRINTFprintf("%10p unref'd", file);
875#endif
876
877 g_object_unref (file);
878}
879
880/**
881 * caja_file_get_parent_uri_for_display:
882 *
883 * Get the uri for the parent directory.
884 *
885 * @file: The file in question.
886 *
887 * Return value: A string representing the parent's location,
888 * formatted for user display (including stripping "file://").
889 * If the parent is NULL, returns the empty string.
890 */
891char *
892caja_file_get_parent_uri_for_display (CajaFile *file)
893{
894 GFile *parent;
895 char *result;
896
897 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_158
= 1; else _g_boolean_var_158 = 0; _g_boolean_var_158; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 897, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
898
899 parent = caja_file_get_parent_location (file);
900 if (parent) {
901 result = g_file_get_parse_name (parent);
902 g_object_unref (parent);
903 } else {
904 result = g_strdup ("")g_strdup_inline ("");
905 }
906
907 return result;
908}
909
910/**
911 * caja_file_get_parent_uri:
912 *
913 * Get the uri for the parent directory.
914 *
915 * @file: The file in question.
916 *
917 * Return value: A string for the parent's location, in "raw URI" form.
918 * Use caja_file_get_parent_uri_for_display instead if the
919 * result is to be displayed on-screen.
920 * If the parent is NULL, returns the empty string.
921 */
922char *
923caja_file_get_parent_uri (CajaFile *file)
924{
925 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_159
= 1; else _g_boolean_var_159 = 0; _g_boolean_var_159; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 925, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
926
927 if (caja_file_is_self_owned (file)) {
928 /* Callers expect an empty string, not a NULL. */
929 return g_strdup ("")g_strdup_inline ("");
930 }
931
932 return caja_directory_get_uri (file->details->directory);
933}
934
935GFile *
936caja_file_get_parent_location (CajaFile *file)
937{
938 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_160
= 1; else _g_boolean_var_160 = 0; _g_boolean_var_160; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 938, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
939
940 if (caja_file_is_self_owned (file)) {
941 /* Callers expect an empty string, not a NULL. */
942 return NULL((void*)0);
943 }
944
945 return caja_directory_get_location (file->details->directory);
946}
947
948CajaFile *
949caja_file_get_parent (CajaFile *file)
950{
951 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_161
= 1; else _g_boolean_var_161 = 0; _g_boolean_var_161; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 951, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); } while
(0)
;
952
953 if (caja_file_is_self_owned (file)) {
954 return NULL((void*)0);
955 }
956
957 return caja_directory_get_corresponding_file (file->details->directory);
958}
959
960/**
961 * caja_file_can_read:
962 *
963 * Check whether the user is allowed to read the contents of this file.
964 *
965 * @file: The file to check.
966 *
967 * Return value: FALSE if the user is definitely not allowed to read
968 * the contents of the file. If the user has read permission, or
969 * the code can't tell whether the user has read permission,
970 * returns TRUE (so failures must always be handled).
971 */
972gboolean
973caja_file_can_read (CajaFile *file)
974{
975 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_162
= 1; else _g_boolean_var_162 = 0; _g_boolean_var_162; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
976
977 return file->details->can_read;
978}
979
980/**
981 * caja_file_can_write:
982 *
983 * Check whether the user is allowed to write to this file.
984 *
985 * @file: The file to check.
986 *
987 * Return value: FALSE if the user is definitely not allowed to write
988 * to the file. If the user has write permission, or
989 * the code can't tell whether the user has write permission,
990 * returns TRUE (so failures must always be handled).
991 */
992gboolean
993caja_file_can_write (CajaFile *file)
994{
995 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_163
= 1; else _g_boolean_var_163 = 0; _g_boolean_var_163; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
996
997 return file->details->can_write;
998}
999
1000/**
1001 * caja_file_can_execute:
1002 *
1003 * Check whether the user is allowed to execute this file.
1004 *
1005 * @file: The file to check.
1006 *
1007 * Return value: FALSE if the user is definitely not allowed to execute
1008 * the file. If the user has execute permission, or
1009 * the code can't tell whether the user has execute permission,
1010 * returns TRUE (so failures must always be handled).
1011 */
1012gboolean
1013caja_file_can_execute (CajaFile *file)
1014{
1015 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_164
= 1; else _g_boolean_var_164 = 0; _g_boolean_var_164; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1016
1017 return file->details->can_execute;
1018}
1019
1020gboolean
1021caja_file_can_mount (CajaFile *file)
1022{
1023 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_165
= 1; else _g_boolean_var_165 = 0; _g_boolean_var_165; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1024
1025 return file->details->can_mount;
1026}
1027
1028gboolean
1029caja_file_can_unmount (CajaFile *file)
1030{
1031 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_166
= 1; else _g_boolean_var_166 = 0; _g_boolean_var_166; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1032
1033 return file->details->can_unmount ||
1034 (file->details->mount != NULL((void*)0) &&
1035 g_mount_can_unmount (file->details->mount));
1036}
1037
1038gboolean
1039caja_file_can_eject (CajaFile *file)
1040{
1041 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_167
= 1; else _g_boolean_var_167 = 0; _g_boolean_var_167; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1042
1043 return file->details->can_eject ||
1044 (file->details->mount != NULL((void*)0) &&
1045 g_mount_can_eject (file->details->mount));
1046}
1047
1048gboolean
1049caja_file_can_start (CajaFile *file)
1050{
1051 gboolean ret;
1052 GDrive *drive;
1053
1054 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_168
= 1; else _g_boolean_var_168 = 0; _g_boolean_var_168; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1055
1056 ret = FALSE(0);
1057
1058 if (file->details->can_start) {
1059 ret = TRUE(!(0));
1060 goto out;
1061 }
1062
1063 if (file->details->mount != NULL((void*)0)) {
1064 drive = g_mount_get_drive (file->details->mount);
1065 if (drive != NULL((void*)0)) {
1066 ret = g_drive_can_start (drive);
1067 g_object_unref (drive);
1068 }
1069 }
1070
1071 out:
1072 return ret;
1073}
1074
1075gboolean
1076caja_file_can_start_degraded (CajaFile *file)
1077{
1078 gboolean ret;
1079 GDrive *drive;
1080
1081 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_169
= 1; else _g_boolean_var_169 = 0; _g_boolean_var_169; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1082
1083 ret = FALSE(0);
1084
1085 if (file->details->can_start_degraded) {
1086 ret = TRUE(!(0));
1087 goto out;
1088 }
1089
1090 if (file->details->mount != NULL((void*)0)) {
1091 drive = g_mount_get_drive (file->details->mount);
1092 if (drive != NULL((void*)0)) {
1093 ret = g_drive_can_start_degraded (drive);
1094 g_object_unref (drive);
1095 }
1096 }
1097
1098 out:
1099 return ret;
1100}
1101
1102gboolean
1103caja_file_can_poll_for_media (CajaFile *file)
1104{
1105 gboolean ret;
1106 GDrive *drive;
1107
1108 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_170
= 1; else _g_boolean_var_170 = 0; _g_boolean_var_170; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1109
1110 ret = FALSE(0);
1111
1112 if (file->details->can_poll_for_media) {
1113 ret = TRUE(!(0));
1114 goto out;
1115 }
1116
1117 if (file->details->mount != NULL((void*)0)) {
1118 drive = g_mount_get_drive (file->details->mount);
1119 if (drive != NULL((void*)0)) {
1120 ret = g_drive_can_poll_for_media (drive);
1121 g_object_unref (drive);
1122 }
1123 }
1124
1125 out:
1126 return ret;
1127}
1128
1129gboolean
1130caja_file_is_media_check_automatic (CajaFile *file)
1131{
1132 gboolean ret;
1133 GDrive *drive;
1134
1135 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_171
= 1; else _g_boolean_var_171 = 0; _g_boolean_var_171; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1136
1137 ret = FALSE(0);
1138
1139 if (file->details->is_media_check_automatic) {
1140 ret = TRUE(!(0));
1141 goto out;
1142 }
1143
1144 if (file->details->mount != NULL((void*)0)) {
1145 drive = g_mount_get_drive (file->details->mount);
1146 if (drive != NULL((void*)0)) {
1147 ret = g_drive_is_media_check_automatic (drive);
1148 g_object_unref (drive);
1149 }
1150 }
1151
1152 out:
1153 return ret;
1154}
1155
1156
1157gboolean
1158caja_file_can_stop (CajaFile *file)
1159{
1160 gboolean ret;
1161 GDrive *drive;
1162
1163 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_172
= 1; else _g_boolean_var_172 = 0; _g_boolean_var_172; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1164
1165 ret = FALSE(0);
1166
1167 if (file->details->can_stop) {
1168 ret = TRUE(!(0));
1169 goto out;
1170 }
1171
1172 if (file->details->mount != NULL((void*)0)) {
1173 drive = g_mount_get_drive (file->details->mount);
1174 if (drive != NULL((void*)0)) {
1175 ret = g_drive_can_stop (drive);
1176 g_object_unref (drive);
1177 }
1178 }
1179
1180 out:
1181 return ret;
1182}
1183
1184GDriveStartStopType
1185caja_file_get_start_stop_type (CajaFile *file)
1186{
1187 GDriveStartStopType ret;
1188 GDrive *drive;
1189
1190 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_173
= 1; else _g_boolean_var_173 = 0; _g_boolean_var_173; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1191
1192 ret = G_DRIVE_START_STOP_TYPE_UNKNOWN;
Value stored to 'ret' is never read
1193
1194 ret = file->details->start_stop_type;
1195 if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN)
1196 goto out;
1197
1198 if (file->details->mount != NULL((void*)0)) {
1199 drive = g_mount_get_drive (file->details->mount);
1200 if (drive != NULL((void*)0)) {
1201 ret = g_drive_get_start_stop_type (drive);
1202 g_object_unref (drive);
1203 }
1204 }
1205
1206 out:
1207 return ret;
1208}
1209
1210void
1211caja_file_mount (CajaFile *file,
1212 GMountOperation *mount_op,
1213 GCancellable *cancellable,
1214 CajaFileOperationCallback callback,
1215 gpointer callback_data)
1216{
1217 GError *error;
1218
1219 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount == NULL((void*)0)) {
1220 if (callback) {
1221 error = NULL((void*)0);
1222 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1223 _("This file cannot be mounted")dcgettext (((void*)0), "This file cannot be mounted", 5));
1224 callback (file, NULL((void*)0), error, callback_data);
1225 g_error_free (error);
1226 }
1227 } else {
1228 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->mount (file, mount_op, cancellable, callback, callback_data);
1229 }
1230}
1231
1232typedef struct {
1233 CajaFile *file;
1234 CajaFileOperationCallback callback;
1235 gpointer callback_data;
1236} UnmountData;
1237
1238static void
1239unmount_done (void *callback_data)
1240{
1241 UnmountData *data;
1242
1243 data = (UnmountData *)callback_data;
1244 if (data->callback) {
1245 data->callback (data->file, NULL((void*)0), NULL((void*)0), data->callback_data);
1246 }
1247 caja_file_unref (data->file);
1248 g_free (data);
1249}
1250
1251void
1252caja_file_unmount (CajaFile *file,
1253 GMountOperation *mount_op,
1254 GCancellable *cancellable,
1255 CajaFileOperationCallback callback,
1256 gpointer callback_data)
1257{
1258 GError *error;
1259 UnmountData *data;
1260
1261 if (file->details->can_unmount) {
1262 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount != NULL((void*)0)) {
1263 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->unmount (file, mount_op, cancellable, callback, callback_data);
1264 } else {
1265 if (callback) {
1266 error = NULL((void*)0);
1267 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1268 _("This file cannot be unmounted")dcgettext (((void*)0), "This file cannot be unmounted", 5));
1269 callback (file, NULL((void*)0), error, callback_data);
1270 g_error_free (error);
1271 }
1272 }
1273 } else if (file->details->mount != NULL((void*)0) &&
1274 g_mount_can_unmount (file->details->mount)) {
1275 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1276 data->file = caja_file_ref (file);
1277 data->callback = callback;
1278 data->callback_data = callback_data;
1279 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, FALSE(0), TRUE(!(0)), unmount_done, data);
1280 } else if (callback) {
1281 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1282 }
1283}
1284
1285void
1286caja_file_eject (CajaFile *file,
1287 GMountOperation *mount_op,
1288 GCancellable *cancellable,
1289 CajaFileOperationCallback callback,
1290 gpointer callback_data)
1291{
1292 GError *error;
1293 UnmountData *data;
1294
1295 if (file->details->can_eject) {
1296 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject != NULL((void*)0)) {
1297 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->eject (file, mount_op, cancellable, callback, callback_data);
1298 } else {
1299 if (callback) {
1300 error = NULL((void*)0);
1301 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1302 _("This file cannot be ejected")dcgettext (((void*)0), "This file cannot be ejected", 5));
1303 callback (file, NULL((void*)0), error, callback_data);
1304 g_error_free (error);
1305 }
1306 }
1307 } else if (file->details->mount != NULL((void*)0) &&
1308 g_mount_can_eject (file->details->mount)) {
1309 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
1310 data->file = caja_file_ref (file);
1311 data->callback = callback;
1312 data->callback_data = callback_data;
1313 caja_file_operations_unmount_mount_full (NULL((void*)0), file->details->mount, TRUE(!(0)), TRUE(!(0)), unmount_done, data);
1314 } else if (callback) {
1315 callback (file, NULL((void*)0), NULL((void*)0), callback_data);
1316 }
1317}
1318
1319void
1320caja_file_start (CajaFile *file,
1321 GMountOperation *start_op,
1322 GCancellable *cancellable,
1323 CajaFileOperationCallback callback,
1324 gpointer callback_data)
1325{
1326 GError *error;
1327
1328 if ((file->details->can_start || file->details->can_start_degraded) &&
1329 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start != NULL((void*)0)) {
1330 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->start (file, start_op, cancellable, callback, callback_data);
1331 } else {
1332 if (callback) {
1333 error = NULL((void*)0);
1334 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1335 _("This file cannot be started")dcgettext (((void*)0), "This file cannot be started", 5));
1336 callback (file, NULL((void*)0), error, callback_data);
1337 g_error_free (error);
1338 }
1339 }
1340}
1341
1342static void
1343file_stop_callback (GObject *source_object,
1344 GAsyncResult *res,
1345 gpointer callback_data)
1346{
1347 CajaFileOperation *op;
1348 gboolean stopped;
1349 GError *error;
1350
1351 op = callback_data;
1352
1353 error = NULL((void*)0);
1354 stopped = g_drive_stop_finish (G_DRIVE (source_object)((((GDrive*) (void *) ((source_object))))),
1355 res, &error);
1356
1357 if (!stopped &&
1358 error->domain == G_IO_ERRORg_io_error_quark() &&
1359 (error->code == G_IO_ERROR_FAILED_HANDLED ||
1360 error->code == G_IO_ERROR_CANCELLED)) {
1361 g_error_free (error);
1362 error = NULL((void*)0);
1363 }
1364
1365 caja_file_operation_complete (op, NULL((void*)0), error);
1366 if (error) {
1367 g_error_free (error);
1368 }
1369}
1370
1371void
1372caja_file_stop (CajaFile *file,
1373 GMountOperation *mount_op,
1374 GCancellable *cancellable,
1375 CajaFileOperationCallback callback,
1376 gpointer callback_data)
1377{
1378 GError *error;
1379
1380 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1381 if (file->details->can_stop) {
1382 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop (file, mount_op, cancellable, callback, callback_data);
1383 } else {
1384 if (callback) {
1385 error = NULL((void*)0);
1386 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1387 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1388 callback (file, NULL((void*)0), error, callback_data);
1389 g_error_free (error);
1390 }
1391 }
1392 } else {
1393 GDrive *drive;
1394
1395 drive = NULL((void*)0);
1396 if (file->details->mount != NULL((void*)0))
1397 drive = g_mount_get_drive (file->details->mount);
1398
1399 if (drive != NULL((void*)0) && g_drive_can_stop (drive)) {
1400 CajaFileOperation *op;
1401
1402 op = caja_file_operation_new (file, callback, callback_data);
1403 if (cancellable) {
1404 g_object_unref (op->cancellable);
1405 op->cancellable = g_object_ref (cancellable)((__typeof__ (cancellable)) (g_object_ref) (cancellable));
1406 }
1407
1408 g_drive_stop (drive,
1409 G_MOUNT_UNMOUNT_NONE,
1410 mount_op,
1411 op->cancellable,
1412 file_stop_callback,
1413 op);
1414 } else {
1415 if (callback) {
1416 error = NULL((void*)0);
1417 g_set_error_literal (&error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1418 _("This file cannot be stopped")dcgettext (((void*)0), "This file cannot be stopped", 5));
1419 callback (file, NULL((void*)0), error, callback_data);
1420 g_error_free (error);
1421 }
1422 }
1423
1424 if (drive != NULL((void*)0)) {
1425 g_object_unref (drive);
1426 }
1427 }
1428}
1429
1430void
1431caja_file_poll_for_media (CajaFile *file)
1432{
1433 if (file->details->can_poll_for_media) {
1434 if (CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->stop != NULL((void*)0)) {
1435 CAJA_FILE_GET_CLASS (file)((((CajaFileClass*) (((GTypeInstance*) ((file)))->g_class)
)))
->poll_for_media (file);
1436 }
1437 } else if (file->details->mount != NULL((void*)0)) {
1438 GDrive *drive;
1439 drive = g_mount_get_drive (file->details->mount);
1440 if (drive != NULL((void*)0)) {
1441 g_drive_poll_for_media (drive,
1442 NULL((void*)0), /* cancellable */
1443 NULL((void*)0), /* GAsyncReadyCallback */
1444 NULL((void*)0)); /* user_data */
1445 g_object_unref (drive);
1446 }
1447 }
1448}
1449
1450/**
1451 * caja_file_is_desktop_directory:
1452 *
1453 * Check whether this file is the desktop directory.
1454 *
1455 * @file: The file to check.
1456 *
1457 * Return value: TRUE if this is the physical desktop directory.
1458 */
1459gboolean
1460caja_file_is_desktop_directory (CajaFile *file)
1461{
1462 GFile *dir;
1463
1464 dir = file->details->directory->details->location;
1465
1466 if (dir == NULL((void*)0)) {
1467 return FALSE(0);
1468 }
1469
1470 return caja_is_desktop_directory_file (dir, file->details->name);
1471}
1472
1473static gboolean
1474is_desktop_file (CajaFile *file)
1475{
1476 return caja_file_is_mime_type (file, "application/x-desktop");
1477}
1478
1479static gboolean
1480can_rename_desktop_file (CajaFile *file)
1481{
1482 GFile *location;
1483 gboolean res;
1484
1485 location = caja_file_get_location (file);
1486 res = g_file_is_native (location);
1487 g_object_unref (location);
1488 return res;
1489}
1490
1491/**
1492 * caja_file_can_rename:
1493 *
1494 * Check whether the user is allowed to change the name of the file.
1495 *
1496 * @file: The file to check.
1497 *
1498 * Return value: FALSE if the user is definitely not allowed to change
1499 * the name of the file. If the user is allowed to change the name, or
1500 * the code can't tell whether the user is allowed to change the name,
1501 * returns TRUE (so rename failures must always be handled).
1502 */
1503gboolean
1504caja_file_can_rename (CajaFile *file)
1505{
1506 gboolean can_rename;
1507
1508 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_174
= 1; else _g_boolean_var_174 = 0; _g_boolean_var_174; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1509
1510 /* Nonexistent files can't be renamed. */
1511 if (caja_file_is_gone (file)) {
1512 return FALSE(0);
1513 }
1514
1515 /* Self-owned files can't be renamed */
1516 if (caja_file_is_self_owned (file)) {
1517 return FALSE(0);
1518 }
1519
1520 if ((is_desktop_file (file) && !can_rename_desktop_file (file)) ||
1521 caja_file_is_home (file)) {
1522 return FALSE(0);
1523 }
1524
1525 can_rename = TRUE(!(0));
1526
1527 /* Certain types of links can't be renamed */
1528 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1529 CajaDesktopLink *link;
1530
1531 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1532
1533 if (link != NULL((void*)0)) {
1534 can_rename = caja_desktop_link_can_rename (link);
1535 g_object_unref (link);
1536 }
1537 }
1538
1539 if (!can_rename) {
1540 return FALSE(0);
1541 }
1542
1543 return file->details->can_rename;
1544}
1545
1546gboolean
1547caja_file_can_delete (CajaFile *file)
1548{
1549 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_175
= 1; else _g_boolean_var_175 = 0; _g_boolean_var_175; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1550
1551 /* Nonexistent files can't be deleted. */
1552 if (caja_file_is_gone (file)) {
1553 return FALSE(0);
1554 }
1555
1556 /* Self-owned files can't be deleted */
1557 if (caja_file_is_self_owned (file)) {
1558 return FALSE(0);
1559 }
1560
1561 return file->details->can_delete;
1562}
1563
1564gboolean
1565caja_file_can_trash (CajaFile *file)
1566{
1567 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_176
= 1; else _g_boolean_var_176 = 0; _g_boolean_var_176; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
1568
1569 /* Nonexistent files can't be deleted. */
1570 if (caja_file_is_gone (file)) {
1571 return FALSE(0);
1572 }
1573
1574 /* Self-owned files can't be deleted */
1575 if (caja_file_is_self_owned (file)) {
1576 return FALSE(0);
1577 }
1578
1579 return file->details->can_trash;
1580}
1581
1582GFile *
1583caja_file_get_location (CajaFile *file)
1584{
1585 GFile *dir;
1586
1587 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_177
= 1; else _g_boolean_var_177 = 0; _g_boolean_var_177; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1588
1589 dir = file->details->directory->details->location;
1590
1591 if (caja_file_is_self_owned (file)) {
1592 return g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir));
1593 }
1594
1595 return g_file_get_child (dir, file->details->name);
1596}
1597
1598/* Return the actual uri associated with the passed-in file. */
1599char *
1600caja_file_get_uri (CajaFile *file)
1601{
1602 char *uri;
1603 GFile *loc;
1604
1605 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_178
= 1; else _g_boolean_var_178 = 0; _g_boolean_var_178; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1606
1607 loc = caja_file_get_location (file);
1608 uri = g_file_get_uri (loc);
1609 g_object_unref (loc);
1610
1611 return uri;
1612}
1613
1614char *
1615caja_file_get_uri_scheme (CajaFile *file)
1616{
1617 GFile *loc;
1618 char *scheme;
1619
1620 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_179
= 1; else _g_boolean_var_179 = 0; _g_boolean_var_179; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
1621
1622 if (file->details->directory == NULL((void*)0) ||
1623 file->details->directory->details->location == NULL((void*)0)) {
1624 return NULL((void*)0);
1625 }
1626
1627 loc = caja_directory_get_location (file->details->directory);
1628 scheme = g_file_get_uri_scheme (loc);
1629 g_object_unref (loc);
1630
1631 return scheme;
1632}
1633
1634CajaFileOperation *
1635caja_file_operation_new (CajaFile *file,
1636 CajaFileOperationCallback callback,
1637 gpointer callback_data)
1638{
1639 CajaFileOperation *op;
1640
1641 op = g_new0 (CajaFileOperation, 1)(CajaFileOperation *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (CajaFileOperation); 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; }))
;
1642 op->file = caja_file_ref (file);
1643 op->callback = callback;
1644 op->callback_data = callback_data;
1645 op->cancellable = g_cancellable_new ();
1646
1647 op->file->details->operations_in_progress = g_list_prepend
1648 (op->file->details->operations_in_progress, op);
1649
1650 return op;
1651}
1652
1653static void
1654caja_file_operation_remove (CajaFileOperation *op)
1655{
1656 op->file->details->operations_in_progress = g_list_remove
1657 (op->file->details->operations_in_progress, op);
1658}
1659
1660void
1661caja_file_operation_free (CajaFileOperation *op)
1662{
1663 caja_file_operation_remove (op);
1664 caja_file_unref (op->file);
1665 g_object_unref (op->cancellable);
1666 if (op->free_data) {
1667 op->free_data (op->data);
1668 }
1669 // Start UNDO-REDO
1670 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1671 op->undo_redo_data);
1672 // End UNDO-REDO
1673 g_free (op);
1674}
1675
1676void
1677caja_file_operation_complete (CajaFileOperation *op, GFile *result_file, GError *error)
1678{
1679 /* Claim that something changed even if the operation failed.
1680 * This makes it easier for some clients who see the "reverting"
1681 * as "changing back".
1682 */
1683 caja_file_operation_remove (op);
1684 caja_file_changed (op->file);
1685 if (op->callback) {
1686 (* op->callback) (op->file, result_file, error, op->callback_data);
1687 }
1688 caja_file_operation_free (op);
1689}
1690
1691void
1692caja_file_operation_cancel (CajaFileOperation *op)
1693{
1694 /* Cancel the operation if it's still in progress. */
1695 g_cancellable_cancel (op->cancellable);
1696}
1697
1698static void
1699rename_get_info_callback (GObject *source_object,
1700 GAsyncResult *res,
1701 gpointer callback_data)
1702{
1703 CajaFileOperation *op;
1704 GFileInfo *new_info;
1705 GError *error;
1706
1707 op = callback_data;
1708
1709 error = NULL((void*)0);
1710 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
1711 if (new_info != NULL((void*)0)) {
1712 CajaDirectory *directory;
1713 CajaFile *existing_file;
1714 char *old_name;
1715 char *old_uri;
1716 char *new_uri;
1717 const char *new_name;
1718
1719 directory = op->file->details->directory;
1720
1721 new_name = g_file_info_get_name (new_info);
1722
1723 /* If there was another file by the same name in this
1724 * directory, mark it gone.
1725 */
1726 existing_file = caja_directory_find_file_by_name (directory, new_name);
1727 if (existing_file != NULL((void*)0)) {
1728 caja_file_mark_gone (existing_file);
1729 caja_file_changed (existing_file);
1730 }
1731
1732 old_uri = caja_file_get_uri (op->file);
1733 old_name = g_strdup (op->file->details->name)g_strdup_inline (op->file->details->name);
1734
1735 update_info_and_name (op->file, new_info);
1736
1737 g_free (old_name);
1738
1739 new_uri = caja_file_get_uri (op->file);
1740 caja_directory_moved (old_uri, new_uri);
1741 g_free (new_uri);
1742 g_free (old_uri);
1743
1744 /* the rename could have affected the display name if e.g.
1745 * we're in a vfolder where the name comes from a desktop file
1746 * and a rename affects the contents of the desktop file.
1747 */
1748 if (op->file->details->got_custom_display_name) {
1749 caja_file_invalidate_attributes (op->file,
1750 CAJA_FILE_ATTRIBUTE_INFO |
1751 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1752 }
1753
1754 g_object_unref (new_info);
1755 }
1756 caja_file_operation_complete (op, NULL((void*)0), error);
1757 if (error) {
1758 g_error_free (error);
1759 }
1760}
1761
1762static void
1763rename_callback (GObject *source_object,
1764 GAsyncResult *res,
1765 gpointer callback_data)
1766{
1767 CajaFileOperation *op;
1768 GFile *new_file;
1769 GError *error;
1770
1771 op = callback_data;
1772
1773 error = NULL((void*)0);
1774 new_file = g_file_set_display_name_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
1775 res, &error);
1776
1777 if (new_file != NULL((void*)0)) {
1778 // Start UNDO-REDO
1779 caja_undostack_manager_data_set_rename_information(op->undo_redo_data, G_FILE (source_object)((((GFile*) (void *) ((source_object))))), new_file);
1780 // End UNDO-REDO
1781 g_file_query_info_async (new_file,
1782 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
1783 0,
1784 G_PRIORITY_DEFAULT0,
1785 op->cancellable,
1786 rename_get_info_callback, op);
1787 } else {
1788 caja_file_operation_complete (op, NULL((void*)0), error);
1789 g_error_free (error);
1790 }
1791}
1792
1793static gboolean
1794name_is (CajaFile *file, const char *new_name)
1795{
1796 const char *old_name;
1797 old_name = file->details->name;
1798 return strcmp (new_name, old_name) == 0;
1799}
1800
1801void
1802caja_file_rename (CajaFile *file,
1803 const char *new_name,
1804 CajaFileOperationCallback callback,
1805 gpointer callback_data)
1806{
1807 CajaFileOperation *op;
1808 char *old_name;
1809 char *new_file_name;
1810 gboolean success, name_changed;
1811 gboolean is_renameable_desktop_file;
1812 GFile *location;
1813 GError *error;
1814
1815 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_180
= 1; else _g_boolean_var_180 = 0; _g_boolean_var_180; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
1816 g_return_if_fail (new_name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if (new_name != ((void*)0)) _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__)), "new_name != NULL"
); return; } } while (0)
;
1817 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if (callback != ((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__)), "callback != NULL"
); return; } } while (0)
;
1818
1819 is_renameable_desktop_file =
1820 is_desktop_file (file) && can_rename_desktop_file (file);
1821
1822 /* Return an error for incoming names containing path separators.
1823 * But not for .desktop files as '/' are allowed for them */
1824 if (strstr (new_name, "/") != NULL((void*)0) && !is_renameable_desktop_file) {
1825 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
1826 _("Slashes are not allowed in filenames")dcgettext (((void*)0), "Slashes are not allowed in filenames"
, 5)
);
1827 (* callback) (file, NULL((void*)0), error, callback_data);
1828 g_error_free (error);
1829 return;
1830 }
1831
1832 /* Can't rename a file that's already gone.
1833 * We need to check this here because there may be a new
1834 * file with the same name.
1835 */
1836 if (caja_file_is_gone (file)) {
1837 /* Claim that something changed even if the rename
1838 * failed. This makes it easier for some clients who
1839 * see the "reverting" to the old name as "changing
1840 * back".
1841 */
1842 caja_file_changed (file);
1843 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_FOUND,
1844 _("File not found")dcgettext (((void*)0), "File not found", 5));
1845 (* callback) (file, NULL((void*)0), error, callback_data);
1846 g_error_free (error);
1847 return;
1848 }
1849
1850 /* Test the name-hasn't-changed case explicitly, for two reasons.
1851 * (1) rename returns an error if new & old are same.
1852 * (2) We don't want to send file-changed signal if nothing changed.
1853 */
1854 if (!CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
&&
1855 !is_renameable_desktop_file &&
1856 name_is (file, new_name)) {
1857 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1858 return;
1859 }
1860
1861 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1862 * case before this case.
1863 */
1864 if (caja_file_is_self_owned (file)) {
1865 /* Claim that something changed even if the rename
1866 * failed. This makes it easier for some clients who
1867 * see the "reverting" to the old name as "changing
1868 * back".
1869 */
1870 caja_file_changed (file);
1871 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_NOT_SUPPORTED,
1872 _("Toplevel files cannot be renamed")dcgettext (((void*)0), "Toplevel files cannot be renamed", 5));
1873
1874 (* callback) (file, NULL((void*)0), error, callback_data);
1875 g_error_free (error);
1876 return;
1877 }
1878
1879 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
1880 CajaDesktopLink *link;
1881
1882 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
1883 old_name = caja_file_get_display_name (file);
1884
1885 if ((old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0)) {
1886 success = TRUE(!(0));
1887 } else {
1888 success = (link != NULL((void*)0) && caja_desktop_link_rename (link, new_name));
1889 }
1890
1891 if (success) {
1892 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1893 } else {
1894 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1895 _("Unable to rename desktop icon")dcgettext (((void*)0), "Unable to rename desktop icon", 5));
1896 (* callback) (file, NULL((void*)0), error, callback_data);
1897 g_error_free (error);
1898 }
1899
1900 g_free (old_name);
1901 g_object_unref (link);
1902 return;
1903 }
1904
1905 if (is_renameable_desktop_file) {
1906 char *uri;
1907
1908 /* Don't actually change the name if the new name is the same.
1909 * This helps for the vfolder method where this can happen and
1910 * we want to minimize actual changes
1911 */
1912 uri = caja_file_get_uri (file);
1913 old_name = caja_link_local_get_text (uri);
1914 if (old_name != NULL((void*)0) && strcmp (new_name, old_name) == 0) {
1915 success = TRUE(!(0));
1916 name_changed = FALSE(0);
1917 } else {
1918 success = caja_link_local_set_text (uri, new_name);
1919 name_changed = TRUE(!(0));
1920 }
1921 g_free (old_name);
1922 g_free (uri);
1923
1924 if (!success) {
1925 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_FAILED,
1926 _("Unable to rename desktop file")dcgettext (((void*)0), "Unable to rename desktop file", 5));
1927 (* callback) (file, NULL((void*)0), error, callback_data);
1928 g_error_free (error);
1929 return;
1930 }
1931 if (!g_str_has_suffix(new_name, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (new_name); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_183; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_183 = 1; else _g_boolean_var_183
= 0; _g_boolean_var_183; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (new_name, ".desktop") )
)
1932 new_file_name = g_strdup_printf ("%s.desktop", new_name);
1933 else
1934 new_file_name = g_strdup_printf("%s", new_name);
1935 new_file_name = g_strdelimit (new_file_name, "/", '-');
1936
1937 if (name_is (file, new_file_name)) {
1938 if (name_changed) {
1939 caja_file_invalidate_attributes (file,
1940 CAJA_FILE_ATTRIBUTE_INFO |
1941 CAJA_FILE_ATTRIBUTE_LINK_INFO);
1942 }
1943
1944 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
1945 g_free (new_file_name);
1946 return;
1947 }
1948 } else {
1949 new_file_name = g_strdup (new_name)g_strdup_inline (new_name);
1950 }
1951
1952 /* Set up a renaming operation. */
1953 op = caja_file_operation_new (file, callback, callback_data);
1954 op->is_rename = TRUE(!(0));
1955
1956 /* Do the renaming. */
1957
1958 location = caja_file_get_location (file);
1959
1960 // Start UNDO-REDO
1961 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
1962 op->undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RENAME, 1);
1963 }
1964 // End UNDO-REDO
1965
1966 g_file_set_display_name_async (location,
1967 new_file_name,
1968 G_PRIORITY_DEFAULT0,
1969 op->cancellable,
1970 rename_callback,
1971 op);
1972 g_free (new_file_name);
1973 g_object_unref (location);
1974}
1975
1976gboolean
1977caja_file_rename_in_progress (CajaFile *file)
1978{
1979 GList *node;
1980 CajaFileOperation *op = NULL((void*)0);
1981
1982 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = node->next) {
1983 op = node->data;
1984 if (op->is_rename) {
1985 return TRUE(!(0));
1986 }
1987 }
1988 return FALSE(0);
1989}
1990
1991void
1992caja_file_cancel (CajaFile *file,
1993 CajaFileOperationCallback callback,
1994 gpointer callback_data)
1995{
1996 GList *node, *next;
1997 CajaFileOperation *op = NULL((void*)0);
1998
1999 for (node = file->details->operations_in_progress; node != NULL((void*)0); node = next) {
2000 next = node->next;
2001 op = node->data;
2002
2003 g_assert (op->file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (op->file == file) _g_boolean_var_184 = 1; else _g_boolean_var_184
= 0; _g_boolean_var_184; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2003, ((const char*) (__func__
)), "op->file == file"); } while (0)
;
2004 if (op->callback == callback && op->callback_data == callback_data) {
2005 caja_file_operation_cancel (op);
2006 }
2007 }
2008}
2009
2010gboolean
2011caja_file_matches_uri (CajaFile *file, const char *match_uri)
2012{
2013 GFile *match_file, *location;
2014 gboolean result;
2015
2016 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_185
= 1; else _g_boolean_var_185 = 0; _g_boolean_var_185; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2017 g_return_val_if_fail (match_uri != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if (match_uri != ((void*)0)) _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__)), "match_uri != NULL"
); return ((0)); } } while (0)
;
2018
2019 location = caja_file_get_location (file);
2020 match_file = g_file_new_for_uri (match_uri);
2021 result = g_file_equal (location, match_file);
2022 g_object_unref (location);
2023 g_object_unref (match_file);
2024
2025 return result;
2026}
2027
2028int
2029caja_file_compare_location (CajaFile *file_1,
2030 CajaFile *file_2)
2031{
2032 GFile *loc_a, *loc_b;
2033 gboolean res;
2034
2035 loc_a = caja_file_get_location (file_1);
2036 loc_b = caja_file_get_location (file_2);
2037
2038 res = !g_file_equal (loc_a, loc_b);
2039
2040 g_object_unref (loc_a);
2041 g_object_unref (loc_b);
2042
2043 return (gint) res;
2044}
2045
2046gboolean
2047caja_file_is_local (CajaFile *file)
2048{
2049 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_187
= 1; else _g_boolean_var_187 = 0; _g_boolean_var_187; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2050
2051 return caja_directory_is_local (file->details->directory);
2052}
2053
2054static void
2055update_link (CajaFile *link_file, CajaFile *target_file)
2056{
2057 g_assert (CAJA_IS_FILE (link_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((link_file)); GType __t = (caja_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_188
= 1; else _g_boolean_var_188 = 0; _g_boolean_var_188; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2057, ((const char*) (__func__)), "CAJA_IS_FILE (link_file)"
); } while (0)
;
2058 g_assert (CAJA_IS_FILE (target_file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_file)); GType __t = (caja_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_189
= 1; else _g_boolean_var_189 = 0; _g_boolean_var_189; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 2058, ((const char*) (__func__)), "CAJA_IS_FILE (target_file)"
); } while (0)
;
2059
2060 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
2061 * here then the hash table is a waste of time.
2062 */
2063}
2064
2065static GList *
2066get_link_files (CajaFile *target_file)
2067{
2068 GList **link_files;
2069
2070 if (symbolic_links == NULL((void*)0)) {
2071 link_files = NULL((void*)0);
2072 } else {
2073 char *uri;
2074
2075 uri = caja_file_get_uri (target_file);
2076 link_files = g_hash_table_lookup (symbolic_links, uri);
2077 g_free (uri);
2078 }
2079 if (link_files) {
2080 return caja_file_list_copy (*link_files);
2081 }
2082 return NULL((void*)0);
2083}
2084
2085static void
2086update_links_if_target (CajaFile *target_file)
2087{
2088 GList *link_files, *p;
2089
2090 link_files = get_link_files (target_file);
2091 for (p = link_files; p != NULL((void*)0); p = p->next) {
2092 update_link (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))), target_file);
2093 }
2094 caja_file_list_free (link_files);
2095}
2096
2097static gboolean
2098update_info_internal (CajaFile *file,
2099 GFileInfo *info,
2100 gboolean update_name)
2101{
2102 gboolean changed;
2103 gboolean is_symlink, is_hidden, is_backup, is_mountpoint;
2104 gboolean has_permissions;
2105 guint32 permissions;
2106 gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
2107 gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
2108 GDriveStartStopType start_stop_type;
2109 gboolean thumbnailing_failed;
2110 int uid, gid;
2111 goffset size;
2112 goffset size_on_disk;
2113 int sort_order;
2114 time_t atime, mtime, ctime, btime;
2115 time_t trash_time;
2116 const char * time_string;
2117 const char *symlink_name, *mime_type, *selinux_context, *thumbnail_path;
2118 GFileType file_type;
2119 GIcon *icon;
2120 const char *description;
2121 const char *filesystem_id;
2122 const char *trash_orig_path;
2123 const char *group, *owner, *owner_real;
2124 gboolean free_owner, free_group;
2125
2126 if (file->details->is_gone) {
2127 return FALSE(0);
2128 }
2129
2130 if (info == NULL((void*)0)) {
2131 caja_file_mark_gone (file);
2132 return TRUE(!(0));
2133 }
2134
2135 file->details->file_info_is_up_to_date = TRUE(!(0));
2136
2137 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2138 * point to the old name know that the file has been renamed.
2139 */
2140
2141 remove_from_link_hash_table (file);
2142
2143 changed = FALSE(0);
2144
2145 if (!file->details->got_file_info) {
2146 changed = TRUE(!(0));
2147 }
2148 file->details->got_file_info = TRUE(!(0));
2149
2150 changed |= caja_file_set_display_name (file,
2151 g_file_info_get_display_name (info),
2152 g_file_info_get_edit_name (info),
2153 FALSE(0));
2154
2155 file_type = g_file_info_get_file_type (info);
2156 if (file->details->type != file_type) {
2157 changed = TRUE(!(0));
2158 }
2159 file->details->type = file_type;
2160
2161 if (!file->details->got_custom_activation_uri) {
2162 const char *activation_uri;
2163
2164 activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri");
2165 if (activation_uri == NULL((void*)0)) {
2166 if (file->details->activation_uri) {
2167 g_free (file->details->activation_uri);
2168 file->details->activation_uri = NULL((void*)0);
2169 changed = TRUE(!(0));
2170 }
2171 } else {
2172 char *old_activation_uri;
2173
2174 old_activation_uri = file->details->activation_uri;
2175 file->details->activation_uri = g_strdup (activation_uri)g_strdup_inline (activation_uri);
2176
2177 if (old_activation_uri) {
2178 if (strcmp (old_activation_uri,
2179 file->details->activation_uri) != 0) {
2180 changed = TRUE(!(0));
2181 }
2182 g_free (old_activation_uri);
2183 } else {
2184 changed = TRUE(!(0));
2185 }
2186 }
2187 }
2188
2189 is_symlink = g_file_info_get_is_symlink (info);
2190 if (file->details->is_symlink != is_symlink) {
2191 changed = TRUE(!(0));
2192 }
2193 file->details->is_symlink = is_symlink;
2194
2195 is_hidden = g_file_info_get_is_hidden (info);
2196 is_backup = g_file_info_get_is_backup (info);
2197 if (file->details->is_hidden != is_hidden ||
2198 file->details->is_backup != is_backup) {
2199 changed = TRUE(!(0));
2200 }
2201 file->details->is_hidden = is_hidden;
2202 file->details->is_backup = is_backup;
2203
2204 is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT"unix::is-mountpoint");
2205 if (file->details->is_mountpoint != is_mountpoint) {
2206 changed = TRUE(!(0));
2207 }
2208 file->details->is_mountpoint = is_mountpoint;
2209
2210 has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
2211 permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");;
2212 if (file->details->has_permissions != has_permissions ||
2213 file->details->permissions != permissions) {
2214 changed = TRUE(!(0));
2215 }
2216 file->details->has_permissions = has_permissions;
2217 file->details->permissions = permissions;
2218
2219 /* We default to TRUE for this if we can't know */
2220 can_read = TRUE(!(0));
2221 can_write = TRUE(!(0));
2222 can_execute = TRUE(!(0));
2223 can_delete = TRUE(!(0));
2224 can_trash = TRUE(!(0));
2225 can_rename = TRUE(!(0));
2226 can_mount = FALSE(0);
2227 can_unmount = FALSE(0);
2228 can_eject = FALSE(0);
2229 can_start = FALSE(0);
2230 can_start_degraded = FALSE(0);
2231 can_stop = FALSE(0);
2232 can_poll_for_media = FALSE(0);
2233 is_media_check_automatic = FALSE(0);
2234 start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
2235 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read")) {
2236 can_read = g_file_info_get_attribute_boolean (info,
2237 G_FILE_ATTRIBUTE_ACCESS_CAN_READ"access::can-read");
2238 }
2239 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write")) {
2240 can_write = g_file_info_get_attribute_boolean (info,
2241 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write");
2242 }
2243 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute")) {
2244 can_execute = g_file_info_get_attribute_boolean (info,
2245 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute");
2246 }
2247 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete")) {
2248 can_delete = g_file_info_get_attribute_boolean (info,
2249 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE"access::can-delete");
2250 }
2251 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash")) {
2252 can_trash = g_file_info_get_attribute_boolean (info,
2253 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH"access::can-trash");
2254 }
2255 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename")) {
2256 can_rename = g_file_info_get_attribute_boolean (info,
2257 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME"access::can-rename");
2258 }
2259 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount")) {
2260 can_mount = g_file_info_get_attribute_boolean (info,
2261 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT"mountable::can-mount");
2262 }
2263 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount")) {
2264 can_unmount = g_file_info_get_attribute_boolean (info,
2265 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT"mountable::can-unmount");
2266 }
2267 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject")) {
2268 can_eject = g_file_info_get_attribute_boolean (info,
2269 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT"mountable::can-eject");
2270 }
2271 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start")) {
2272 can_start = g_file_info_get_attribute_boolean (info,
2273 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START"mountable::can-start");
2274 }
2275 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded")) {
2276 can_start_degraded = g_file_info_get_attribute_boolean (info,
2277 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED"mountable::can-start-degraded");
2278 }
2279 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop")) {
2280 can_stop = g_file_info_get_attribute_boolean (info,
2281 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP"mountable::can-stop");
2282 }
2283 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type")) {
2284 start_stop_type = g_file_info_get_attribute_uint32 (info,
2285 G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE"mountable::start-stop-type");
2286 }
2287 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll")) {
2288 can_poll_for_media = g_file_info_get_attribute_boolean (info,
2289 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL"mountable::can-poll");
2290 }
2291 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic")) {
2292 is_media_check_automatic = g_file_info_get_attribute_boolean (info,
2293 G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC"mountable::is-media-check-automatic");
2294 }
2295 if (file->details->can_read != can_read ||
2296 file->details->can_write != can_write ||
2297 file->details->can_execute != can_execute ||
2298 file->details->can_delete != can_delete ||
2299 file->details->can_trash != can_trash ||
2300 file->details->can_rename != can_rename ||
2301 file->details->can_mount != can_mount ||
2302 file->details->can_unmount != can_unmount ||
2303 file->details->can_eject != can_eject ||
2304 file->details->can_start != can_start ||
2305 file->details->can_start_degraded != can_start_degraded ||
2306 file->details->can_stop != can_stop ||
2307 file->details->start_stop_type != start_stop_type ||
2308 file->details->can_poll_for_media != can_poll_for_media ||
2309 file->details->is_media_check_automatic != is_media_check_automatic) {
2310 changed = TRUE(!(0));
2311 }
2312
2313 file->details->can_read = can_read;
2314 file->details->can_write = can_write;
2315 file->details->can_execute = can_execute;
2316 file->details->can_delete = can_delete;
2317 file->details->can_trash = can_trash;
2318 file->details->can_rename = can_rename;
2319 file->details->can_mount = can_mount;
2320 file->details->can_unmount = can_unmount;
2321 file->details->can_eject = can_eject;
2322 file->details->can_start = can_start;
2323 file->details->can_start_degraded = can_start_degraded;
2324 file->details->can_stop = can_stop;
2325 file->details->start_stop_type = start_stop_type;
2326 file->details->can_poll_for_media = can_poll_for_media;
2327 file->details->is_media_check_automatic = is_media_check_automatic;
2328
2329 free_owner = FALSE(0);
2330 owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER"owner::user");
2331 owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL"owner::user-real");
2332 free_group = FALSE(0);
2333 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
2334
2335 uid = -1;
2336 gid = -1;
2337 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid")) {
2338 uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid");
2339 if (owner == NULL((void*)0)) {
2340 free_owner = TRUE(!(0));
2341 owner = g_strdup_printf ("%d", uid);
2342 }
2343 }
2344 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid")) {
2345 gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid");
2346 if (group == NULL((void*)0)) {
2347 free_group = TRUE(!(0));
2348 group = g_strdup_printf ("%d", gid);
2349 }
2350 }
2351 if (file->details->uid != uid ||
2352 file->details->gid != gid) {
2353 changed = TRUE(!(0));
2354 }
2355 file->details->uid = uid;
2356 file->details->gid = gid;
2357
2358 if (eel_strcmp (file->details->owner, owner) != 0) {
2359 changed = TRUE(!(0));
2360 g_clear_pointer (&file->details->owner, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner)) _pp = (&file->details
->owner); __typeof__ (*(&file->details->owner)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2361 file->details->owner = g_ref_string_new_intern (owner);
2362 }
2363
2364 if (eel_strcmp (file->details->owner_real, owner_real) != 0) {
2365 changed = TRUE(!(0));
2366 g_clear_pointer (&file->details->owner_real, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->owner_real
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->owner_real)) _pp = (&file->
details->owner_real); __typeof__ (*(&file->details->
owner_real)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2367 file->details->owner_real = g_ref_string_new_intern (owner_real);
2368 }
2369
2370 if (eel_strcmp (file->details->group, group) != 0) {
2371 changed = TRUE(!(0));
2372 g_clear_pointer (&file->details->group, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->group
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->group)) _pp = (&file->details
->group); __typeof__ (*(&file->details->group)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2373 file->details->group = g_ref_string_new_intern (group);
2374 }
2375
2376 if (free_owner) {
2377 g_free ((char *)owner);
2378 }
2379 if (free_group) {
2380 g_free ((char *)group);
2381 }
2382
2383 size = -1;
2384 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size")) {
2385 size = g_file_info_get_size (info);
2386 }
2387 if (file->details->size != size) {
2388 changed = TRUE(!(0));
2389 }
2390 file->details->size = size;
2391
2392 size_on_disk = -1;
2393 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size")) {
2394 size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size");
2395 }
2396 if (file->details->size_on_disk != size_on_disk) {
2397 changed = TRUE(!(0));
2398 }
2399 file->details->size_on_disk = size_on_disk;
2400
2401 sort_order = g_file_info_get_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER"standard::sort-order");
2402 if (file->details->sort_order != sort_order) {
2403 changed = TRUE(!(0));
2404 }
2405 file->details->sort_order = sort_order;
2406
2407 atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS"time::access");
2408 ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED"time::changed");
2409 mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED"time::modified");
2410 btime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED"time::created");
2411 if (file->details->atime != atime ||
2412 file->details->mtime != mtime ||
2413 file->details->ctime != ctime ||
2414 file->details->btime != btime) {
2415 if (file->details->thumbnail == NULL((void*)0)) {
2416 file->details->thumbnail_is_up_to_date = FALSE(0);
2417 }
2418
2419 changed = TRUE(!(0));
2420 }
2421 file->details->atime = atime;
2422 file->details->ctime = ctime;
2423 file->details->mtime = mtime;
2424 file->details->btime = btime;
2425
2426 if (file->details->thumbnail != NULL((void*)0) &&
2427 file->details->thumbnail_mtime != 0 &&
2428 file->details->thumbnail_mtime != mtime) {
2429 file->details->thumbnail_is_up_to_date = FALSE(0);
2430 changed = TRUE(!(0));
2431 }
2432
2433 icon = g_file_info_get_icon (info);
2434 if (!g_icon_equal (icon, file->details->icon)) {
2435 changed = TRUE(!(0));
2436
2437 if (file->details->icon) {
2438 g_object_unref (file->details->icon);
2439 }
2440 file->details->icon = g_object_ref (icon)((__typeof__ (icon)) (g_object_ref) (icon));
2441 }
2442
2443 thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH"thumbnail::path");
2444 if (eel_strcmp (file->details->thumbnail_path, thumbnail_path) != 0) {
2445 changed = TRUE(!(0));
2446 g_free (file->details->thumbnail_path);
2447 file->details->thumbnail_path = g_strdup (thumbnail_path)g_strdup_inline (thumbnail_path);
2448 }
2449
2450 thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED"thumbnail::failed");
2451 if (file->details->thumbnailing_failed != thumbnailing_failed) {
2452 changed = TRUE(!(0));
2453 file->details->thumbnailing_failed = thumbnailing_failed;
2454 }
2455
2456 symlink_name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET"standard::symlink-target");
2457
2458 if (eel_strcmp (file->details->symlink_name, symlink_name) != 0) {
2459 changed = TRUE(!(0));
2460 g_free (file->details->symlink_name);
2461 file->details->symlink_name = g_strdup (symlink_name)g_strdup_inline (symlink_name);
2462 }
2463
2464 mime_type = g_file_info_get_content_type (info);
2465 if (eel_strcmp (file->details->mime_type, mime_type) != 0) {
2466 changed = TRUE(!(0));
2467 g_clear_pointer (&file->details->mime_type, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->mime_type
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->mime_type)) _pp = (&file->
details->mime_type); __typeof__ (*(&file->details->
mime_type)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release
) (_ptr); } while (0)
;
2468 file->details->mime_type = g_ref_string_new_intern (mime_type);
2469 }
2470
2471 selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT"selinux::context");
2472 if (eel_strcmp (file->details->selinux_context, selinux_context) != 0) {
2473 changed = TRUE(!(0));
2474 g_free (file->details->selinux_context);
2475 file->details->selinux_context = g_strdup (selinux_context)g_strdup_inline (selinux_context);
2476 }
2477
2478 description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION"standard::description");
2479 if (eel_strcmp (file->details->description, description) != 0) {
2480 changed = TRUE(!(0));
2481 g_free (file->details->description);
2482 file->details->description = g_strdup (description)g_strdup_inline (description);
2483 }
2484
2485 filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
2486 if (eel_strcmp (file->details->filesystem_id, filesystem_id) != 0) {
2487 changed = TRUE(!(0));
2488 g_clear_pointer (&file->details->filesystem_id, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->filesystem_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->filesystem_id)) _pp = (&file
->details->filesystem_id); __typeof__ (*(&file->
details->filesystem_id)) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_ref_string_release) (_ptr); } while (0)
;
2489 file->details->filesystem_id = g_ref_string_new_intern (filesystem_id);
2490 }
2491
2492 trash_time = 0;
2493 time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"trash::deletion-date");
2494 if (time_string != NULL((void*)0)) {
2495#if GLIB_CHECK_VERSION(2,61,2)(2 > (2) || (2 == (2) && 80 > (61)) || (2 == (2
) && 80 == (61) && 3 >= (2)))
2496 GDateTime *dt;
2497 GTimeZone *tz;
2498 tz = g_time_zone_new_local ();
2499 dt = g_date_time_new_from_iso8601 (time_string, tz);
2500 if (dt) {
2501 trash_time = (time_t) g_date_time_to_unix (dt);
2502 g_date_time_unref (dt);
2503 }
2504 g_time_zone_unref (tz);
2505#else
2506 GTimeVal g_trash_time;
2507 g_time_val_from_iso8601 (time_string, &g_trash_time);
2508 trash_time = g_trash_time.tv_sec;
2509#endif
2510 }
2511 if (file->details->trash_time != trash_time) {
2512 changed = TRUE(!(0));
2513 file->details->trash_time = trash_time;
2514 }
2515
2516 trash_orig_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH"trash::orig-path");
2517 if (eel_strcmp (file->details->trash_orig_path, trash_orig_path) != 0) {
2518 changed = TRUE(!(0));
2519 g_free (file->details->trash_orig_path);
2520 file->details->trash_orig_path = g_strdup (trash_orig_path)g_strdup_inline (trash_orig_path);
2521 }
2522
2523 changed |=
2524 caja_file_update_metadata_from_info (file, info);
2525
2526 if (update_name) {
2527 const char *name;
2528
2529 name = g_file_info_get_name (info);
2530 if (file->details->name == NULL((void*)0) ||
2531 strcmp (file->details->name, name) != 0) {
2532 GList *node;
2533
2534 changed = TRUE(!(0));
2535
2536 node = caja_directory_begin_file_name_change
2537 (file->details->directory, file);
2538
2539 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2540 if (eel_strcmp (file->details->display_name, name) == 0) {
2541 file->details->name = g_ref_string_acquire (file->details->display_name);
2542 } else {
2543 file->details->name = g_ref_string_new (name);
2544 }
2545
2546 if (!file->details->got_custom_display_name &&
2547 g_file_info_get_display_name (info) == NULL((void*)0)) {
2548 /* If the file info's display name is NULL,
2549 * caja_file_set_display_name() did
2550 * not unset the display name.
2551 */
2552 caja_file_clear_display_name (file);
2553 }
2554
2555 caja_directory_end_file_name_change
2556 (file->details->directory, file, node);
2557 }
2558 }
2559
2560 if (changed) {
2561 add_to_link_hash_table (file);
2562
2563 update_links_if_target (file);
2564 }
2565
2566 return changed;
2567}
2568
2569static gboolean
2570update_info_and_name (CajaFile *file,
2571 GFileInfo *info)
2572{
2573 return update_info_internal (file, info, TRUE(!(0)));
2574}
2575
2576gboolean
2577caja_file_update_info (CajaFile *file,
2578 GFileInfo *info)
2579{
2580 return update_info_internal (file, info, FALSE(0));
2581}
2582
2583void
2584caja_file_refresh_info (CajaFile *file)
2585{
2586 GFile *gfile;
2587 GFileInfo *new_info;
2588
2589 gfile = caja_file_get_location (file);
2590 new_info = g_file_query_info (gfile, CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
2591 G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0));
2592 if (new_info != NULL((void*)0)) {
2593 if (caja_file_update_info (file, new_info)) {
2594 caja_file_changed (file);
2595 }
2596 g_object_unref (new_info);
2597 }
2598 g_object_unref (gfile);
2599}
2600
2601static gboolean
2602update_name_internal (CajaFile *file,
2603 const char *name,
2604 gboolean in_directory)
2605{
2606 GList *node;
2607
2608 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if (name != ((void*)0)) _g_boolean_var_190 = 1; else _g_boolean_var_190
= 0; _g_boolean_var_190; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 2608, ((const char*) (__func__
)), "name != NULL"); } while (0)
;
2609
2610 if (file->details->is_gone) {
2611 return FALSE(0);
2612 }
2613
2614 if (name_is (file, name)) {
2615 return FALSE(0);
2616 }
2617
2618 node = NULL((void*)0);
2619 if (in_directory) {
2620 node = caja_directory_begin_file_name_change
2621 (file->details->directory, file);
2622 }
2623
2624 g_clear_pointer (&file->details->name, g_ref_string_release)do { _Static_assert (sizeof *(&file->details->name)
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
((&file->details->name)) _pp = (&file->details
->name); __typeof__ (*(&file->details->name)) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_ref_string_release) (
_ptr); } while (0)
;
2625 file->details->name = g_ref_string_new (name);
2626
2627 if (!file->details->got_custom_display_name) {
2628 caja_file_clear_display_name (file);
2629 }
2630
2631 if (in_directory) {
2632 caja_directory_end_file_name_change
2633 (file->details->directory, file, node);
2634 }
2635
2636 return TRUE(!(0));
2637}
2638
2639gboolean
2640caja_file_update_name (CajaFile *file, const char *name)
2641{
2642 gboolean ret;
2643
2644 ret = update_name_internal (file, name, TRUE(!(0)));
2645
2646 if (ret) {
2647 update_links_if_target (file);
2648 }
2649
2650 return ret;
2651}
2652
2653gboolean
2654caja_file_update_name_and_directory (CajaFile *file,
2655 const char *name,
2656 CajaDirectory *new_directory)
2657{
2658 CajaDirectory *old_directory;
2659 FileMonitors *monitors;
2660
2661 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_191
= 1; else _g_boolean_var_191 = 0; _g_boolean_var_191; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
2662 g_return_val_if_fail (CAJA_IS_DIRECTORY (file->details->directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file->details->directory)); GType __t = (caja_directory_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__)), "CAJA_IS_DIRECTORY (file->details->directory)"
); return ((0)); } } while (0)
;
2663 g_return_val_if_fail (!file->details->is_gone, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if (!file->details->is_gone) _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__
)), "!file->details->is_gone"); return ((0)); } } while
(0)
;
2664 g_return_val_if_fail (!caja_file_is_self_owned (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (!caja_file_is_self_owned (file)) _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__)), "!caja_file_is_self_owned (file)"); return ((
0)); } } while (0)
;
2665 g_return_val_if_fail (CAJA_IS_DIRECTORY (new_directory), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((new_directory)); GType __t = (caja_directory_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__)), "CAJA_IS_DIRECTORY (new_directory)"
); return ((0)); } } while (0)
;
2666
2667 old_directory = file->details->directory;
2668 if (old_directory == new_directory) {
2669 if (name) {
2670 return update_name_internal (file, name, TRUE(!(0)));
2671 } else {
2672 return FALSE(0);
2673 }
2674 }
2675
2676 caja_file_ref (file);
2677
2678 /* FIXME bugzilla.gnome.org 42044: Need to let links that
2679 * point to the old name know that the file has been moved.
2680 */
2681
2682 remove_from_link_hash_table (file);
2683
2684 monitors = caja_directory_remove_file_monitors (old_directory, file);
2685 caja_directory_remove_file (old_directory, file);
2686
2687 file->details->directory = caja_directory_ref (new_directory);
2688 caja_directory_unref (old_directory);
2689
2690 if (name) {
2691 update_name_internal (file, name, FALSE(0));
2692 }
2693
2694 caja_directory_add_file (new_directory, file);
2695 caja_directory_add_file_monitors (new_directory, file, monitors);
2696
2697 add_to_link_hash_table (file);
2698
2699 update_links_if_target (file);
2700
2701 caja_file_unref (file);
2702
2703 return TRUE(!(0));
2704}
2705
2706void
2707caja_file_set_directory (CajaFile *file,
2708 CajaDirectory *new_directory)
2709{
2710 caja_file_update_name_and_directory (file, NULL((void*)0), new_directory);
2711}
2712
2713static Knowledge
2714get_item_count (CajaFile *file,
2715 guint *count)
2716{
2717 gboolean known, unreadable;
2718
2719 known = caja_file_get_directory_item_count
2720 (file, count, &unreadable);
2721 if (!known) {
2722 return UNKNOWN;
2723 }
2724 if (unreadable) {
2725 return UNKNOWABLE;
2726 }
2727 return KNOWN;
2728}
2729
2730static Knowledge
2731get_size (CajaFile *file,
2732 goffset *size,
2733 gboolean size_on_disk)
2734{
2735 /* If we tried and failed, then treat it like there is no size
2736 * to know.
2737 */
2738 if (file->details->get_info_failed) {
2739 return UNKNOWABLE;
2740 }
2741
2742 /* If the info is NULL that means we haven't even tried yet,
2743 * so it's just unknown, not unknowable.
2744 */
2745 if (!file->details->got_file_info) {
2746 return UNKNOWN;
2747 }
2748
2749 /* If we got info with no size in it, it means there is no
2750 * such thing as a size as far as mate-vfs is concerned,
2751 * so "unknowable".
2752 */
2753 if (size_on_disk && file->details->size_on_disk == -1) {
2754 return UNKNOWABLE;
2755 }
2756
2757 if (!size_on_disk && file->details->size == -1) {
2758 return UNKNOWABLE;
2759 }
2760
2761 /* We have a size! */
2762 if (size_on_disk) {
2763 *size = file->details->size_on_disk;
2764 } else {
2765 *size = file->details->size;
2766 }
2767
2768 return KNOWN;
2769}
2770
2771static Knowledge
2772get_time (CajaFile *file,
2773 time_t *time_out,
2774 CajaDateType type)
2775{
2776 time_t time;
2777
2778 /* If we tried and failed, then treat it like there is no size
2779 * to know.
2780 */
2781 if (file->details->get_info_failed) {
2782 return UNKNOWABLE;
2783 }
2784
2785 /* If the info is NULL that means we haven't even tried yet,
2786 * so it's just unknown, not unknowable.
2787 */
2788 if (!file->details->got_file_info) {
2789 return UNKNOWN;
2790 }
2791
2792 time = 0;
2793 switch (type) {
2794 case CAJA_DATE_TYPE_MODIFIED:
2795 time = file->details->mtime;
2796 break;
2797 case CAJA_DATE_TYPE_ACCESSED:
2798 time = file->details->atime;
2799 break;
2800 case CAJA_DATE_TYPE_CREATED:
2801 time = file->details->btime;
2802 break;
2803 case CAJA_DATE_TYPE_TRASHED:
2804 time = file->details->trash_time;
2805 break;
2806 default:
2807 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file.c", 2807
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2808 break;
2809 }
2810
2811 *time_out = time;
2812
2813 /* If we got info with no modification time in it, it means
2814 * there is no such thing as a modification time as far as
2815 * mate-vfs is concerned, so "unknowable".
2816 */
2817 if (time == 0) {
2818 return UNKNOWABLE;
2819 }
2820 return KNOWN;
2821}
2822
2823static int
2824compare_directories_by_count (CajaFile *file_1, CajaFile *file_2)
2825{
2826 /* Sort order:
2827 * Directories with unknown # of items
2828 * Directories with "unknowable" # of items
2829 * Directories with 0 items
2830 * Directories with n items
2831 */
2832
2833 Knowledge count_known_1, count_known_2;
2834 guint count_1, count_2;
2835
2836 count_known_1 = get_item_count (file_1, &count_1);
2837 count_known_2 = get_item_count (file_2, &count_2);
2838
2839 if (count_known_1 > count_known_2) {
2840 return -1;
2841 }
2842 if (count_known_1 < count_known_2) {
2843 return +1;
2844 }
2845
2846 /* count_known_1 and count_known_2 are equal now. Check if count
2847 * details are UNKNOWABLE or UNKNOWN.
2848 */
2849 if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) {
2850 return 0;
2851 }
2852
2853 if (count_1 < count_2) {
2854 return -1;
2855 }
2856 if (count_1 > count_2) {
2857 return +1;
2858 }
2859
2860 return 0;
2861}
2862
2863static int
2864compare_files_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2865{
2866 /* Sort order:
2867 * Files with unknown size.
2868 * Files with "unknowable" size.
2869 * Files with smaller sizes.
2870 * Files with large sizes.
2871 */
2872
2873 Knowledge size_known_1, size_known_2;
2874 goffset size_1 = 0, size_2 = 0;
2875
2876 size_known_1 = get_size (file_1, &size_1, size_on_disk);
2877 size_known_2 = get_size (file_2, &size_2, size_on_disk);
2878
2879 if (size_known_1 > size_known_2) {
2880 return -1;
2881 }
2882 if (size_known_1 < size_known_2) {
2883 return +1;
2884 }
2885
2886 /* size_known_1 and size_known_2 are equal now. Check if size
2887 * details are UNKNOWABLE or UNKNOWN
2888 */
2889 if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) {
2890 return 0;
2891 }
2892
2893 if (size_1 < size_2) {
2894 return -1;
2895 }
2896 if (size_1 > size_2) {
2897 return +1;
2898 }
2899
2900 return 0;
2901}
2902
2903static int
2904compare_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
2905{
2906 /* Sort order:
2907 * Directories with n items
2908 * Directories with 0 items
2909 * Directories with "unknowable" # of items
2910 * Directories with unknown # of items
2911 * Files with large sizes.
2912 * Files with smaller sizes.
2913 * Files with "unknowable" size.
2914 * Files with unknown size.
2915 */
2916
2917 gboolean is_directory_1, is_directory_2;
2918
2919 is_directory_1 = caja_file_is_directory (file_1);
2920 is_directory_2 = caja_file_is_directory (file_2);
2921
2922 if (is_directory_1 && !is_directory_2) {
2923 return -1;
2924 }
2925 if (is_directory_2 && !is_directory_1) {
2926 return +1;
2927 }
2928
2929 if (is_directory_1) {
2930 return compare_directories_by_count (file_1, file_2);
2931 } else {
2932 return compare_files_by_size (file_1, file_2, size_on_disk);
2933 }
2934}
2935
2936static int
2937compare_by_display_name (CajaFile *file_1, CajaFile *file_2)
2938{
2939 const char *name_1, *name_2;
2940 const char *key_1, *key_2;
2941 gboolean sort_last_1, sort_last_2;
2942 int compare;
2943
2944 name_1 = caja_file_peek_display_name (file_1);
2945 name_2 = caja_file_peek_display_name (file_2);
2946
2947 sort_last_1 = name_1[0] == SORT_LAST_CHAR1'.' || name_1[0] == SORT_LAST_CHAR2'#';
2948 sort_last_2 = name_2[0] == SORT_LAST_CHAR1'.' || name_2[0] == SORT_LAST_CHAR2'#';
2949
2950 if (sort_last_1 && !sort_last_2) {
2951 compare = +1;
2952 } else if (!sort_last_1 && sort_last_2) {
2953 compare = -1;
2954 } else {
2955 key_1 = caja_file_peek_display_name_collation_key (file_1);
2956 key_2 = caja_file_peek_display_name_collation_key (file_2);
2957 compare = strcmp (key_1, key_2);
2958 }
2959
2960 return compare;
2961}
2962
2963static int
2964compare_by_directory_name (CajaFile *file_1, CajaFile *file_2)
2965{
2966 char *directory_1, *directory_2;
2967 int compare;
2968
2969 if (file_1->details->directory == file_2->details->directory) {
2970 return 0;
2971 }
2972
2973 directory_1 = caja_file_get_parent_uri_for_display (file_1);
2974 directory_2 = caja_file_get_parent_uri_for_display (file_2);
2975
2976 compare = g_utf8_collate (directory_1, directory_2);
2977
2978 g_free (directory_1);
2979 g_free (directory_2);
2980
2981 return compare;
2982}
2983
2984static gboolean
2985file_has_note (CajaFile *file)
2986{
2987 char *note;
2988 gboolean res;
2989
2990 note = caja_file_get_metadata (file, CAJA_METADATA_KEY_ANNOTATION"annotation", NULL((void*)0));
2991 res = note != NULL((void*)0) && note[0] != 0;
2992 g_free (note);
2993
2994 return res;
2995}
2996
2997static GList *
2998prepend_automatic_keywords (CajaFile *file,
2999 GList *names)
3000{
3001 /* Prepend in reverse order. */
3002 CajaFile *parent;
3003
3004 parent = caja_file_get_parent (file);
3005
3006#ifdef TRASH_IS_FAST_ENOUGH
3007 if (caja_file_is_in_trash (file)) {
3008 names = g_list_prepend
3009 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_TRASH)g_strdup_inline ("trash"));
3010 }
3011#endif
3012 if (file_has_note (file)) {
3013 names = g_list_prepend
3014 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_NOTE)g_strdup_inline ("note"));
3015 }
3016
3017 /* Trash files are assumed to be read-only,
3018 * so we want to ignore them here. */
3019 if (!caja_file_can_write (file) &&
3020 !caja_file_is_in_trash (file) &&
3021 (parent == NULL((void*)0) || caja_file_can_write (parent))) {
3022 names = g_list_prepend
3023 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_WRITE)g_strdup_inline ("nowrite"));
3024 }
3025 if (!caja_file_can_read (file)) {
3026 names = g_list_prepend
3027 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_CANT_READ)g_strdup_inline ("noread"));
3028 }
3029 if (caja_file_is_symbolic_link (file)) {
3030 names = g_list_prepend
3031 (names, g_strdup (CAJA_FILE_EMBLEM_NAME_SYMBOLIC_LINK)g_strdup_inline ("symbolic-link"));
3032 }
3033
3034 if (parent) {
3035 caja_file_unref (parent);
3036 }
3037
3038
3039 return names;
3040}
3041
3042static void
3043fill_emblem_cache_if_needed (CajaFile *file)
3044{
3045 GList *node, *keywords;
3046 char *scanner;
3047 size_t length;
3048
3049 if (file->details->compare_by_emblem_cache != NULL((void*)0)) {
3050 /* Got a cache already. */
3051 return;
3052 }
3053
3054 keywords = caja_file_get_keywords (file);
3055
3056 /* Add up the keyword string lengths */
3057 length = 1;
3058 for (node = keywords; node != NULL((void*)0); node = node->next) {
3059 length += strlen ((const char *) node->data) + 1;
3060 }
3061
3062 /* Now that we know how large the cache struct needs to be, allocate it. */
3063 file->details->compare_by_emblem_cache = g_malloc (sizeof(CajaFileSortByEmblemCache) + length);
3064
3065 /* Copy them into the cache. */
3066 scanner = file->details->compare_by_emblem_cache->emblem_keywords;
3067 for (node = keywords; node != NULL((void*)0); node = node->next) {
3068 length = strlen ((const char *) node->data) + 1;
3069 memcpy (scanner, (const char *) node->data, length);
3070 scanner += length;
3071 }
3072
3073 /* Zero-terminate so we can tell where the list ends. */
3074 *scanner = 0;
3075
3076 g_list_free_full (keywords, g_free);
3077}
3078
3079static int
3080compare_by_emblems (CajaFile *file_1, CajaFile *file_2)
3081{
3082 const char *keyword_cache_1, *keyword_cache_2;
3083 int compare_result;
3084
3085 fill_emblem_cache_if_needed (file_1);
3086 fill_emblem_cache_if_needed (file_2);
3087
3088 /* We ignore automatic emblems, and only sort by user-added keywords. */
3089 compare_result = 0;
3090 keyword_cache_1 = file_1->details->compare_by_emblem_cache->emblem_keywords;
3091 keyword_cache_2 = file_2->details->compare_by_emblem_cache->emblem_keywords;
3092 for (; *keyword_cache_1 != '\0' && *keyword_cache_2 != '\0';) {
3093 size_t length;
3094
3095 compare_result = g_utf8_collate (keyword_cache_1, keyword_cache_2);
3096 if (compare_result != 0) {
3097 return compare_result;
3098 }
3099
3100 /* Advance to the next keyword */
3101 length = strlen (keyword_cache_1);
3102 keyword_cache_1 += length + 1;
3103 keyword_cache_2 += length + 1;
3104 }
3105
3106
3107 /* One or both is now NULL. */
3108 if (*keyword_cache_1 != '\0') {
3109 g_assert (*keyword_cache_2 == '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if (*keyword_cache_2 == '\0') _g_boolean_var_196 = 1; else _g_boolean_var_196
= 0; _g_boolean_var_196; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3109, ((const char*) (__func__
)), "*keyword_cache_2 == '\\0'"); } while (0)
;
3110 return -1;
3111 } else if (*keyword_cache_2 != '\0') {
3112 return +1;
3113 }
3114
3115 return 0;
3116}
3117
3118static int
3119compare_by_type (CajaFile *file_1, CajaFile *file_2)
3120{
3121 gboolean is_directory_1;
3122 gboolean is_directory_2;
3123 char *type_string_1;
3124 char *type_string_2;
3125 int result;
3126
3127 /* Directories go first. Then, if mime types are identical,
3128 * don't bother getting strings (for speed). This assumes
3129 * that the string is dependent entirely on the mime type,
3130 * which is true now but might not be later.
3131 */
3132 is_directory_1 = caja_file_is_directory (file_1);
3133 is_directory_2 = caja_file_is_directory (file_2);
3134
3135 if (is_directory_1 && is_directory_2) {
3136 return 0;
3137 }
3138
3139 if (is_directory_1) {
3140 return -1;
3141 }
3142
3143 if (is_directory_2) {
3144 return +1;
3145 }
3146
3147 if (file_1->details->mime_type != NULL((void*)0) &&
3148 file_2->details->mime_type != NULL((void*)0) &&
3149 strcmp (file_1->details->mime_type,
3150 file_2->details->mime_type) == 0) {
3151 return 0;
3152 }
3153
3154 type_string_1 = caja_file_get_type_as_string (file_1);
3155 type_string_2 = caja_file_get_type_as_string (file_2);
3156
3157 result = g_utf8_collate (type_string_1, type_string_2);
3158
3159 g_free (type_string_1);
3160 g_free (type_string_2);
3161
3162 return result;
3163}
3164
3165static int
3166compare_by_time (CajaFile *file_1, CajaFile *file_2, CajaDateType type)
3167{
3168 /* Sort order:
3169 * Files with unknown times.
3170 * Files with "unknowable" times.
3171 * Files with older times.
3172 * Files with newer times.
3173 */
3174
3175 Knowledge time_known_1, time_known_2;
3176 time_t time_1, time_2;
3177
3178 time_1 = 0;
3179 time_2 = 0;
3180
3181 time_known_1 = get_time (file_1, &time_1, type);
3182 time_known_2 = get_time (file_2, &time_2, type);
3183
3184 if (time_known_1 > time_known_2) {
3185 return -1;
3186 }
3187 if (time_known_1 < time_known_2) {
3188 return +1;
3189 }
3190
3191 /* Now time_known_1 is equal to time_known_2. Check whether
3192 * we failed to get modification times for files
3193 */
3194 if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) {
3195 return 0;
3196 }
3197
3198 if (time_1 < time_2) {
3199 return -1;
3200 }
3201 if (time_1 > time_2) {
3202 return +1;
3203 }
3204
3205 return 0;
3206}
3207
3208static int
3209compare_by_full_path (CajaFile *file_1, CajaFile *file_2)
3210{
3211 int compare;
3212
3213 compare = compare_by_directory_name (file_1, file_2);
3214 if (compare != 0) {
3215 return compare;
3216 }
3217 return compare_by_display_name (file_1, file_2);
3218}
3219
3220/* prev_extension_segment:
3221 * @basename The basename of a file
3222 * @rem_chars A pointer to the amount of remaining characters
3223 *
3224 * Finds the next segment delimiter to the left. A starting character of '.' is
3225 * set to '\0'.
3226 *
3227 * Return value: The start of the previous segment (right of the dot) or
3228 * basename if there are none remaining.
3229 */
3230static char *
3231prev_extension_segment (char *basename, int *rem_chars)
3232{
3233 if (*basename == '.') {
3234 *basename = 0;
3235 basename--;
3236 (*rem_chars)--;
3237 }
3238
3239 while (*rem_chars > 0 && *basename != '.') {
3240 (*rem_chars)--;
3241 basename--;
3242 }
3243
3244 return basename + 1;
3245}
3246
3247/* is_valid_extension_segment:
3248 * @segment Part of a modifiable zero-terminated string
3249 * @segment_index The index of the current segment
3250 *
3251 * Uses a heuristic to identify valid file extensions.
3252 *
3253 * Return value: Whether the segment is part of the file extension.
3254 */
3255static gboolean
3256is_valid_extension_segment (const char *segment, int segment_index)
3257{
3258 gboolean result;
3259 gboolean has_letters;
3260 int char_offset;
3261 switch (segment_index) {
3262 case 0:
3263 /* extremely long segments are probably not part of the extension */
3264 result = strlen (segment) < 20;
3265 break;
3266 default:
3267 has_letters = FALSE(0);
3268 char_offset = 0;
3269 while (TRUE(!(0))) {
3270 char c;
3271
3272 c = *(segment + char_offset);
3273 if (c == '\0') {
3274 result = has_letters;
3275 break;
3276 }
3277 /* allow digits if there are also letters */
3278 else if (isalpha (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha
)
) {
3279 has_letters = TRUE(!(0));
3280 }
3281 /* fail if it is neither digit nor letter */
3282 else if (!isdigit (c)((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISdigit
)
) {
3283 result = FALSE(0);
3284 break;
3285 }
3286
3287 if (char_offset >= SORT_BY_EXTENSION_FOLLOWING_MAX_LENGTH3) {
3288 result = FALSE(0);
3289 break;
3290 }
3291 char_offset++;
3292 }
3293 }
3294 return result;
3295}
3296
3297static int
3298compare_by_extension_segments (CajaFile *file_1, CajaFile *file_2)
3299{
3300 char *name_1, *name_2;
3301 char *segment_1, *segment_2;
3302 int compare;
3303 int rem_chars_1, rem_chars_2;
3304 gboolean done_1, done_2;
3305 gboolean is_directory_1, is_directory_2;
3306 int segment_index;
3307
3308
3309 /* Directories do not have an extension */
3310 is_directory_1 = caja_file_is_directory (file_1);
3311 is_directory_2 = caja_file_is_directory (file_2);
3312
3313 if (is_directory_1 && is_directory_2) {
3314 return 0;
3315 } else if (is_directory_1) {
3316 return -1;
3317 } else if (is_directory_2) {
3318 return 1;
3319 }
3320
3321 name_1 = caja_file_get_display_name (file_1);
3322 name_2 = caja_file_get_display_name (file_2);
3323 rem_chars_1 = strlen (name_1);
3324 rem_chars_2 = strlen (name_2);
3325
3326 /* Point to one after the zero character */
3327 segment_1 = name_1 + rem_chars_1 + 1;
3328 segment_2 = name_2 + rem_chars_2 + 1;
3329
3330 segment_index = 0;
3331 do {
3332 segment_1 = prev_extension_segment (segment_1 - 1, &rem_chars_1);
3333 segment_2 = prev_extension_segment (segment_2 - 1, &rem_chars_2);
3334
3335 done_1 = rem_chars_1 <= 0 || !is_valid_extension_segment (segment_1, segment_index);
3336 done_2 = rem_chars_2 <= 0 || !is_valid_extension_segment (segment_2, segment_index);
3337 if (done_1 && !done_2) {
3338 compare = -1;
3339 break;
3340 }
3341 else if (!done_1 && done_2) {
3342 compare = 1;
3343 break;
3344 }
3345 else if (done_1 && done_2) {
3346 compare = 0;
3347 break;
3348 }
3349
3350 segment_index++;
3351 if (segment_index > SORT_BY_EXTENSION_MAX_SEGMENTS3 - 1) {
3352 break;
3353 }
3354 compare = strcmp (segment_1, segment_2);
3355 } while (compare == 0);
3356
3357 g_free (name_1);
3358 g_free (name_2);
3359
3360 return compare;
3361}
3362
3363static gchar *
3364caja_file_get_extension_as_string (CajaFile *file)
3365{
3366 int rem_chars;
3367 char *segment;
3368
3369 if (!caja_file_is_directory (file)) {
3370 char *name;
3371
3372 name = caja_file_get_display_name (file);
3373 rem_chars = strlen (name);
3374 segment = prev_extension_segment (name + rem_chars, &rem_chars);
3375
3376 if (rem_chars > 0 && is_valid_extension_segment (segment, 0)) {
3377 int segment_index;
3378 char *right_segment;
3379 char *result;
3380
3381 segment_index = 1;
3382 do {
3383 right_segment = segment;
3384 segment = prev_extension_segment (segment - 1, &rem_chars);
3385 if (rem_chars > 0 && is_valid_extension_segment (segment, segment_index)) {
3386 /* remove zero-termination of segment */
3387 *(right_segment - 1) = '.';
3388 }
3389 else {
3390 break;
3391 }
3392
3393 segment_index++;
3394 } while (segment_index < SORT_BY_EXTENSION_MAX_SEGMENTS3 + 1);
3395 result = g_strdup (right_segment)g_strdup_inline (right_segment);
3396 g_free (name);
3397 return result;
3398 }
3399 g_free (name);
3400 }
3401 return g_strdup ("")g_strdup_inline ("");
3402}
3403
3404static int
3405caja_file_compare_for_sort_internal (CajaFile *file_1,
3406 CajaFile *file_2,
3407 gboolean directories_first,
3408 gboolean reversed)
3409{
3410 gboolean is_directory_1, is_directory_2;
3411
3412 if (directories_first) {
3413 is_directory_1 = caja_file_is_directory (file_1);
3414 is_directory_2 = caja_file_is_directory (file_2);
3415
3416 if (is_directory_1 && !is_directory_2) {
3417 return -1;
3418 }
3419
3420 if (is_directory_2 && !is_directory_1) {
3421 return +1;
3422 }
3423 }
3424
3425 if (file_1->details->sort_order < file_2->details->sort_order) {
3426 return reversed ? 1 : -1;
3427 } else if (file_1->details->sort_order > file_2->details->sort_order) {
3428 return reversed ? -1 : 1;
3429 }
3430
3431 return 0;
3432}
3433
3434/**
3435 * caja_file_compare_for_sort:
3436 * @file_1: A file object
3437 * @file_2: Another file object
3438 * @sort_type: Sort criterion
3439 * @directories_first: Put all directories before any non-directories
3440 * @reversed: Reverse the order of the items, except that
3441 * the directories_first flag is still respected.
3442 *
3443 * Return value: int < 0 if @file_1 should come before file_2 in a
3444 * sorted list; int > 0 if @file_2 should come before file_1 in a
3445 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
3446 * that each named sort type may actually break ties several ways, with the name
3447 * of the sort criterion being the primary but not only differentiator.
3448 **/
3449int
3450caja_file_compare_for_sort (CajaFile *file_1,
3451 CajaFile *file_2,
3452 CajaFileSortType sort_type,
3453 gboolean directories_first,
3454 gboolean reversed)
3455{
3456 int result;
3457
3458 if (file_1 == file_2) {
3459 return 0;
3460 }
3461
3462 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3463
3464 if (result == 0) {
3465 switch (sort_type) {
3466 case CAJA_FILE_SORT_BY_DISPLAY_NAME:
3467 result = compare_by_display_name (file_1, file_2);
3468 if (result == 0) {
3469 result = compare_by_directory_name (file_1, file_2);
3470 }
3471 break;
3472 case CAJA_FILE_SORT_BY_DIRECTORY:
3473 result = compare_by_full_path (file_1, file_2);
3474 break;
3475 case CAJA_FILE_SORT_BY_SIZE:
3476 /* Compare directory sizes ourselves, then if necessary
3477 * use MateVFS to compare file sizes.
3478 */
3479 result = compare_by_size (file_1, file_2, FALSE(0));
3480 if (result == 0) {
3481 result = compare_by_full_path (file_1, file_2);
3482 }
3483 break;
3484 case CAJA_FILE_SORT_BY_SIZE_ON_DISK:
3485 /* Compare directory sizes ourselves, then if necessary
3486 * use MateVFS to compare file sizes.
3487 */
3488 result = compare_by_size (file_1, file_2, TRUE(!(0)));
3489 if (result == 0) {
3490 result = compare_by_full_path (file_1, file_2);
3491 }
3492 break;
3493 case CAJA_FILE_SORT_BY_TYPE:
3494 /* MateVFS doesn't know about our special text for certain
3495 * mime types, so we handle the mime-type sorting ourselves.
3496 */
3497 result = compare_by_type (file_1, file_2);
3498 if (result == 0) {
3499 result = compare_by_full_path (file_1, file_2);
3500 }
3501 break;
3502 case CAJA_FILE_SORT_BY_MTIME:
3503 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_MODIFIED);
3504 if (result == 0) {
3505 result = compare_by_full_path (file_1, file_2);
3506 }
3507 break;
3508 case CAJA_FILE_SORT_BY_BTIME:
3509 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_CREATED);
3510 if (result == 0) {
3511 result = compare_by_full_path (file_1, file_2);
3512 }
3513 break;
3514 case CAJA_FILE_SORT_BY_ATIME:
3515 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_ACCESSED);
3516 if (result == 0) {
3517 result = compare_by_full_path (file_1, file_2);
3518 }
3519 break;
3520 case CAJA_FILE_SORT_BY_TRASHED_TIME:
3521 result = compare_by_time (file_1, file_2, CAJA_DATE_TYPE_TRASHED);
3522 if (result == 0) {
3523 result = compare_by_full_path (file_1, file_2);
3524 }
3525 break;
3526 case CAJA_FILE_SORT_BY_EMBLEMS:
3527 /* MateVFS doesn't know squat about our emblems, so
3528 * we handle comparing them here, before falling back
3529 * to tie-breakers.
3530 */
3531 result = compare_by_emblems (file_1, file_2);
3532 if (result == 0) {
3533 result = compare_by_full_path (file_1, file_2);
3534 }
3535 break;
3536 case CAJA_FILE_SORT_BY_EXTENSION:
3537 result = compare_by_extension_segments (file_1, file_2);
3538 if (result == 0) {
3539 result = compare_by_full_path (file_1, file_2);
3540 }
3541 break;
3542 default:
3543 g_return_val_if_reached (0)do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "caja-file.c", 3543, ((const char*) (__func__))); return (0
); } while (0)
;
3544 }
3545
3546 if (reversed) {
3547 result = -result;
3548 }
3549 }
3550
3551 return result;
3552}
3553
3554int
3555caja_file_compare_for_sort_by_attribute_q (CajaFile *file_1,
3556 CajaFile *file_2,
3557 GQuark attribute,
3558 gboolean directories_first,
3559 gboolean reversed)
3560{
3561 int result;
3562
3563 if (file_1 == file_2) {
3564 return 0;
3565 }
3566
3567 /* Convert certain attributes into CajaFileSortTypes and use
3568 * caja_file_compare_for_sort()
3569 */
3570 if (attribute == 0 || attribute == attribute_name_q) {
3571 return caja_file_compare_for_sort (file_1, file_2,
3572 CAJA_FILE_SORT_BY_DISPLAY_NAME,
3573 directories_first,
3574 reversed);
3575 } else if (attribute == attribute_size_q) {
3576 return caja_file_compare_for_sort (file_1, file_2,
3577 CAJA_FILE_SORT_BY_SIZE,
3578 directories_first,
3579 reversed);
3580 } else if (attribute == attribute_size_on_disk_q) {
3581 return caja_file_compare_for_sort (file_1, file_2,
3582 CAJA_FILE_SORT_BY_SIZE_ON_DISK,
3583 directories_first,
3584 reversed);
3585 } else if (attribute == attribute_type_q) {
3586 return caja_file_compare_for_sort (file_1, file_2,
3587 CAJA_FILE_SORT_BY_TYPE,
3588 directories_first,
3589 reversed);
3590 } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q) {
3591 return caja_file_compare_for_sort (file_1, file_2,
3592 CAJA_FILE_SORT_BY_MTIME,
3593 directories_first,
3594 reversed);
3595 } else if (attribute == attribute_creation_date_q || attribute == attribute_date_created_q) {
3596 return caja_file_compare_for_sort (file_1, file_2,
3597 CAJA_FILE_SORT_BY_BTIME,
3598 directories_first,
3599 reversed);
3600 } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q) {
3601 return caja_file_compare_for_sort (file_1, file_2,
3602 CAJA_FILE_SORT_BY_ATIME,
3603 directories_first,
3604 reversed);
3605 } else if (attribute == attribute_trashed_on_q) {
3606 return caja_file_compare_for_sort (file_1, file_2,
3607 CAJA_FILE_SORT_BY_TRASHED_TIME,
3608 directories_first,
3609 reversed);
3610 } else if (attribute == attribute_emblems_q) {
3611 return caja_file_compare_for_sort (file_1, file_2,
3612 CAJA_FILE_SORT_BY_EMBLEMS,
3613 directories_first,
3614 reversed);
3615 } else if (attribute == attribute_extension_q) {
3616 return caja_file_compare_for_sort (file_1, file_2,
3617 CAJA_FILE_SORT_BY_EXTENSION,
3618 directories_first,
3619 reversed);
3620 }
3621
3622 /* it is a normal attribute, compare by strings */
3623
3624 result = caja_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed);
3625
3626 if (result == 0) {
3627 char *value_1;
3628 char *value_2;
3629
3630 value_1 = caja_file_get_string_attribute_q (file_1,
3631 attribute);
3632 value_2 = caja_file_get_string_attribute_q (file_2,
3633 attribute);
3634
3635 if (value_1 != NULL((void*)0) && value_2 != NULL((void*)0)) {
3636 result = strcmp (value_1, value_2);
3637 }
3638
3639 g_free (value_1);
3640 g_free (value_2);
3641
3642 if (reversed) {
3643 result = -result;
3644 }
3645 }
3646
3647 return result;
3648}
3649
3650int
3651caja_file_compare_for_sort_by_attribute (CajaFile *file_1,
3652 CajaFile *file_2,
3653 const char *attribute,
3654 gboolean directories_first,
3655 gboolean reversed)
3656{
3657 return caja_file_compare_for_sort_by_attribute_q (file_1, file_2,
3658 g_quark_from_string (attribute),
3659 directories_first,
3660 reversed);
3661}
3662
3663
3664/**
3665 * caja_file_compare_name:
3666 * @file: A file object
3667 * @pattern: A string we are comparing it with
3668 *
3669 * Return value: result of a comparison of the file name and the given pattern,
3670 * using the same sorting order as sort by name.
3671 **/
3672int
3673caja_file_compare_display_name (CajaFile *file,
3674 const char *pattern)
3675{
3676 const char *name;
3677 int result;
3678
3679 g_return_val_if_fail (pattern != NULL, -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if (pattern != ((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__)), "pattern != NULL"
); return (-1); } } while (0)
;
3680
3681 name = caja_file_peek_display_name (file);
3682 result = g_utf8_collate (name, pattern);
3683 return result;
3684}
3685
3686
3687gboolean
3688caja_file_is_hidden_file (CajaFile *file)
3689{
3690 return file->details->is_hidden;
3691}
3692
3693static gboolean
3694caja_file_is_backup_file (CajaFile *file)
3695{
3696 return file->details->is_backup;
3697}
3698
3699/**
3700 * caja_file_should_show:
3701 * @file: the file to check.
3702 * @show_hidden: whether we want to show hidden files or not.
3703 * @show_backup: whether we want to show backup files or not.
3704 *
3705 * Determines if a #CajaFile should be shown. Note that when browsing
3706 * a trash directory, this function will always return %TRUE.
3707 *
3708 * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't.
3709 */
3710gboolean
3711caja_file_should_show (CajaFile *file,
3712 gboolean show_hidden,
3713 gboolean show_foreign,
3714 gboolean show_backup)
3715{
3716 /* Never hide any files in trash. */
3717 if (caja_file_is_in_trash (file)) {
3718 return TRUE(!(0));
3719 } else {
3720 return (show_hidden || !caja_file_is_hidden_file (file)) &&
3721 (show_backup || !caja_file_is_backup_file (file)) &&
3722 (show_foreign || !(caja_file_is_in_desktop (file) && caja_file_is_foreign_link (file)));
3723 }
3724}
3725
3726gboolean
3727caja_file_is_home (CajaFile *file)
3728{
3729 GFile *dir;
3730
3731 dir = file->details->directory->details->location;
3732 if (dir == NULL((void*)0)) {
3733 return FALSE(0);
3734 }
3735
3736 return caja_is_home_directory_file (dir, file->details->name);
3737}
3738
3739gboolean
3740caja_file_is_in_desktop (CajaFile *file)
3741{
3742 if (file->details->directory->details->location) {
3743 return caja_is_desktop_directory (file->details->directory->details->location);
3744 }
3745 return FALSE(0);
3746
3747}
3748
3749static gboolean
3750filter_hidden_partition_callback (gpointer data,
3751 gpointer callback_data)
3752{
3753 CajaFile *file;
3754 FilterOptions options;
3755
3756 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
3757 options = GPOINTER_TO_INT (callback_data)((gint) (glong) (callback_data));
3758
3759 return caja_file_should_show (file,
3760 options & SHOW_HIDDEN,
3761 TRUE(!(0)),
3762 options & SHOW_BACKUP);
3763}
3764
3765GList *
3766caja_file_list_filter_hidden (GList *files,
3767 gboolean show_hidden)
3768{
3769 GList *filtered_files;
3770 GList *removed_files;
3771
3772 /* FIXME bugzilla.gnome.org 40653:
3773 * Eventually this should become a generic filtering thingy.
3774 */
3775
3776 filtered_files = caja_file_list_copy (files);
3777 filtered_files = eel_g_list_partition (filtered_files,
3778 filter_hidden_partition_callback,
3779 GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0))((gpointer) (glong) ((show_hidden ? SHOW_HIDDEN : 0))),
3780 &removed_files);
3781 caja_file_list_free (removed_files);
3782
3783 return filtered_files;
3784}
3785
3786char *
3787caja_file_get_metadata (CajaFile *file,
3788 const char *key,
3789 const char *default_metadata)
3790{
3791 guint id;
3792 char *value;
3793
3794 g_return_val_if_fail (key != NULL, g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if (key != ((void*)0)) _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__)), "key != NULL"); return
(g_strdup_inline (default_metadata)); } } while (0)
;
3795 g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if (key[0] != '\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__)), "key[0] != '\\0'"
); return (g_strdup_inline (default_metadata)); } } while (0)
;
3796
3797 if (file == NULL((void*)0) ||
3798 file->details->metadata == NULL((void*)0)) {
3799 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3800 }
3801
3802 g_return_val_if_fail (CAJA_IS_FILE (file), g_strdup (default_metadata))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_200
= 1; else _g_boolean_var_200 = 0; _g_boolean_var_200; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (g_strdup_inline
(default_metadata)); } } while (0)
;
3803
3804 id = caja_metadata_get_id (key);
3805 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3806
3807 if (value) {
3808 return g_strdup (value)g_strdup_inline (value);
3809 }
3810 return g_strdup (default_metadata)g_strdup_inline (default_metadata);
3811}
3812
3813GList *
3814caja_file_get_metadata_list (CajaFile *file,
3815 const char *key)
3816{
3817 guint id;
3818 char **value;
3819
3820 g_return_val_if_fail (key != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if (key != ((void*)0)) _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__)), "key != NULL"); return
(((void*)0)); } } while (0)
;
3821 g_return_val_if_fail (key[0] != '\0', NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (key[0] != '\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__)), "key[0] != '\\0'"
); return (((void*)0)); } } while (0)
;
3822
3823 if (file == NULL((void*)0) ||
3824 file->details->metadata == NULL((void*)0)) {
3825 return NULL((void*)0);
3826 }
3827
3828 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_203
= 1; else _g_boolean_var_203 = 0; _g_boolean_var_203; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
3829
3830 id = caja_metadata_get_id (key);
3831 id |= METADATA_ID_IS_LIST_MASK(1U<<31);
3832
3833 value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)((gpointer) (gulong) (id)));
3834
3835 if (value) {
3836 GList *res;
3837 int i;
3838
3839 res = NULL((void*)0);
3840 for (i = 0; value[i] != NULL((void*)0); i++) {
3841 res = g_list_prepend (res, g_strdup (value[i])g_strdup_inline (value[i]));
3842 }
3843 return g_list_reverse (res);
3844 }
3845
3846 return NULL((void*)0);
3847}
3848
3849void
3850caja_file_set_metadata (CajaFile *file,
3851 const char *key,
3852 const char *default_metadata,
3853 const char *metadata)
3854{
3855 const char *val;
3856
3857 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_204
= 1; else _g_boolean_var_204 = 0; _g_boolean_var_204; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3858 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if (key != ((void*)0)) _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__)), "key != NULL"); return
; } } while (0)
;
3859 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (key[0] != '\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__)), "key[0] != '\\0'"
); return; } } while (0)
;
3860
3861 val = metadata;
3862 if (val == NULL((void*)0)) {
3863 val = default_metadata;
3864 }
3865
3866 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3867 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
3868 set_metadata, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata
) (file, key, val); } } while (0)
;
3869}
3870
3871void
3872caja_file_set_metadata_list (CajaFile *file,
3873 const char *key,
3874 GList *list)
3875{
3876 char **val;
3877 int len, i;
3878 GList *l;
3879
3880 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_207
= 1; else _g_boolean_var_207 = 0; _g_boolean_var_207; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
3881 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (key != ((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__)), "key != NULL"); return
; } } while (0)
;
3882 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return; } } while (0)
;
3883
3884 len = g_list_length (list);
3885 val = g_new (char *, len + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
3886 for (l = list, i = 0; l != NULL((void*)0); l = l->next, i++) {
3887 val[i] = l->data;
3888 }
3889 val[i] = NULL((void*)0);
3890
3891 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3892 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
3893 set_metadata_as_list, (file, key, val))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->set_metadata_as_list
) (file, key, val); } } while (0)
;
3894
3895 g_free (val);
3896}
3897
3898
3899gboolean
3900caja_file_get_boolean_metadata (CajaFile *file,
3901 const char *key,
3902 gboolean default_metadata)
3903{
3904 char *result_as_string;
3905 gboolean result;
3906
3907 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if (key != ((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__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3908 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (key[0] != '\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__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3909
3910 if (file == NULL((void*)0)) {
3911 return default_metadata;
3912 }
3913
3914 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_212
= 1; else _g_boolean_var_212 = 0; _g_boolean_var_212; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3915
3916 result_as_string = caja_file_get_metadata
3917 (file, key, default_metadata ? "true" : "false");
3918 g_assert (result_as_string != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if (result_as_string != ((void*)0)) _g_boolean_var_213 = 1;
else _g_boolean_var_213 = 0; _g_boolean_var_213; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file.c", 3918,
((const char*) (__func__)), "result_as_string != NULL"); } while
(0)
;
3919
3920 if (g_ascii_strcasecmp (result_as_string, "true") == 0) {
3921 result = TRUE(!(0));
3922 } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) {
3923 result = FALSE(0);
3924 } else {
3925 g_error ("boolean metadata with value other than true or false");
3926 result = default_metadata;
3927 }
3928
3929 g_free (result_as_string);
3930 return result;
3931}
3932
3933int
3934caja_file_get_integer_metadata (CajaFile *file,
3935 const char *key,
3936 int default_metadata)
3937{
3938 char *result_as_string;
3939 char default_as_string[32];
3940 int result;
3941 char c;
3942
3943 g_return_val_if_fail (key != NULL, default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if (key != ((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__)), "key != NULL"); return
(default_metadata); } } while (0)
;
3944 g_return_val_if_fail (key[0] != '\0', default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return (default_metadata); } } while (0)
;
3945
3946 if (file == NULL((void*)0)) {
3947 return default_metadata;
3948 }
3949 g_return_val_if_fail (CAJA_IS_FILE (file), default_metadata)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_216
= 1; else _g_boolean_var_216 = 0; _g_boolean_var_216; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (default_metadata
); } } while (0)
;
3950
3951 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
3952 result_as_string = caja_file_get_metadata
3953 (file, key, default_as_string);
3954
3955 /* Normally we can't get a a NULL, but we check for it here to
3956 * handle the oddball case of a non-existent directory.
3957 */
3958 if (result_as_string == NULL((void*)0)) {
3959 result = default_metadata;
3960 } else {
3961 if (sscanf (result_as_string, " %d %c", &result, &c) != 1) {
3962 result = default_metadata;
3963 }
3964 g_free (result_as_string);
3965 }
3966
3967 return result;
3968}
3969
3970static gboolean
3971get_time_from_time_string (const char *time_string,
3972 time_t *time)
3973{
3974 long scanned_time;
3975 char c;
3976
3977 g_assert (time != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if (time != ((void*)0)) _g_boolean_var_217 = 1; else _g_boolean_var_217
= 0; _g_boolean_var_217; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 3977, ((const char*) (__func__
)), "time != NULL"); } while (0)
;
3978
3979 /* Only accept string if it has one integer with nothing
3980 * afterwards.
3981 */
3982 if (time_string == NULL((void*)0) ||
3983 sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) {
3984 return FALSE(0);
3985 }
3986 *time = (time_t) scanned_time;
3987 return TRUE(!(0));
3988}
3989
3990time_t
3991caja_file_get_time_metadata (CajaFile *file,
3992 const char *key)
3993{
3994 time_t time;
3995 char *time_string;
3996
3997 time_string = caja_file_get_metadata (file, key, NULL((void*)0));
3998 if (!get_time_from_time_string (time_string, &time)) {
3999 time = UNDEFINED_TIME((time_t) (-1));
4000 }
4001 g_free (time_string);
4002
4003 return time;
4004}
4005
4006void
4007caja_file_set_time_metadata (CajaFile *file,
4008 const char *key,
4009 time_t time)
4010{
4011 char time_str[21];
4012 char *metadata;
4013
4014 if (time != UNDEFINED_TIME((time_t) (-1))) {
4015 /* 2^64 turns out to be 20 characters */
4016 g_snprintf (time_str, 20, "%ld", (long int)time);
4017 time_str[20] = '\0';
4018 metadata = time_str;
4019 } else {
4020 metadata = NULL((void*)0);
4021 }
4022
4023 caja_file_set_metadata (file, key, NULL((void*)0), metadata);
4024}
4025
4026
4027void
4028caja_file_set_boolean_metadata (CajaFile *file,
4029 const char *key,
4030 gboolean default_metadata,
4031 gboolean metadata)
4032{
4033 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_218
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_218
= 1; else _g_boolean_var_218 = 0; _g_boolean_var_218; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4034 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_219
; if (key != ((void*)0)) _g_boolean_var_219 = 1; else _g_boolean_var_219
= 0; _g_boolean_var_219; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
; } } while (0)
;
4035 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_220
; if (key[0] != '\0') _g_boolean_var_220 = 1; else _g_boolean_var_220
= 0; _g_boolean_var_220; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key[0] != '\\0'"
); return; } } while (0)
;
4036
4037 caja_file_set_metadata (file, key,
4038 default_metadata ? "true" : "false",
4039 metadata ? "true" : "false");
4040}
4041
4042void
4043caja_file_set_integer_metadata (CajaFile *file,
4044 const char *key,
4045 int default_metadata,
4046 int metadata)
4047{
4048 char value_as_string[32];
4049 char default_as_string[32];
4050
4051 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_221
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_221
= 1; else _g_boolean_var_221 = 0; _g_boolean_var_221; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4052 g_return_if_fail (key != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if (key != ((void*)0)) _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__)), "key != NULL"); return
; } } while (0)
;
4053 g_return_if_fail (key[0] != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_223
; if (key[0] != '\0') _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__)), "key[0] != '\\0'"
); return; } } while (0)
;
4054
4055 g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata);
4056 g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata);
4057
4058 caja_file_set_metadata (file, key,
4059 default_as_string, value_as_string);
4060}
4061
4062static const char *
4063caja_file_peek_display_name_collation_key (CajaFile *file)
4064{
4065 const char *res;
4066
4067 res = file->details->display_name_collation_key;
4068 if (res == NULL((void*)0))
4069 res = "";
4070
4071 return res;
4072}
4073
4074static const char *
4075caja_file_peek_display_name (CajaFile *file)
4076{
4077 /*
4078 stefano-k: Imported 15_nautilus_file_peek_crash.patch from debian nautilus
4079 Date: Thu, 27 Jan 2011 10:22:10 +0000
4080 Subject: Prevent a crash in nautilus_file_peek_display_name() on invalid NautilusFile
4081 This is more a workaround only, expect assert failures at other
4082 places when something bad happens. There's a race condition somewhere,
4083 this patch only prevents immediate crash.
4084 Patch by Marcus Husar <marcus.husar@rose.uni-heidelberg.de>
4085 https://bugzilla.gnome.org/show_bug.cgi?id=602500
4086 */
4087 if (file == NULL((void*)0) || caja_file_is_gone (file))
4088 return "";
4089
4090 /* Default to display name based on filename if its not set yet */
4091
4092 if (file->details->display_name == NULL((void*)0)) {
4093 const char *name;
4094
4095 name = file->details->name;
4096 if (g_utf8_validate (name, -1, NULL((void*)0))) {
4097 caja_file_set_display_name (file,
4098 name,
4099 NULL((void*)0),
4100 FALSE(0));
4101 } else {
4102 char *escaped_name;
4103
4104 escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
4105 caja_file_set_display_name (file,
4106 escaped_name,
4107 NULL((void*)0),
4108 FALSE(0));
4109 g_free (escaped_name);
4110 }
4111 }
4112
4113 return file->details->display_name;
4114}
4115
4116char *
4117caja_file_get_display_name (CajaFile *file)
4118{
4119 return g_strdup (caja_file_peek_display_name (file))g_strdup_inline (caja_file_peek_display_name (file));
4120}
4121
4122char *
4123caja_file_get_edit_name (CajaFile *file)
4124{
4125 const char *res;
4126
4127 res = file->details->edit_name;
4128 if (res == NULL((void*)0))
4129 res = "";
4130
4131 return g_strdup (res)g_strdup_inline (res);
4132}
4133
4134char *
4135caja_file_get_name (CajaFile *file)
4136{
4137 return g_strdup (file->details->name)g_strdup_inline (file->details->name);
4138}
4139
4140/**
4141 * caja_file_get_description:
4142 * @file: a #CajaFile.
4143 *
4144 * Gets the standard::description key from @file, if
4145 * it has been cached.
4146 *
4147 * Returns: a string containing the value of the standard::description
4148 * key, or %NULL.
4149 */
4150char *
4151caja_file_get_description (CajaFile *file)
4152{
4153 return g_strdup (file->details->description)g_strdup_inline (file->details->description);
4154}
4155
4156void
4157caja_file_monitor_add (CajaFile *file,
4158 gconstpointer client,
4159 CajaFileAttributes attributes)
4160{
4161 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_224
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_224
= 1; else _g_boolean_var_224 = 0; _g_boolean_var_224; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4162 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_225
; if (client != ((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__)), "client != NULL")
; return; } } while (0)
;
4163
4164 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4165 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
4166 monitor_add, (file, client, attributes))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_add
) (file, client, attributes); } } while (0)
;
4167}
4168
4169void
4170caja_file_monitor_remove (CajaFile *file,
4171 gconstpointer client)
4172{
4173 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_226
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_226
= 1; else _g_boolean_var_226 = 0; _g_boolean_var_226; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
4174 g_return_if_fail (client != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if (client != ((void*)0)) _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__)), "client != NULL")
; return; } } while (0)
;
4175
4176 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4177 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
4178 monitor_remove, (file, client))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->monitor_remove
) (file, client); } } while (0)
;
4179}
4180
4181gboolean
4182caja_file_is_launcher (CajaFile *file)
4183{
4184 return file->details->is_launcher;
4185}
4186
4187gboolean
4188caja_file_is_foreign_link (CajaFile *file)
4189{
4190 return file->details->is_foreign_link;
4191}
4192
4193gboolean
4194caja_file_is_trusted_link (CajaFile *file)
4195{
4196 return file->details->is_trusted_link;
4197}
4198
4199gboolean
4200caja_file_has_activation_uri (CajaFile *file)
4201{
4202 return file->details->activation_uri != NULL((void*)0);
4203}
4204
4205
4206/* Return the uri associated with the passed-in file, which may not be
4207 * the actual uri if the file is an desktop file or a caja
4208 * xml link file.
4209 */
4210char *
4211caja_file_get_activation_uri (CajaFile *file)
4212{
4213 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_228
= 1; else _g_boolean_var_228 = 0; _g_boolean_var_228; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4214
4215 if (file->details->activation_uri != NULL((void*)0)) {
4216 return g_strdup (file->details->activation_uri)g_strdup_inline (file->details->activation_uri);
4217 }
4218
4219 return caja_file_get_uri (file);
4220}
4221
4222GFile *
4223caja_file_get_activation_location (CajaFile *file)
4224{
4225 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_229
= 1; else _g_boolean_var_229 = 0; _g_boolean_var_229; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4226
4227 if (file->details->activation_uri != NULL((void*)0)) {
4228 return g_file_new_for_uri (file->details->activation_uri);
4229 }
4230
4231 return caja_file_get_location (file);
4232}
4233
4234
4235char *
4236caja_file_get_drop_target_uri (CajaFile *file)
4237{
4238 char *uri, *target_uri;
4239 GFile *location;
4240
4241 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_230
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_230
= 1; else _g_boolean_var_230 = 0; _g_boolean_var_230; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4242
4243 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
4244 CajaDesktopLink *link;
4245
4246 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
4247
4248 if (link != NULL((void*)0)) {
4249 location = caja_desktop_link_get_activation_location (link);
4250 g_object_unref (link);
4251 if (location != NULL((void*)0)) {
4252 uri = g_file_get_uri (location);
4253 g_object_unref (location);
4254 return uri;
4255 }
4256 }
4257 }
4258
4259 uri = caja_file_get_uri (file);
4260
4261 /* Check for Caja link */
4262 if (caja_file_is_caja_link (file)) {
4263 location = caja_file_get_location (file);
4264 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
4265 if (g_file_is_native (location)) {
4266 target_uri = caja_link_local_get_link_uri (uri);
4267 if (target_uri != NULL((void*)0)) {
4268 g_free (uri);
4269 uri = target_uri;
4270 }
4271 }
4272 g_object_unref (location);
4273 }
4274
4275 return uri;
4276}
4277
4278static gboolean
4279is_uri_relative (const char *uri)
4280{
4281 char *scheme;
4282 gboolean ret;
4283
4284 scheme = g_uri_parse_scheme (uri);
4285 ret = (scheme == NULL((void*)0));
4286 g_free (scheme);
4287 return ret;
4288}
4289
4290static char *
4291get_custom_icon_metadata_uri (CajaFile *file)
4292{
4293 char *custom_icon_uri;
4294 char *uri;
4295
4296 uri = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
4297 if (uri != NULL((void*)0) &&
4298 caja_file_is_directory (file) &&
4299 is_uri_relative (uri)) {
4300 char *dir_uri;
4301
4302 dir_uri = caja_file_get_uri (file);
4303 custom_icon_uri = g_build_filename (dir_uri, uri, NULL((void*)0));
4304 g_free (dir_uri);
4305 g_free (uri);
4306 } else {
4307 custom_icon_uri = uri;
4308 }
4309 return custom_icon_uri;
4310}
4311
4312static GIcon *
4313get_custom_icon (CajaFile *file)
4314{
4315 char *custom_icon_uri;
4316 GFile *icon_file;
4317 GIcon *icon;
4318
4319 if (file == NULL((void*)0)) {
4320 return NULL((void*)0);
4321 }
4322
4323 icon = NULL((void*)0);
4324
4325 /* Metadata takes precedence */
4326 custom_icon_uri = get_custom_icon_metadata_uri (file);
4327
4328 if (custom_icon_uri) {
4329 icon_file = g_file_new_for_uri (custom_icon_uri);
4330 icon = g_file_icon_new (icon_file);
4331 g_object_unref (icon_file);
4332 g_free (custom_icon_uri);
4333 }
4334
4335 if (icon == NULL((void*)0) && file->details->got_link_info && file->details->custom_icon != NULL((void*)0)) {
4336 if (g_path_is_absolute (file->details->custom_icon)) {
4337 icon_file = g_file_new_for_path (file->details->custom_icon);
4338 icon = g_file_icon_new (icon_file);
4339 g_object_unref (icon_file);
4340 } else {
4341 icon = g_themed_icon_new (file->details->custom_icon);
4342 }
4343 }
4344
4345 return icon;
4346}
4347
4348
4349static guint64 cached_thumbnail_limit;
4350int cached_thumbnail_size;
4351static int show_image_thumbs;
4352
4353GFilesystemPreviewType
4354caja_file_get_filesystem_use_preview (CajaFile *file)
4355{
4356 GFilesystemPreviewType use_preview;
4357 CajaFile *parent;
4358
4359 parent = caja_file_get_parent (file);
4360 if (parent != NULL((void*)0)) {
4361 use_preview = parent->details->filesystem_use_preview;
4362 g_object_unref (parent);
4363 } else {
4364 use_preview = 0;
4365 }
4366
4367 return use_preview;
4368}
4369
4370gboolean
4371caja_file_should_show_thumbnail (CajaFile *file)
4372{
4373 const char *mime_type;
4374 GFilesystemPreviewType use_preview;
4375
4376 use_preview = caja_file_get_filesystem_use_preview (file);
4377
4378 mime_type = file->details->mime_type;
4379 if (mime_type == NULL((void*)0)) {
4380 mime_type = "application/octet-stream";
4381 }
4382
4383 /* If the thumbnail has already been created, don't care about the size
4384 * of the original file.
4385 */
4386 if (caja_thumbnail_is_mimetype_limited_by_size (mime_type) &&
4387 file->details->thumbnail_path == NULL((void*)0) &&
4388 caja_file_get_size (file) > cached_thumbnail_limit) {
4389 return FALSE(0);
4390 }
4391
4392 if (show_image_thumbs == CAJA_SPEED_TRADEOFF_ALWAYS) {
4393 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4394 return FALSE(0);
4395 } else {
4396 return TRUE(!(0));
4397 }
4398 } else if (show_image_thumbs == CAJA_SPEED_TRADEOFF_NEVER) {
4399 return FALSE(0);
4400 } else {
4401 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
4402 /* file system says to never thumbnail anything */
4403 return FALSE(0);
4404 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
4405 /* file system says we should treat file as if it's local */
4406 return TRUE(!(0));
4407 } else {
4408 /* only local files */
4409 return caja_file_is_local (file);
4410 }
4411 }
4412
4413 return FALSE(0);
4414}
4415
4416static void
4417prepend_icon_name (const char *name,
4418 GThemedIcon *icon)
4419{
4420 g_themed_icon_prepend_name(icon, name);
4421}
4422
4423GIcon *
4424caja_file_get_gicon (CajaFile *file,
4425 CajaFileIconFlags flags)
4426{
4427 const char * const * names;
4428 GIcon *icon, *mount_icon = NULL((void*)0), *emblemed_icon;
4429 gboolean is_folder = FALSE(0), is_preview = FALSE(0), is_inode_directory = FALSE(0);
4430
4431 if (file == NULL((void*)0)) {
4432 return NULL((void*)0);
4433 }
4434
4435 icon = get_custom_icon (file);
4436 if (icon != NULL((void*)0)) {
4437 return icon;
4438 }
4439
4440 if (file->details->icon) {
4441 icon = NULL((void*)0);
4442
4443 /* fetch the mount icon here, we'll use it later */
4444 if (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON ||
4445 flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) {
4446 GMount *mount;
4447
4448 mount = caja_file_get_mount (file);
4449
4450 if (mount != NULL((void*)0)) {
4451 mount_icon = g_mount_get_icon (mount);
4452 g_object_unref (mount);
4453 }
4454 }
4455
4456 if (((flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) ||
4457 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) ||
4458 (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) ||
4459 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) ||
4460 (flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) ||
4461 ((flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4462 caja_file_has_open_window (file))) &&
4463 G_IS_THEMED_ICON (file->details->icon)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file->details->icon)); GType __t = ((g_themed_icon_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; }))))
) {
4464 GPtrArray *prepend_array;
4465 int i;
4466
4467 names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon)((((GThemedIcon*) (void *) ((file->details->icon))))));
4468 prepend_array = g_ptr_array_new ();
4469
4470 for (i = 0; names[i] != NULL((void*)0); i++) {
4471 const char *name;
4472
4473 name = names[i];
4474
4475 if (strcmp (name, "folder") == 0) {
4476 is_folder = TRUE(!(0));
4477 }
4478 if (strcmp (name, "inode-directory") == 0) {
4479 is_inode_directory = TRUE(!(0));
4480 }
4481 if (strcmp (name, "text-x-generic") == 0 &&
4482 (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT)) {
4483 is_preview = TRUE(!(0));
4484 }
4485 }
4486
4487 /* Here, we add icons in reverse order of precedence,
4488 * because they are later prepended */
4489 if (is_preview) {
4490 g_ptr_array_add (prepend_array, "text-x-preview");
4491 }
4492
4493 /* "folder" should override "inode-directory", not the other way around */
4494 if (is_inode_directory) {
4495 g_ptr_array_add (prepend_array, "folder");
4496 }
4497 if (is_folder && (flags & CAJA_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) {
4498 g_ptr_array_add (prepend_array, "folder-open");
4499 }
4500 if (is_folder &&
4501 (flags & CAJA_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 &&
4502 caja_file_has_open_window (file)) {
4503 g_ptr_array_add (prepend_array, "folder-visiting");
4504 }
4505 if (is_folder &&
4506 (flags & CAJA_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) {
4507 g_ptr_array_add (prepend_array, "folder-drag-accept");
4508 }
4509
4510 if (prepend_array->len) {
4511 /* When constructing GThemed Icon, pointers from the array
4512 * are reused, but not the array itself, so the cast is safe */
4513 icon = g_themed_icon_new_from_names ((char**) names, -1);
4514 g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon);
4515 }
4516
4517 g_ptr_array_free (prepend_array, TRUE(!(0)));
4518 }
4519
4520 if (icon == NULL((void*)0)) {
4521 icon = g_object_ref (file->details->icon)((__typeof__ (file->details->icon)) (g_object_ref) (file
->details->icon))
;
4522 }
4523
4524 if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON) &&
4525 mount_icon != NULL((void*)0)) {
4526 g_object_unref (icon);
4527 icon = mount_icon;
4528 } else if ((flags & CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) &&
4529 mount_icon != NULL((void*)0) && !g_icon_equal (mount_icon, icon)) {
4530 GEmblem *emblem;
4531
4532 emblem = g_emblem_new (mount_icon);
4533 emblemed_icon = g_emblemed_icon_new (icon, emblem);
4534
4535 g_object_unref (emblem);
4536 g_object_unref (icon);
4537 g_object_unref (mount_icon);
4538
4539 icon = emblemed_icon;
4540 } else if (mount_icon != NULL((void*)0)) {
4541 g_object_unref (mount_icon);
4542 }
4543
4544 return icon;
4545 }
4546
4547 return g_themed_icon_new ("text-x-generic");
4548}
4549
4550static GIcon *
4551get_default_file_icon (CajaFileIconFlags flags)
4552{
4553 static GIcon *fallback_icon = NULL((void*)0);
4554 static GIcon *fallback_icon_preview = NULL((void*)0);
4555 if (fallback_icon == NULL((void*)0)) {
4556 fallback_icon = g_themed_icon_new ("text-x-generic");
4557 fallback_icon_preview = g_themed_icon_new ("text-x-preview");
4558 g_themed_icon_append_name (G_THEMED_ICON (fallback_icon_preview)((((GThemedIcon*) (void *) ((fallback_icon_preview))))), "text-x-generic");
4559 }
4560 if (flags & CAJA_FILE_ICON_FLAGS_EMBEDDING_TEXT) {
4561 return fallback_icon_preview;
4562 } else {
4563 return fallback_icon;
4564 }
4565}
4566
4567CajaIconInfo *
4568caja_file_get_icon (CajaFile *file,
4569 int size,
4570 int scale,
4571 CajaFileIconFlags flags)
4572{
4573 CajaIconInfo *icon;
4574 GIcon *gicon;
4575 GdkPixbuf *scaled_pixbuf;
4576
4577 if (file == NULL((void*)0)) {
4578 return NULL((void*)0);
4579 }
4580
4581 gicon = get_custom_icon (file);
4582 if (gicon) {
4583 GdkPixbuf *pixbuf;
4584
4585 icon = caja_icon_info_lookup (gicon, size, scale);
4586 g_object_unref (gicon);
4587
4588 pixbuf = caja_icon_info_get_pixbuf (icon);
4589 if (pixbuf != NULL((void*)0)) {
4590 if (!file->details->is_launcher && !gdk_pixbuf_get_has_alpha (pixbuf)) {
4591 caja_ui_frame_image (&pixbuf);
4592 }
4593 g_object_unref (icon);
4594
4595 icon = caja_icon_info_new_for_pixbuf (pixbuf, scale);
4596 g_object_unref (pixbuf);
4597 }
4598
4599 return icon;
4600 }
4601
4602 if (flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS &&
4603 caja_file_should_show_thumbnail (file)) {
4604 int modified_size;
4605
4606 if (flags & CAJA_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) {
4607 modified_size = size * scale;
4608 } else {
4609 modified_size = size * scale * cached_thumbnail_size / CAJA_ICON_SIZE_STANDARD48;
4610 }
4611
4612 if (file->details->thumbnail) {
4613 int w, h, s;
4614 double thumb_scale;
4615 GdkPixbuf *raw_pixbuf;
4616
4617 raw_pixbuf = g_object_ref (file->details->thumbnail)((__typeof__ (file->details->thumbnail)) (g_object_ref)
(file->details->thumbnail))
;
4618
4619 w = gdk_pixbuf_get_width (raw_pixbuf);
4620 h = gdk_pixbuf_get_height (raw_pixbuf);
4621
4622 s = MAX (w, h)(((w) > (h)) ? (w) : (h));
4623 /* Don't scale up small thumbnails in the standard view */
4624 if (s <= cached_thumbnail_size) {
4625 thumb_scale = (double)size / CAJA_ICON_SIZE_STANDARD48;
4626 }
4627 else {
4628 thumb_scale = (double)modified_size / s;
4629 }
4630 /* Make sure that icons don't get smaller than CAJA_ICON_SIZE_SMALLEST */
4631 if (s*thumb_scale <= CAJA_ICON_SIZE_SMALLEST16) {
4632 thumb_scale = (double) CAJA_ICON_SIZE_SMALLEST16 / s;
4633 }
4634
4635 scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf,
4636 MAX (w * thumb_scale, 1)(((w * thumb_scale) > (1)) ? (w * thumb_scale) : (1)),
4637 MAX (h * thumb_scale, 1)(((h * thumb_scale) > (1)) ? (h * thumb_scale) : (1)),
4638 GDK_INTERP_BILINEAR);
4639
4640 /* Render frames only for thumbnails of non-image files
4641 and for images with no alpha channel. */
4642 gboolean is_image = file->details->mime_type &&
4643 (strncmp (file->details->mime_type, "image/", 6) == 0);
4644 if (!is_image || !gdk_pixbuf_get_has_alpha (raw_pixbuf)) {
4645 caja_ui_frame_image (&scaled_pixbuf);
4646 }
4647
4648 g_object_unref (raw_pixbuf);
4649
4650 /* Don't scale up if more than 25%, then read the original
4651 image instead. We don't want to compare to exactly 100%,
4652 since the zoom level 150% gives thumbnails at 144, which is
4653 ok to scale up from 128. */
4654 if (modified_size > 128 * 1.25 * scale &&
4655 !file->details->thumbnail_wants_original &&
4656 caja_can_thumbnail_internally (file)) {
4657 /* Invalidate if we resize upward */
4658 file->details->thumbnail_wants_original = TRUE(!(0));
4659 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_THUMBNAIL);
4660 }
4661
4662 icon = caja_icon_info_new_for_pixbuf (scaled_pixbuf, scale);
4663 g_object_unref (scaled_pixbuf);
4664 return icon;
4665 } else if (file->details->thumbnail_path == NULL((void*)0) &&
4666 file->details->can_read &&
4667 !file->details->is_thumbnailing &&
4668 !file->details->thumbnailing_failed) {
4669 if (caja_can_thumbnail (file)) {
4670 caja_create_thumbnail (file);
4671 }
4672 }
4673 }
4674
4675 if (file->details->is_thumbnailing &&
4676 flags & CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS)
4677 gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING"image-loading");
4678 else
4679 gicon = caja_file_get_gicon (file, flags);
4680
4681 if (gicon) {
4682 icon = caja_icon_info_lookup (gicon, size, scale);
4683 g_object_unref (gicon);
4684 return icon;
4685 } else {
4686 return caja_icon_info_lookup (get_default_file_icon (flags), size, scale);
4687 }
4688}
4689
4690cairo_surface_t *
4691caja_file_get_icon_surface (CajaFile *file,
4692 int size,
4693 gboolean force_size,
4694 int scale,
4695 CajaFileIconFlags flags)
4696{
4697 CajaIconInfo *info;
4698 cairo_surface_t *surface;
4699
4700 info = caja_file_get_icon (file, size, scale, flags);
4701 if (force_size) {
4702 surface = caja_icon_info_get_surface_at_size (info, size);
4703 } else {
4704 surface = caja_icon_info_get_surface (info);
4705 }
4706 g_object_unref (info);
4707
4708 return surface;
4709}
4710
4711char *
4712caja_file_get_custom_icon (CajaFile *file)
4713{
4714 char *custom_icon;
4715
4716 if (file == NULL((void*)0)) {
4717 return NULL((void*)0);
4718 }
4719
4720 /* Metadata takes precedence */
4721 custom_icon = get_custom_icon_metadata_uri (file);
4722
4723 if (custom_icon == NULL((void*)0) && file->details->got_link_info) {
4724 custom_icon = g_strdup (file->details->custom_icon)g_strdup_inline (file->details->custom_icon);
4725 }
4726
4727 return custom_icon;
4728}
4729
4730
4731gboolean
4732caja_file_get_date (CajaFile *file,
4733 CajaDateType date_type,
4734 time_t *date)
4735{
4736 if (date != NULL((void*)0)) {
4737 *date = 0;
4738 }
4739
4740 g_return_val_if_fail (date_type == CAJA_DATE_TYPE_CHANGEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _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__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4741 || date_type == CAJA_DATE_TYPE_ACCESSEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _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__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4742 || date_type == CAJA_DATE_TYPE_MODIFIEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _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__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4743 || date_type == CAJA_DATE_TYPE_CREATEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _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__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4744 || date_type == CAJA_DATE_TYPE_TRASHEDdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _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__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
4745 || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if (date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED
|| date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED
|| date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED
) _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__)), "date_type == CAJA_DATE_TYPE_CHANGED || date_type == CAJA_DATE_TYPE_ACCESSED || date_type == CAJA_DATE_TYPE_MODIFIED || date_type == CAJA_DATE_TYPE_CREATED || date_type == CAJA_DATE_TYPE_TRASHED || date_type == CAJA_DATE_TYPE_PERMISSIONS_CHANGED"
); return ((0)); } } while (0)
;
4746
4747 if (file == NULL((void*)0)) {
4748 return FALSE(0);
4749 }
4750
4751 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_232
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_232
= 1; else _g_boolean_var_232 = 0; _g_boolean_var_232; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
4752
4753 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4754 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
4755 get_date, (file, date_type, date))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_date == ((void*)0))
? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass*) (
((GTypeInstance*) ((file)))->g_class)))))))))->get_date
) (file, date_type, date))
;
4756}
4757
4758static char *
4759caja_file_get_where_string (CajaFile *file)
4760{
4761 if (file == NULL((void*)0)) {
4762 return NULL((void*)0);
4763 }
4764
4765 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_233
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_233
= 1; else _g_boolean_var_233 = 0; _g_boolean_var_233; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
4766
4767 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4768 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
4769 get_where_string, (file))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_where_string == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_where_string
) (file))
;
4770}
4771
4772static const char *TODAY_TIME_FORMATS [] = {
4773 /* Today, use special word.
4774 * strftime patterns preceeded with the widest
4775 * possible resulting string for that pattern.
4776 *
4777 * Note to localizers: You can look at man strftime
4778 * for details on the format, but you should only use
4779 * the specifiers from the C standard, not extensions.
4780 * These include "%" followed by one of
4781 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
4782 * in the Caja version of strftime that can be
4783 * used (and match GNU extensions). Putting a "-"
4784 * between the "%" and any numeric directive will turn
4785 * off zero padding, and putting a "_" there will use
4786 * space padding instead of zero padding.
4787 */
4788 N_("today at 00:00:00 PM")("today at 00:00:00 PM"),
4789 N_("today at %-I:%M:%S %p")("today at %-I:%M:%S %p"),
4790
4791 N_("today at 00:00 PM")("today at 00:00 PM"),
4792 N_("today at %-I:%M %p")("today at %-I:%M %p"),
4793
4794 N_("today, 00:00 PM")("today, 00:00 PM"),
4795 N_("today, %-I:%M %p")("today, %-I:%M %p"),
4796
4797 N_("today")("today"),
4798 N_("today")("today"),
4799
4800 NULL((void*)0)
4801};
4802
4803static const char *YESTERDAY_TIME_FORMATS [] = {
4804 /* Yesterday, use special word.
4805 * Note to localizers: Same issues as "today" string.
4806 */
4807 N_("yesterday at 00:00:00 PM")("yesterday at 00:00:00 PM"),
4808 N_("yesterday at %-I:%M:%S %p")("yesterday at %-I:%M:%S %p"),
4809
4810 N_("yesterday at 00:00 PM")("yesterday at 00:00 PM"),
4811 N_("yesterday at %-I:%M %p")("yesterday at %-I:%M %p"),
4812
4813 N_("yesterday, 00:00 PM")("yesterday, 00:00 PM"),
4814 N_("yesterday, %-I:%M %p")("yesterday, %-I:%M %p"),
4815
4816 N_("yesterday")("yesterday"),
4817 N_("yesterday")("yesterday"),
4818
4819 NULL((void*)0)
4820};
4821
4822static const char *CURRENT_WEEK_TIME_FORMATS [] = {
4823 /* Current week, include day of week.
4824 * Note to localizers: Same issues as "today" string.
4825 * The width measurement templates correspond to
4826 * the day/month name with the most letters.
4827 */
4828 N_("Wednesday, September 00 0000 at 00:00:00 PM")("Wednesday, September 00 0000 at 00:00:00 PM"),
4829 N_("%A, %B %-d %Y at %-I:%M:%S %p")("%A, %B %-d %Y at %-I:%M:%S %p"),
4830
4831 N_("Mon, Oct 00 0000 at 00:00:00 PM")("Mon, Oct 00 0000 at 00:00:00 PM"),
4832 N_("%a, %b %-d %Y at %-I:%M:%S %p")("%a, %b %-d %Y at %-I:%M:%S %p"),
4833
4834 N_("Mon, Oct 00 0000 at 00:00 PM")("Mon, Oct 00 0000 at 00:00 PM"),
4835 N_("%a, %b %-d %Y at %-I:%M %p")("%a, %b %-d %Y at %-I:%M %p"),
4836
4837 N_("Oct 00 0000 at 00:00 PM")("Oct 00 0000 at 00:00 PM"),
4838 N_("%b %-d %Y at %-I:%M %p")("%b %-d %Y at %-I:%M %p"),
4839
4840 N_("Oct 00 0000, 00:00 PM")("Oct 00 0000, 00:00 PM"),
4841 N_("%b %-d %Y, %-I:%M %p")("%b %-d %Y, %-I:%M %p"),
4842
4843 N_("00/00/00, 00:00 PM")("00/00/00, 00:00 PM"),
4844 N_("%m/%-d/%y, %-I:%M %p")("%m/%-d/%y, %-I:%M %p"),
4845
4846 N_("00/00/00")("00/00/00"),
4847 N_("%m/%d/%y")("%m/%d/%y"),
4848
4849 NULL((void*)0)
4850};
4851
4852static char *
4853caja_file_fit_date_as_string (CajaFile *file,
4854 CajaDateType date_type,
4855 int width,
4856 CajaWidthMeasureCallback measure_callback,
4857 CajaTruncateCallback truncate_callback,
4858 void *measure_context)
4859{
4860 time_t file_time_raw;
4861 const char **formats;
4862 const char *format;
4863 char *date_string;
4864 gchar *result = NULL((void*)0);
4865 int i;
4866 GDateTime *date_time, *today, *end_of_today;
4867 GTimeSpan file_date_age;
4868
4869 if (!caja_file_get_date (file, date_type, &file_time_raw)) {
4870 return NULL((void*)0);
4871 }
4872
4873 date_time = g_date_time_new_from_unix_local (file_time_raw);
4874
4875 if (date_format_pref == CAJA_DATE_FORMAT_LOCALE) {
4876 result = g_date_time_format (date_time, "%c");
4877 goto out;
4878 } else if (date_format_pref == CAJA_DATE_FORMAT_ISO) {
4879 result = g_date_time_format (date_time, "%Y-%m-%d %H:%M:%S");
4880 goto out;
4881 }
4882
4883 today = g_date_time_new_now_local ();
4884 end_of_today = g_date_time_add_full (today, 0, 0, 1,
4885 -1 * g_date_time_get_hour (today),
4886 -1 * g_date_time_get_minute (today),
4887 -1.0 * g_date_time_get_seconds (today));
4888 g_date_time_unref (today);
4889
4890 file_date_age = g_date_time_difference (end_of_today, date_time);
4891 g_date_time_unref (end_of_today);
4892
4893 /* Format varies depending on how old the date is. This minimizes
4894 * the length (and thus clutter & complication) of typical dates
4895 * while providing sufficient detail for recent dates to make
4896 * them maximally understandable at a glance. Keep all format
4897 * strings separate rather than combining bits & pieces for
4898 * internationalization's sake.
4899 */
4900
4901 if (file_date_age <= 0 || file_date_age > 2 * G_TIME_SPAN_DAY((86400000000L))) {
4902 formats = CURRENT_WEEK_TIME_FORMATS;
4903 } else if (file_date_age > G_TIME_SPAN_DAY((86400000000L))) {
4904 formats = YESTERDAY_TIME_FORMATS;
4905 } else {
4906 formats = TODAY_TIME_FORMATS;
4907 }
4908
4909 /* Find the date format that just fits the required width. Instead of measuring
4910 * the resulting string width directly, measure the width of a template that represents
4911 * the widest possible version of a date in a given format. This is done by using M, m
4912 * and 0 for the variable letters/digits respectively.
4913 */
4914 format = NULL((void*)0);
4915
4916 for (i = 0; ; i += 2) {
4917 const char *width_template;
4918
4919 width_template = (formats [i] ? _(formats [i])dcgettext (((void*)0), formats [i], 5) : NULL((void*)0));
4920 if (width_template == NULL((void*)0)) {
4921 /* no more formats left */
4922 g_assert (format != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_234
; if (format != ((void*)0)) _g_boolean_var_234 = 1; else _g_boolean_var_234
= 0; _g_boolean_var_234; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 4922, ((const char*) (__func__
)), "format != NULL"); } while (0)
;
4923
4924 /* Can't fit even the shortest format -- return an ellipsized form in the
4925 * shortest format
4926 */
4927
4928 date_string = g_date_time_format (date_time, format);
4929
4930 if (truncate_callback == NULL((void*)0)) {
4931 result = date_string;
4932 break;
4933 }
4934
4935 result = (* truncate_callback) (date_string, width, measure_context);
4936 g_free (date_string);
4937 break;
4938 }
4939
4940 format = _(formats [i + 1])dcgettext (((void*)0), formats [i + 1], 5);
4941
4942 if (measure_callback == NULL((void*)0)) {
4943 /* don't care about fitting the width */
4944 break;
4945 }
4946
4947 if ((* measure_callback) (width_template, measure_context) <= width) {
4948 /* The template fits, this is the format we can fit. */
4949 break;
4950 }
4951 }
4952
4953 if (result == NULL((void*)0)) {
4954 result = g_date_time_format (date_time, format);
4955 }
4956
4957out:
4958 g_date_time_unref (date_time);
4959 return result;
4960}
4961
4962/**
4963 * caja_file_fit_modified_date_as_string:
4964 *
4965 * Get a user-displayable string representing a file modification date,
4966 * truncated to @width using the measuring and truncating callbacks.
4967 * @file: CajaFile representing the file in question.
4968 * @width: The desired resulting string width.
4969 * @measure_callback: The callback used to measure the string width.
4970 * @truncate_callback: The callback used to truncate the string to a desired width.
4971 * @measure_context: Data neede when measuring and truncating.
4972 *
4973 * Returns: Newly allocated string ready to display to the user.
4974 *
4975 **/
4976char *
4977caja_file_fit_modified_date_as_string (CajaFile *file,
4978 int width,
4979 CajaWidthMeasureCallback measure_callback,
4980 CajaTruncateCallback truncate_callback,
4981 void *measure_context)
4982{
4983 return caja_file_fit_date_as_string (file, CAJA_DATE_TYPE_MODIFIED,
4984 width, measure_callback, truncate_callback, measure_context);
4985}
4986
4987static char *
4988caja_file_get_trash_original_file_parent_as_string (CajaFile *file)
4989{
4990 if (file->details->trash_orig_path != NULL((void*)0)) {
4991 CajaFile *orig_file, *parent;
4992 GFile *location;
4993 char *filename;
4994
4995 orig_file = caja_file_get_trash_original_file (file);
4996 parent = caja_file_get_parent (orig_file);
4997 location = caja_file_get_location (parent);
4998
4999 filename = g_file_get_parse_name (location);
5000
5001 g_object_unref (location);
5002 caja_file_unref (parent);
5003 caja_file_unref (orig_file);
5004
5005 return filename;
5006 }
5007
5008 return NULL((void*)0);
5009}
5010
5011/**
5012 * caja_file_get_date_as_string:
5013 *
5014 * Get a user-displayable string representing a file modification date.
5015 * The caller is responsible for g_free-ing this string.
5016 * @file: CajaFile representing the file in question.
5017 *
5018 * Returns: Newly allocated string ready to display to the user.
5019 *
5020 **/
5021static char *
5022caja_file_get_date_as_string (CajaFile *file, CajaDateType date_type)
5023{
5024 return caja_file_fit_date_as_string (file, date_type,
5025 0, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5026}
5027
5028static CajaSpeedTradeoffValue show_directory_item_count;
5029static CajaSpeedTradeoffValue show_text_in_icons;
5030
5031static void
5032show_text_in_icons_changed_callback (gpointer callback_data)
5033{
5034 show_text_in_icons = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS"show-icon-text");
5035}
5036
5037static void
5038show_directory_item_count_changed_callback (gpointer callback_data)
5039{
5040 show_directory_item_count = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS"show-directory-item-counts");
5041}
5042
5043static gboolean
5044get_speed_tradeoff_preference_for_file (CajaFile *file, CajaSpeedTradeoffValue value)
5045{
5046 GFilesystemPreviewType use_preview;
5047
5048 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_235
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_235
= 1; else _g_boolean_var_235 = 0; _g_boolean_var_235; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5049
5050 use_preview = caja_file_get_filesystem_use_preview (file);
5051
5052 if (value == CAJA_SPEED_TRADEOFF_ALWAYS) {
5053 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5054 return FALSE(0);
5055 } else {
5056 return TRUE(!(0));
5057 }
5058 }
5059
5060 if (value == CAJA_SPEED_TRADEOFF_NEVER) {
5061 return FALSE(0);
5062 }
5063
5064 g_assert (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_236
; if (value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY) _g_boolean_var_236
= 1; else _g_boolean_var_236 = 0; _g_boolean_var_236; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5064, ((const char*) (__func__)), "value == CAJA_SPEED_TRADEOFF_LOCAL_ONLY"
); } while (0)
;
5065
5066 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) {
5067 /* file system says to never preview anything */
5068 return FALSE(0);
5069 } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) {
5070 /* file system says we should treat file as if it's local */
5071 return TRUE(!(0));
5072 } else {
5073 /* only local files */
5074 return caja_file_is_local (file);
5075 }
5076}
5077
5078gboolean
5079caja_file_should_show_directory_item_count (CajaFile *file)
5080{
5081 static gboolean show_directory_item_count_callback_added = FALSE(0);
5082
5083 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_237
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_237
= 1; else _g_boolean_var_237 = 0; _g_boolean_var_237; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5084
5085 if (file->details->mime_type &&
5086 strcmp (file->details->mime_type, "x-directory/smb-share") == 0) {
5087 return FALSE(0);
5088 }
5089
5090 /* Add the callback once for the life of our process */
5091 if (!show_directory_item_count_callback_added) {
5092 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5093 "changed::" CAJA_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS,g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5094 G_CALLBACK(show_directory_item_count_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5095 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-directory-item-counts"
), (((GCallback) (show_directory_item_count_changed_callback)
)), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5096 show_directory_item_count_callback_added = TRUE(!(0));
5097
5098 /* Peek for the first time */
5099 show_directory_item_count_changed_callback (NULL((void*)0));
5100 }
5101
5102 return get_speed_tradeoff_preference_for_file (file, show_directory_item_count);
5103}
5104
5105gboolean
5106caja_file_should_show_type (CajaFile *file)
5107{
5108 char *uri;
5109 gboolean ret;
5110
5111 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_238
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_238
= 1; else _g_boolean_var_238 = 0; _g_boolean_var_238; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5112
5113 uri = caja_file_get_uri (file);
5114 ret = ((strcmp (uri, "computer:///") != 0) &&
5115 (strcmp (uri, "network:///") != 0) &&
5116 (strcmp (uri, "smb:///") != 0));
5117 g_free (uri);
5118
5119 return ret;
5120}
5121
5122gboolean
5123caja_file_should_get_top_left_text (CajaFile *file)
5124{
5125 static gboolean show_text_in_icons_callback_added = FALSE(0);
5126
5127 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_239
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_239
= 1; else _g_boolean_var_239 = 0; _g_boolean_var_239; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5128
5129 /* Add the callback once for the life of our process */
5130 if (!show_text_in_icons_callback_added) {
5131 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5132 "changed::" CAJA_PREFERENCES_SHOW_TEXT_IN_ICONS,g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5133 G_CALLBACK (show_text_in_icons_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
5134 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-icon-text"
), (((GCallback) (show_text_in_icons_changed_callback))), (((
void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
5135 show_text_in_icons_callback_added = TRUE(!(0));
5136
5137 /* Peek for the first time */
5138 show_text_in_icons_changed_callback (NULL((void*)0));
5139 }
5140
5141 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_ALWAYS) {
5142 return TRUE(!(0));
5143 }
5144
5145 if (show_text_in_icons == CAJA_SPEED_TRADEOFF_NEVER) {
5146 return FALSE(0);
5147 }
5148
5149 return get_speed_tradeoff_preference_for_file (file, show_text_in_icons);
5150}
5151
5152/**
5153 * caja_file_get_directory_item_count
5154 *
5155 * Get the number of items in a directory.
5156 * @file: CajaFile representing a directory.
5157 * @count: Place to put count.
5158 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
5159 * the item count from being read on this directory. Otherwise set to FALSE.
5160 *
5161 * Returns: TRUE if count is available.
5162 *
5163 **/
5164gboolean
5165caja_file_get_directory_item_count (CajaFile *file,
5166 guint *count,
5167 gboolean *count_unreadable)
5168{
5169 if (count != NULL((void*)0)) {
5170 *count = 0;
5171 }
5172 if (count_unreadable != NULL((void*)0)) {
5173 *count_unreadable = FALSE(0);
5174 }
5175
5176 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_240
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_240
= 1; else _g_boolean_var_240 = 0; _g_boolean_var_240; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
5177
5178 if (!caja_file_is_directory (file)) {
5179 return FALSE(0);
5180 }
5181
5182 if (!caja_file_should_show_directory_item_count (file)) {
5183 return FALSE(0);
5184 }
5185
5186 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5187 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
5188 get_item_count, (file, count, count_unreadable))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_item_count == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_item_count
) (file, count, count_unreadable))
;
5189}
5190
5191/**
5192 * caja_file_get_deep_counts
5193 *
5194 * Get the statistics about items inside a directory.
5195 * @file: CajaFile representing a directory or file.
5196 * @directory_count: Place to put count of directories inside.
5197 * @files_count: Place to put count of files inside.
5198 * @unreadable_directory_count: Number of directories encountered
5199 * that were unreadable.
5200 * @total_size: Total size of all files and directories visited.
5201 * @total_size_on_disk: Total size on disk of all files and directories visited.
5202 * @force: Whether the deep counts should even be collected if
5203 * caja_file_should_show_directory_item_count returns FALSE
5204 * for this file.
5205 *
5206 * Returns: Status to indicate whether sizes are available.
5207 *
5208 **/
5209CajaRequestStatus
5210caja_file_get_deep_counts (CajaFile *file,
5211 guint *directory_count,
5212 guint *file_count,
5213 guint *unreadable_directory_count,
5214 goffset *total_size,
5215 goffset *total_size_on_disk,
5216 gboolean force)
5217{
5218 if (directory_count != NULL((void*)0)) {
5219 *directory_count = 0;
5220 }
5221 if (file_count != NULL((void*)0)) {
5222 *file_count = 0;
5223 }
5224 if (unreadable_directory_count != NULL((void*)0)) {
5225 *unreadable_directory_count = 0;
5226 }
5227 if (total_size != NULL((void*)0)) {
5228 *total_size = 0;
5229 }
5230 if (total_size_on_disk != NULL((void*)0)) {
5231 *total_size_on_disk = 0;
5232 }
5233
5234 g_return_val_if_fail (CAJA_IS_FILE (file), CAJA_REQUEST_DONE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_241
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_241
= 1; else _g_boolean_var_241 = 0; _g_boolean_var_241; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (CAJA_REQUEST_DONE
); } } while (0)
;
5235
5236 if (!force && !caja_file_should_show_directory_item_count (file)) {
5237 /* Set field so an existing value isn't treated as up-to-date
5238 * when preference changes later.
5239 */
5240 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5241 return file->details->deep_counts_status;
5242 }
5243
5244 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5245 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5246 get_deep_counts, (file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5247 directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5248 file_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5249 unreadable_directory_count,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5250 total_size,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
5251 total_size_on_disk))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->get_deep_counts == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->get_deep_counts
) (file, directory_count, file_count, unreadable_directory_count
, total_size, total_size_on_disk))
;
5252}
5253
5254void
5255caja_file_recompute_deep_counts (CajaFile *file)
5256{
5257 if (file->details->deep_counts_status != CAJA_REQUEST_IN_PROGRESS) {
5258 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
5259 if (file->details->directory != NULL((void*)0)) {
5260 caja_directory_add_file_to_work_queue (file->details->directory, file);
5261 caja_directory_async_state_changed (file->details->directory);
5262 }
5263 }
5264}
5265
5266gboolean
5267caja_file_can_get_size (CajaFile *file)
5268{
5269 return file->details->size == -1;
5270}
5271
5272
5273/**
5274 * caja_file_get_size
5275 *
5276 * Get the file size.
5277 * @file: CajaFile representing the file in question.
5278 *
5279 * Returns: Size in bytes.
5280 *
5281 **/
5282goffset
5283caja_file_get_size (CajaFile *file)
5284{
5285 /* Before we have info on the file, we don't know the size. */
5286 if (file->details->size == -1)
5287 return 0;
5288 return file->details->size;
5289}
5290
5291/**
5292 * caja_file_get_size_on_disk
5293 *
5294 * Get the file size on disk (how many bytes is using on the filesystem).
5295 * e.g.: usually files with 1 byte will use a whole inode so it will return the
5296 * size of 1 inode. If the file is sparse the size on disk will be equal or less
5297 * than the size of the file.
5298 * @file: CajaFile representing the file in question.
5299 *
5300 * Returns: Size in bytes.
5301 *
5302 **/
5303goffset
5304caja_file_get_size_on_disk (CajaFile *file)
5305{
5306 /* Before we have info on the file, we don't know the size. */
5307 if (file->details->size_on_disk == -1)
5308 return 0;
5309 return file->details->size_on_disk;
5310}
5311
5312time_t
5313caja_file_get_mtime (CajaFile *file)
5314{
5315 return file->details->mtime;
5316}
5317
5318
5319static void
5320set_attributes_get_info_callback (GObject *source_object,
5321 GAsyncResult *res,
5322 gpointer callback_data)
5323{
5324 CajaFileOperation *op;
5325 GFileInfo *new_info;
5326 GError *error;
5327
5328 op = callback_data;
5329
5330 error = NULL((void*)0);
5331 new_info = g_file_query_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))), res, &error);
5332 if (new_info != NULL((void*)0)) {
5333 if (caja_file_update_info (op->file, new_info)) {
5334 caja_file_changed (op->file);
5335 }
5336 g_object_unref (new_info);
5337 }
5338 caja_file_operation_complete (op, NULL((void*)0), error);
5339 if (error) {
5340 g_error_free (error);
5341 }
5342}
5343
5344
5345static void
5346set_attributes_callback (GObject *source_object,
5347 GAsyncResult *result,
5348 gpointer callback_data)
5349{
5350 CajaFileOperation *op;
5351 GError *error;
5352 gboolean res;
5353
5354 op = callback_data;
5355
5356 error = NULL((void*)0);
5357 res = g_file_set_attributes_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5358 result,
5359 NULL((void*)0),
5360 &error);
5361
5362 if (res) {
5363 g_file_query_info_async (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
5364 CAJA_FILE_DEFAULT_ATTRIBUTES"standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*",
5365 0,
5366 G_PRIORITY_DEFAULT0,
5367 op->cancellable,
5368 set_attributes_get_info_callback, op);
5369 } else {
5370 caja_file_operation_complete (op, NULL((void*)0), error);
5371 g_error_free (error);
5372 }
5373}
5374
5375void
5376caja_file_set_attributes (CajaFile *file,
5377 GFileInfo *attributes,
5378 CajaFileOperationCallback callback,
5379 gpointer callback_data)
5380{
5381 CajaFileOperation *op;
5382 GFile *location;
5383
5384 op = caja_file_operation_new (file, callback, callback_data);
5385
5386 location = caja_file_get_location (file);
5387 g_file_set_attributes_async (location,
5388 attributes,
5389 0,
5390 G_PRIORITY_DEFAULT0,
5391 op->cancellable,
5392 set_attributes_callback,
5393 op);
5394 g_object_unref (location);
5395}
5396
5397
5398/**
5399 * caja_file_can_get_permissions:
5400 *
5401 * Check whether the permissions for a file are determinable.
5402 * This might not be the case for files on non-UNIX file systems.
5403 *
5404 * @file: The file in question.
5405 *
5406 * Return value: TRUE if the permissions are valid.
5407 */
5408gboolean
5409caja_file_can_get_permissions (CajaFile *file)
5410{
5411 return file->details->has_permissions;
5412}
5413
5414/**
5415 * caja_file_can_set_permissions:
5416 *
5417 * Check whether the current user is allowed to change
5418 * the permissions of a file.
5419 *
5420 * @file: The file in question.
5421 *
5422 * Return value: TRUE if the current user can change the
5423 * permissions of @file, FALSE otherwise. It's always possible
5424 * that when you actually try to do it, you will fail.
5425 */
5426gboolean
5427caja_file_can_set_permissions (CajaFile *file)
5428{
5429 uid_t user_id;
5430
5431 if (file->details->uid != -1 &&
5432 caja_file_is_local (file)) {
5433 /* Check the user. */
5434 user_id = geteuid();
5435
5436 /* Owner is allowed to set permissions. */
5437 if (user_id == (uid_t) file->details->uid) {
5438 return TRUE(!(0));
5439 }
5440
5441 /* Root is also allowed to set permissions. */
5442 if (user_id == 0) {
5443 return TRUE(!(0));
5444 }
5445
5446 /* Nobody else is allowed. */
5447 return FALSE(0);
5448 }
5449
5450 /* pretend to have full chmod rights when no info is available, relevant when
5451 * the FS can't provide ownership info, for instance for FTP */
5452 return TRUE(!(0));
5453}
5454
5455guint
5456caja_file_get_permissions (CajaFile *file)
5457{
5458 g_return_val_if_fail (caja_file_can_get_permissions (file), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_242
; if (caja_file_can_get_permissions (file)) _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__)), "caja_file_can_get_permissions (file)");
return (0); } } while (0)
;
5459
5460 return file->details->permissions;
5461}
5462
5463/**
5464 * caja_file_set_permissions:
5465 *
5466 * Change a file's permissions. This should only be called if
5467 * caja_file_can_set_permissions returned TRUE.
5468 *
5469 * @file: CajaFile representing the file in question.
5470 * @new_permissions: New permissions value. This is the whole
5471 * set of permissions, not a delta.
5472 **/
5473void
5474caja_file_set_permissions (CajaFile *file,
5475 guint32 new_permissions,
5476 CajaFileOperationCallback callback,
5477 gpointer callback_data)
5478{
5479 GFileInfo *info;
5480
5481 if (!caja_file_can_set_permissions (file)) {
5482 GError *error;
5483
5484 /* Claim that something changed even if the permission change failed.
5485 * This makes it easier for some clients who see the "reverting"
5486 * to the old permissions as "changing back".
5487 */
5488 caja_file_changed (file);
5489 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5490 _("Not allowed to set permissions")dcgettext (((void*)0), "Not allowed to set permissions", 5));
5491 (* callback) (file, NULL((void*)0), error, callback_data);
5492 g_error_free (error);
5493 return;
5494 }
5495
5496 /* Test the permissions-haven't-changed case explicitly
5497 * because we don't want to send the file-changed signal if
5498 * nothing changed.
5499 */
5500 if (new_permissions == file->details->permissions) {
5501 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5502 return;
5503 }
5504
5505 // Start UNDO-REDO
5506 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5507 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_SETPERMISSIONS, 1);
5508 caja_undostack_manager_data_set_file_permissions(undo_redo_data, caja_file_get_uri(file), file->details->permissions, new_permissions);
5509 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5510 undo_redo_data);
5511 }
5512 // End UNDO-REDO
5513
5514 info = g_file_info_new ();
5515 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode", new_permissions);
5516 caja_file_set_attributes (file, info, callback, callback_data);
5517 g_object_unref (info);
5518}
5519
5520/**
5521 * caja_file_can_get_selinux_context:
5522 *
5523 * Check whether the selinux context for a file are determinable.
5524 * This might not be the case for files on non-UNIX file systems,
5525 * files without a context or systems that don't support selinux.
5526 *
5527 * @file: The file in question.
5528 *
5529 * Return value: TRUE if the permissions are valid.
5530 */
5531gboolean
5532caja_file_can_get_selinux_context (CajaFile *file)
5533{
5534 return file->details->selinux_context != NULL((void*)0);
5535}
5536
5537
5538/**
5539 * caja_file_get_selinux_context:
5540 *
5541 * Get a user-displayable string representing a file's selinux
5542 * context
5543 * @file: CajaFile representing the file in question.
5544 *
5545 * Returns: Newly allocated string ready to display to the user.
5546 *
5547 **/
5548char *
5549caja_file_get_selinux_context (CajaFile *file)
5550{
5551 char *translated;
5552 char *raw;
5553
5554 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_243
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_243
= 1; else _g_boolean_var_243 = 0; _g_boolean_var_243; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
5555
5556 if (!caja_file_can_get_selinux_context (file)) {
5557 return NULL((void*)0);
5558 }
5559
5560 raw = file->details->selinux_context;
5561
5562#ifdef HAVE_SELINUX1
5563 if (selinux_raw_to_trans_context (raw, &translated) == 0) {
5564 char *tmp;
5565 tmp = g_strdup (translated)g_strdup_inline (translated);
5566 freecon (translated);
5567 translated = tmp;
5568 }
5569 else
5570#endif
5571 {
5572 translated = g_strdup (raw)g_strdup_inline (raw);
5573 }
5574
5575 return translated;
5576}
5577
5578static char *
5579get_real_name (const char *name, const char *gecos)
5580{
5581 char *locale_string, *part_before_comma, *capitalized_login_name, *real_name;
5582
5583 if (gecos == NULL((void*)0)) {
5584 return NULL((void*)0);
5585 }
5586
5587 locale_string = eel_str_strip_substring_and_after (gecos, ",");
5588 if (!g_utf8_validate (locale_string, -1, NULL((void*)0))) {
5589 part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5590 g_free (locale_string);
5591 } else {
5592 part_before_comma = locale_string;
5593 }
5594
5595 if (!g_utf8_validate (name, -1, NULL((void*)0))) {
5596 locale_string = g_locale_to_utf8 (name, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
5597 } else {
5598 locale_string = g_strdup (name)g_strdup_inline (name);
5599 }
5600
5601 capitalized_login_name = eel_str_capitalize (locale_string);
5602 g_free (locale_string);
5603
5604 if (capitalized_login_name == NULL((void*)0)) {
5605 real_name = part_before_comma;
5606 } else {
5607 real_name = eel_str_replace_substring
5608 (part_before_comma, "&", capitalized_login_name);
5609 g_free (part_before_comma);
5610 }
5611
5612
5613 if (eel_str_is_empty (real_name)
5614 || eel_strcmp (name, real_name) == 0
5615 || eel_strcmp (capitalized_login_name, real_name) == 0) {
5616 g_free (real_name);
5617 real_name = NULL((void*)0);
5618 }
5619
5620 g_free (capitalized_login_name);
5621
5622 return real_name;
5623}
5624
5625static gboolean
5626get_group_id_from_group_name (const char *group_name, uid_t *gid)
5627{
5628 struct group *group;
5629
5630 g_assert (gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if (gid != ((void*)0)) _g_boolean_var_244 = 1; else _g_boolean_var_244
= 0; _g_boolean_var_244; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5630, ((const char*) (__func__
)), "gid != NULL"); } while (0)
;
5631
5632 group = getgrnam (group_name);
5633
5634 if (group == NULL((void*)0)) {
5635 return FALSE(0);
5636 }
5637
5638 *gid = group->gr_gid;
5639
5640 return TRUE(!(0));
5641}
5642
5643static gboolean
5644get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid)
5645{
5646 struct passwd *password_info;
5647
5648 g_assert (uid != NULL || gid != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_245
; if (uid != ((void*)0) || gid != ((void*)0)) _g_boolean_var_245
= 1; else _g_boolean_var_245 = 0; _g_boolean_var_245; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 5648, ((const char*) (__func__)), "uid != NULL || gid != NULL"
); } while (0)
;
5649
5650 password_info = getpwnam (user_name);
5651
5652 if (password_info == NULL((void*)0)) {
5653 return FALSE(0);
5654 }
5655
5656 if (uid != NULL((void*)0)) {
5657 *uid = password_info->pw_uid;
5658 }
5659
5660 if (gid != NULL((void*)0)) {
5661 *gid = password_info->pw_gid;
5662 }
5663
5664 return TRUE(!(0));
5665}
5666
5667static gboolean
5668get_user_id_from_user_name (const char *user_name, uid_t *id)
5669{
5670 return get_ids_from_user_name (user_name, id, NULL((void*)0));
5671}
5672
5673static gboolean
5674get_id_from_digit_string (const char *digit_string, uid_t *id)
5675{
5676 long scanned_id;
5677 char c;
5678
5679 g_assert (id != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_246
; if (id != ((void*)0)) _g_boolean_var_246 = 1; else _g_boolean_var_246
= 0; _g_boolean_var_246; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 5679, ((const char*) (__func__
)), "id != NULL"); } while (0)
;
5680
5681 /* Only accept string if it has one integer with nothing
5682 * afterwards.
5683 */
5684 if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) {
5685 return FALSE(0);
5686 }
5687 *id = scanned_id;
5688 return TRUE(!(0));
5689}
5690
5691/**
5692 * caja_file_can_get_owner:
5693 *
5694 * Check whether the owner a file is determinable.
5695 * This might not be the case for files on non-UNIX file systems.
5696 *
5697 * @file: The file in question.
5698 *
5699 * Return value: TRUE if the owner is valid.
5700 */
5701gboolean
5702caja_file_can_get_owner (CajaFile *file)
5703{
5704 /* Before we have info on a file, the owner is unknown. */
5705 return file->details->uid != -1;
5706}
5707
5708/**
5709 * caja_file_get_owner_name:
5710 *
5711 * Get the user name of the file's owner. If the owner has no
5712 * name, returns the userid as a string. The caller is responsible
5713 * for g_free-ing this string.
5714 *
5715 * @file: The file in question.
5716 *
5717 * Return value: A newly-allocated string.
5718 */
5719char *
5720caja_file_get_owner_name (CajaFile *file)
5721{
5722 return caja_file_get_owner_as_string (file, FALSE(0));
5723}
5724
5725/**
5726 * caja_file_can_set_owner:
5727 *
5728 * Check whether the current user is allowed to change
5729 * the owner of a file.
5730 *
5731 * @file: The file in question.
5732 *
5733 * Return value: TRUE if the current user can change the
5734 * owner of @file, FALSE otherwise. It's always possible
5735 * that when you actually try to do it, you will fail.
5736 */
5737gboolean
5738caja_file_can_set_owner (CajaFile *file)
5739{
5740 /* Not allowed to set the owner if we can't
5741 * even read it. This can happen on non-UNIX file
5742 * systems.
5743 */
5744 if (!caja_file_can_get_owner (file)) {
5745 return FALSE(0);
5746 }
5747
5748 /* Only root is also allowed to set the owner. */
5749 return geteuid() == 0;
5750}
5751
5752/**
5753 * caja_file_set_owner:
5754 *
5755 * Set the owner of a file. This will only have any effect if
5756 * caja_file_can_set_owner returns TRUE.
5757 *
5758 * @file: The file in question.
5759 * @user_name_or_id: The user name to set the owner to.
5760 * If the string does not match any user name, and the
5761 * string is an integer, the owner will be set to the
5762 * userid represented by that integer.
5763 * @callback: Function called when asynch owner change succeeds or fails.
5764 * @callback_data: Parameter passed back with callback function.
5765 */
5766void
5767caja_file_set_owner (CajaFile *file,
5768 const char *user_name_or_id,
5769 CajaFileOperationCallback callback,
5770 gpointer callback_data)
5771{
5772 GError *error;
5773 GFileInfo *info;
5774 uid_t new_id;
5775
5776 if (!caja_file_can_set_owner (file)) {
5777 /* Claim that something changed even if the permission
5778 * change failed. This makes it easier for some
5779 * clients who see the "reverting" to the old owner as
5780 * "changing back".
5781 */
5782 caja_file_changed (file);
5783 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
5784 _("Not allowed to set owner")dcgettext (((void*)0), "Not allowed to set owner", 5));
5785 (* callback) (file, NULL((void*)0), error, callback_data);
5786 g_error_free (error);
5787 return;
5788 }
5789
5790 /* If no match treating user_name_or_id as name, try treating
5791 * it as id.
5792 */
5793 if (!get_user_id_from_user_name (user_name_or_id, &new_id)
5794 && !get_id_from_digit_string (user_name_or_id, &new_id)) {
5795 /* Claim that something changed even if the permission
5796 * change failed. This makes it easier for some
5797 * clients who see the "reverting" to the old owner as
5798 * "changing back".
5799 */
5800 caja_file_changed (file);
5801 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
5802 _("Specified owner '%s' doesn't exist")dcgettext (((void*)0), "Specified owner '%s' doesn't exist", 5
)
, user_name_or_id);
5803 (* callback) (file, NULL((void*)0), error, callback_data);
5804 g_error_free (error);
5805 return;
5806 }
5807
5808 /* Test the owner-hasn't-changed case explicitly because we
5809 * don't want to send the file-changed signal if nothing
5810 * changed.
5811 */
5812 if (new_id == (uid_t) file->details->uid) {
5813 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
5814 return;
5815 }
5816
5817 // Start UNDO-REDO
5818 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5819 char* current_owner = caja_file_get_owner_as_string (file, FALSE(0));
5820 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEOWNER, 1);
5821 caja_undostack_manager_data_set_owner_change_information(undo_redo_data, caja_file_get_uri(file), current_owner, user_name_or_id);
5822 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
5823 undo_redo_data);
5824 g_free(current_owner);
5825 }
5826 // End UNDO-REDO
5827
5828 info = g_file_info_new ();
5829 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID"unix::uid", new_id);
5830 caja_file_set_attributes (file, info, callback, callback_data);
5831 g_object_unref (info);
5832}
5833
5834/**
5835 * caja_get_user_names:
5836 *
5837 * Get a list of user names. For users with a different associated
5838 * "real name", the real name follows the standard user name, separated
5839 * by a carriage return. The caller is responsible for freeing this list
5840 * and its contents.
5841 */
5842GList *
5843caja_get_user_names (void)
5844{
5845 GList *list;
5846 char *name;
5847 struct passwd *user;
5848
5849 list = NULL((void*)0);
5850
5851 setpwent ();
5852
5853 while ((user = getpwent ()) != NULL((void*)0)) {
5854 char *real_name;
5855
5856 real_name = get_real_name (user->pw_name, user->pw_gecos);
5857 if (real_name != NULL((void*)0)) {
5858 name = g_strconcat (user->pw_name, "\n", real_name, NULL((void*)0));
5859 } else {
5860 name = g_strdup (user->pw_name)g_strdup_inline (user->pw_name);
5861 }
5862 g_free (real_name);
5863 list = g_list_prepend (list, name);
5864 }
5865
5866 endpwent ();
5867
5868 return eel_g_str_list_alphabetize (list);
5869}
5870
5871/**
5872 * caja_file_can_get_group:
5873 *
5874 * Check whether the group a file is determinable.
5875 * This might not be the case for files on non-UNIX file systems.
5876 *
5877 * @file: The file in question.
5878 *
5879 * Return value: TRUE if the group is valid.
5880 */
5881gboolean
5882caja_file_can_get_group (CajaFile *file)
5883{
5884 /* Before we have info on a file, the group is unknown. */
5885 return file->details->gid != -1;
5886}
5887
5888/**
5889 * caja_file_get_group_name:
5890 *
5891 * Get the name of the file's group. If the group has no
5892 * name, returns the groupid as a string. The caller is responsible
5893 * for g_free-ing this string.
5894 *
5895 * @file: The file in question.
5896 *
5897 * Return value: A newly-allocated string.
5898 **/
5899char *
5900caja_file_get_group_name (CajaFile *file)
5901{
5902 return g_strdup (file->details->group)g_strdup_inline (file->details->group);
5903}
5904
5905/**
5906 * caja_file_can_set_group:
5907 *
5908 * Check whether the current user is allowed to change
5909 * the group of a file.
5910 *
5911 * @file: The file in question.
5912 *
5913 * Return value: TRUE if the current user can change the
5914 * group of @file, FALSE otherwise. It's always possible
5915 * that when you actually try to do it, you will fail.
5916 */
5917gboolean
5918caja_file_can_set_group (CajaFile *file)
5919{
5920 uid_t user_id;
5921
5922 /* Not allowed to set the permissions if we can't
5923 * even read them. This can happen on non-UNIX file
5924 * systems.
5925 */
5926 if (!caja_file_can_get_group (file)) {
5927 return FALSE(0);
5928 }
5929
5930 /* Check the user. */
5931 user_id = geteuid();
5932
5933 /* Owner is allowed to set group (with restrictions). */
5934 if (user_id == (uid_t) file->details->uid) {
5935 return TRUE(!(0));
5936 }
5937
5938 /* Root is also allowed to set group. */
5939 if (user_id == 0) {
5940 return TRUE(!(0));
5941 }
5942
5943 /* Nobody else is allowed. */
5944 return FALSE(0);
5945}
5946
5947/* Get a list of group names, filtered to only the ones
5948 * that contain the given username. If the username is
5949 * NULL, returns a list of all group names.
5950 */
5951static GList *
5952caja_get_group_names_for_user (void)
5953{
5954 GList *list;
5955 int count, i;
5956 gid_t gid_list[NGROUPS_MAX65536 + 1];
5957 struct group *group = NULL((void*)0);
5958
5959
5960 list = NULL((void*)0);
5961
5962 count = getgroups (NGROUPS_MAX65536 + 1, gid_list);
5963 for (i = 0; i < count; i++) {
5964 group = getgrgid (gid_list[i]);
5965 if (group == NULL((void*)0))
5966 break;
5967
5968 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5969 }
5970
5971 return eel_g_str_list_alphabetize (list);
5972}
5973
5974/**
5975 * caja_get_group_names:
5976 *
5977 * Get a list of all group names.
5978 */
5979GList *
5980caja_get_all_group_names (void)
5981{
5982 GList *list;
5983 struct group *group;
5984
5985 list = NULL((void*)0);
5986
5987 setgrent ();
5988
5989 while ((group = getgrent ()) != NULL((void*)0))
5990 list = g_list_prepend (list, g_strdup (group->gr_name)g_strdup_inline (group->gr_name));
5991
5992 endgrent ();
5993
5994 return eel_g_str_list_alphabetize (list);
5995}
5996
5997/**
5998 * caja_file_get_settable_group_names:
5999 *
6000 * Get a list of all group names that the current user
6001 * can set the group of a specific file to.
6002 *
6003 * @file: The CajaFile in question.
6004 */
6005GList *
6006caja_file_get_settable_group_names (CajaFile *file)
6007{
6008 uid_t user_id;
6009 GList *result;
6010
6011 if (!caja_file_can_set_group (file)) {
6012 return NULL((void*)0);
6013 }
6014
6015 /* Check the user. */
6016 user_id = geteuid();
6017
6018 if (user_id == 0) {
6019 /* Root is allowed to set group to anything. */
6020 result = caja_get_all_group_names ();
6021 } else if (user_id == (uid_t) file->details->uid) {
6022 /* Owner is allowed to set group to any that owner is member of. */
6023 result = caja_get_group_names_for_user ();
6024 } else {
6025 g_warning ("unhandled case in caja_get_settable_group_names");
6026 result = NULL((void*)0);
6027 }
6028
6029 return result;
6030}
6031
6032/**
6033 * caja_file_set_group:
6034 *
6035 * Set the group of a file. This will only have any effect if
6036 * caja_file_can_set_group returns TRUE.
6037 *
6038 * @file: The file in question.
6039 * @group_name_or_id: The group name to set the owner to.
6040 * If the string does not match any group name, and the
6041 * string is an integer, the group will be set to the
6042 * group id represented by that integer.
6043 * @callback: Function called when asynch group change succeeds or fails.
6044 * @callback_data: Parameter passed back with callback function.
6045 */
6046void
6047caja_file_set_group (CajaFile *file,
6048 const char *group_name_or_id,
6049 CajaFileOperationCallback callback,
6050 gpointer callback_data)
6051{
6052 GError *error;
6053 GFileInfo *info;
6054 uid_t new_id;
6055
6056 if (!caja_file_can_set_group (file)) {
6057 /* Claim that something changed even if the group
6058 * change failed. This makes it easier for some
6059 * clients who see the "reverting" to the old group as
6060 * "changing back".
6061 */
6062 caja_file_changed (file);
6063 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_PERMISSION_DENIED,
6064 _("Not allowed to set group")dcgettext (((void*)0), "Not allowed to set group", 5));
6065 (* callback) (file, NULL((void*)0), error, callback_data);
6066 g_error_free (error);
6067 return;
6068 }
6069
6070 /* If no match treating group_name_or_id as name, try treating
6071 * it as id.
6072 */
6073 if (!get_group_id_from_group_name (group_name_or_id, &new_id)
6074 && !get_id_from_digit_string (group_name_or_id, &new_id)) {
6075 /* Claim that something changed even if the group
6076 * change failed. This makes it easier for some
6077 * clients who see the "reverting" to the old group as
6078 * "changing back".
6079 */
6080 caja_file_changed (file);
6081 error = g_error_new (G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_ARGUMENT,
6082 _("Specified group '%s' doesn't exist")dcgettext (((void*)0), "Specified group '%s' doesn't exist", 5
)
, group_name_or_id);
6083 (* callback) (file, NULL((void*)0), error, callback_data);
6084 g_error_free (error);
6085 return;
6086 }
6087
6088 if (new_id == (gid_t) file->details->gid) {
6089 (* callback) (file, NULL((void*)0), NULL((void*)0), callback_data);
6090 return;
6091 }
6092
6093 // Start UNDO-REDO
6094 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6095 char* current_group = caja_file_get_group_name (file);
6096 CajaUndoStackActionData* undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CHANGEGROUP, 1);
6097 caja_undostack_manager_data_set_group_change_information(undo_redo_data, caja_file_get_uri(file), current_group, group_name_or_id);
6098 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
6099 undo_redo_data);
6100 g_free(current_group);
6101 }
6102 // End UNDO-REDO
6103
6104 info = g_file_info_new ();
6105 g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID"unix::gid", new_id);
6106 caja_file_set_attributes (file, info, callback, callback_data);
6107 g_object_unref (info);
6108}
6109
6110/**
6111 * caja_file_get_octal_permissions_as_string:
6112 *
6113 * Get a user-displayable string representing a file's permissions
6114 * as an octal number. The caller
6115 * is responsible for g_free-ing this string.
6116 * @file: CajaFile representing the file in question.
6117 *
6118 * Returns: Newly allocated string ready to display to the user.
6119 *
6120 **/
6121static char *
6122caja_file_get_octal_permissions_as_string (CajaFile *file)
6123{
6124 guint32 permissions;
6125
6126 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_247
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_247
= 1; else _g_boolean_var_247 = 0; _g_boolean_var_247; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6126, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6127
6128 if (!caja_file_can_get_permissions (file)) {
6129 return NULL((void*)0);
6130 }
6131
6132 permissions = file->details->permissions;
6133 return g_strdup_printf ("%03o", permissions);
6134}
6135
6136/**
6137 * caja_file_get_permissions_as_string:
6138 *
6139 * Get a user-displayable string representing a file's permissions. The caller
6140 * is responsible for g_free-ing this string.
6141 * @file: CajaFile representing the file in question.
6142 *
6143 * Returns: Newly allocated string ready to display to the user.
6144 *
6145 **/
6146static char *
6147caja_file_get_permissions_as_string (CajaFile *file)
6148{
6149 guint32 permissions;
6150 gboolean is_directory;
6151 gboolean is_link;
6152 gboolean suid, sgid, sticky;
6153
6154 if (!caja_file_can_get_permissions (file)) {
6155 return NULL((void*)0);
6156 }
6157
6158 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_248
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_248
= 1; else _g_boolean_var_248 = 0; _g_boolean_var_248; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6158, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6159
6160 permissions = file->details->permissions;
6161 is_directory = caja_file_is_directory (file);
6162 is_link = caja_file_is_symbolic_link (file);
6163
6164 /* We use ls conventions for displaying these three obscure flags */
6165 suid = permissions & S_ISUID04000;
6166 sgid = permissions & S_ISGID02000;
6167 sticky = permissions & S_ISVTX01000;
6168
6169 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
6170 is_link ? 'l' : is_directory ? 'd' : '-',
6171 permissions & S_IRUSR0400 ? 'r' : '-',
6172 permissions & S_IWUSR0200 ? 'w' : '-',
6173 permissions & S_IXUSR0100
6174 ? (suid ? 's' : 'x')
6175 : (suid ? 'S' : '-'),
6176 permissions & S_IRGRP(0400 >> 3) ? 'r' : '-',
6177 permissions & S_IWGRP(0200 >> 3) ? 'w' : '-',
6178 permissions & S_IXGRP(0100 >> 3)
6179 ? (sgid ? 's' : 'x')
6180 : (sgid ? 'S' : '-'),
6181 permissions & S_IROTH((0400 >> 3) >> 3) ? 'r' : '-',
6182 permissions & S_IWOTH((0200 >> 3) >> 3) ? 'w' : '-',
6183 permissions & S_IXOTH((0100 >> 3) >> 3)
6184 ? (sticky ? 't' : 'x')
6185 : (sticky ? 'T' : '-'));
6186}
6187
6188/**
6189 * caja_file_get_owner_as_string:
6190 *
6191 * Get a user-displayable string representing a file's owner. The caller
6192 * is responsible for g_free-ing this string.
6193 * @file: CajaFile representing the file in question.
6194 * @include_real_name: Whether or not to append the real name (if any)
6195 * for this user after the user name.
6196 *
6197 * Returns: Newly allocated string ready to display to the user.
6198 *
6199 **/
6200static char *
6201caja_file_get_owner_as_string (CajaFile *file, gboolean include_real_name)
6202{
6203 char *user_name;
6204
6205 /* Before we have info on a file, the owner is unknown. */
6206 if (file->details->owner == NULL((void*)0) &&
6207 file->details->owner_real == NULL((void*)0)) {
6208 return NULL((void*)0);
6209 }
6210
6211 if (file->details->owner_real == NULL((void*)0)) {
6212 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6213 } else if (file->details->owner == NULL((void*)0)) {
6214 user_name = g_strdup (file->details->owner_real)g_strdup_inline (file->details->owner_real);
6215 } else if (include_real_name &&
6216 strcmp (file->details->owner, file->details->owner_real) != 0) {
6217 user_name = g_strdup_printf ("%s - %s",
6218 file->details->owner,
6219 file->details->owner_real);
6220 } else {
6221 user_name = g_strdup (file->details->owner)g_strdup_inline (file->details->owner);
6222 }
6223
6224 return user_name;
6225}
6226
6227static char *
6228format_item_count_for_display (guint item_count,
6229 gboolean includes_directories,
6230 gboolean includes_files)
6231{
6232 g_assert (includes_directories || includes_files)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_249
; if (includes_directories || includes_files) _g_boolean_var_249
= 1; else _g_boolean_var_249 = 0; _g_boolean_var_249; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6232, ((const char*) (__func__)), "includes_directories || includes_files"
); } while (0)
;
6233
6234 return g_strdup_printf (includes_directories
6235 ? (includes_files
6236 ? ngettext ("%'u item", "%'u items", item_count)dcngettext (((void*)0), "%'u item", "%'u items", item_count, 5
)
6237 : ngettext ("%'u folder", "%'u folders", item_count)dcngettext (((void*)0), "%'u folder", "%'u folders", item_count
, 5)
)
6238 : ngettext ("%'u file", "%'u files", item_count)dcngettext (((void*)0), "%'u file", "%'u files", item_count, 5
)
, item_count);
6239}
6240
6241/**
6242 * caja_file_get_size_as_string:
6243 *
6244 * Get a user-displayable string representing a file size. The caller
6245 * is responsible for g_free-ing this string. The string is an item
6246 * count for directories.
6247 * @file: CajaFile representing the file in question.
6248 * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
6249 *
6250 * Returns: Newly allocated string ready to display to the user.
6251 *
6252 **/
6253static char *
6254caja_file_get_size_as_string (CajaFile *file,
6255 gboolean size_on_disk)
6256{
6257 guint item_count;
6258 gboolean count_unreadable;
6259 goffset size;
6260
6261 if (file == NULL((void*)0)) {
6262 return NULL((void*)0);
6263 }
6264
6265 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_250
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_250
= 1; else _g_boolean_var_250 = 0; _g_boolean_var_250; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6265, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6266
6267 if (caja_file_is_directory (file)) {
6268 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6269 return NULL((void*)0);
6270 }
6271 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6272 }
6273
6274 if (size_on_disk) {
6275 size = file->details->size_on_disk;
6276 } else {
6277 size = file->details->size;
6278 }
6279
6280 if (size == -1) {
6281 return NULL((void*)0);
6282 }
6283
6284 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6285 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6286 else
6287 return g_format_size (size);
6288}
6289
6290/**
6291 * caja_file_get_size_as_string_with_real_size:
6292 *
6293 * Get a user-displayable string representing a file size. The caller
6294 * is responsible for g_free-ing this string. The string is an item
6295 * count for directories.
6296 * This function adds the real size in the string.
6297 * @file: CajaFile representing the file in question.
6298 *
6299 * Returns: Newly allocated string ready to display to the user.
6300 *
6301 **/
6302static char *
6303caja_file_get_size_as_string_with_real_size (CajaFile *file,
6304 gboolean size_on_disk)
6305{
6306 guint item_count;
6307 gboolean count_unreadable;
6308 goffset size;
6309 char * formatted;
6310 char * formatted_plus_real;
6311 char * real_size;
6312
6313 if (file == NULL((void*)0)) {
6314 return NULL((void*)0);
6315 }
6316
6317 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_251
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_251
= 1; else _g_boolean_var_251 = 0; _g_boolean_var_251; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6317, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6318
6319 if (caja_file_is_directory (file)) {
6320 if (!caja_file_get_directory_item_count (file, &item_count, &count_unreadable)) {
6321 return NULL((void*)0);
6322 }
6323 return format_item_count_for_display (item_count, TRUE(!(0)), TRUE(!(0)));
6324 }
6325
6326 if (size_on_disk) {
6327 size = file->details->size_on_disk;
6328 } else {
6329 size = file->details->size;
6330 }
6331
6332 if (size == -1) {
6333 return NULL((void*)0);
6334 }
6335
6336 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6337 formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
6338 else
6339 formatted = g_format_size(size);
6340
6341 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
6342 real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT)dcgettext (((void*)0), "%""lu", 5), (guint64) size);
6343 formatted_plus_real = g_strdup_printf (_("%s (%s bytes)")dcgettext (((void*)0), "%s (%s bytes)", 5), formatted, real_size);
6344 g_free (real_size);
6345 g_free (formatted);
6346 return formatted_plus_real;
6347}
6348
6349static char *
6350caja_file_get_deep_count_as_string_internal (CajaFile *file,
6351 gboolean report_size,
6352 gboolean report_size_on_disk,
6353 gboolean report_directory_count,
6354 gboolean report_file_count)
6355{
6356 CajaRequestStatus status;
6357 guint directory_count;
6358 guint file_count;
6359 guint unreadable_count;
6360 guint total_count;
6361 goffset total_size;
6362 goffset total_size_on_disk;
6363
6364 /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
6365 g_assert (!(report_size && report_size_on_disk))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_252
; if (!(report_size && report_size_on_disk)) _g_boolean_var_252
= 1; else _g_boolean_var_252 = 0; _g_boolean_var_252; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6365, ((const char*) (__func__)), "!(report_size && report_size_on_disk)"
); } while (0)
;
6366 g_assert (!(report_size && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_253
; if (!(report_size && (report_directory_count || report_file_count
))) _g_boolean_var_253 = 1; else _g_boolean_var_253 = 0; _g_boolean_var_253
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6366, ((const char*) (__func__)), "!(report_size && (report_directory_count || report_file_count))"
); } while (0)
;
6367 g_assert (!(report_size_on_disk && (report_directory_count || report_file_count)))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_254
; if (!(report_size_on_disk && (report_directory_count
|| report_file_count))) _g_boolean_var_254 = 1; else _g_boolean_var_254
= 0; _g_boolean_var_254; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6367, ((const char*) (__func__
)), "!(report_size_on_disk && (report_directory_count || report_file_count))"
); } while (0)
;
6368
6369 /* Must ask for something */
6370 g_assert (report_size || report_size_on_disk || report_directory_count || report_file_count)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_255
; if (report_size || report_size_on_disk || report_directory_count
|| report_file_count) _g_boolean_var_255 = 1; else _g_boolean_var_255
= 0; _g_boolean_var_255; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6370, ((const char*) (__func__
)), "report_size || report_size_on_disk || report_directory_count || report_file_count"
); } while (0)
;
6371
6372 if (file == NULL((void*)0)) {
6373 return NULL((void*)0);
6374 }
6375
6376 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_256
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_256
= 1; else _g_boolean_var_256 = 0; _g_boolean_var_256; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6376, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6377 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_257
; if (caja_file_is_directory (file)) _g_boolean_var_257 = 1; else
_g_boolean_var_257 = 0; _g_boolean_var_257; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 6377, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
6378
6379 status = caja_file_get_deep_counts (file,
6380 &directory_count,
6381 &file_count,
6382 &unreadable_count,
6383 &total_size,
6384 &total_size_on_disk,
6385 FALSE(0));
6386
6387 /* Check whether any info is available. */
6388 if (status == CAJA_REQUEST_NOT_STARTED) {
6389 return NULL((void*)0);
6390 }
6391
6392 total_count = file_count + directory_count;
6393
6394 if (total_count == 0) {
6395 switch (status) {
6396 case CAJA_REQUEST_IN_PROGRESS:
6397 /* Don't return confident "zero" until we're finished looking,
6398 * because of next case.
6399 */
6400 return NULL((void*)0);
6401 case CAJA_REQUEST_DONE:
6402 /* Don't return "zero" if we there were contents but we couldn't read them. */
6403 if (unreadable_count != 0) {
6404 return NULL((void*)0);
6405 }
6406 default: break;
6407 }
6408 }
6409
6410 /* Note that we don't distinguish the "everything was readable" case
6411 * from the "some things but not everything was readable" case here.
6412 * Callers can distinguish them using caja_file_get_deep_counts
6413 * directly if desired.
6414 */
6415 if (report_size)
6416 {
6417 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6418 return g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
6419 else
6420 return g_format_size(total_size);
6421 }
6422
6423 if (report_size_on_disk)
6424 {
6425 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
6426 return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
6427 else
6428 return g_format_size (total_size_on_disk);
6429 }
6430
6431 return format_item_count_for_display (report_directory_count
6432 ? (report_file_count ? total_count : directory_count)
6433 : file_count,
6434 report_directory_count, report_file_count);
6435}
6436
6437/**
6438 * caja_file_get_deep_size_as_string:
6439 *
6440 * Get a user-displayable string representing the size of all contained
6441 * items (only makes sense for directories). The caller
6442 * is responsible for g_free-ing this string.
6443 * @file: CajaFile representing the file in question.
6444 * @size_on_disk: if TRUE will return the size on disk, else return size of file.
6445 *
6446 * Returns: Newly allocated string ready to display to the user.
6447 *
6448 **/
6449static char *
6450caja_file_get_deep_size_as_string (CajaFile *file, gboolean size_on_disk)
6451{
6452 if (size_on_disk) {
6453 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), TRUE(!(0)), FALSE(0), FALSE(0));
6454 } else {
6455 return caja_file_get_deep_count_as_string_internal (file, TRUE(!(0)), FALSE(0), FALSE(0), FALSE(0));
6456 }
6457}
6458
6459/**
6460 * caja_file_get_deep_total_count_as_string:
6461 *
6462 * Get a user-displayable string representing the count of all contained
6463 * items (only makes sense for directories). The caller
6464 * is responsible for g_free-ing this string.
6465 * @file: CajaFile representing the file in question.
6466 *
6467 * Returns: Newly allocated string ready to display to the user.
6468 *
6469 **/
6470static char *
6471caja_file_get_deep_total_count_as_string (CajaFile *file)
6472{
6473 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), TRUE(!(0)));
6474}
6475
6476/**
6477 * caja_file_get_deep_file_count_as_string:
6478 *
6479 * Get a user-displayable string representing the count of all contained
6480 * items, not including directories. It only makes sense to call this
6481 * function on a directory. The caller
6482 * is responsible for g_free-ing this string.
6483 * @file: CajaFile representing the file in question.
6484 *
6485 * Returns: Newly allocated string ready to display to the user.
6486 *
6487 **/
6488static char *
6489caja_file_get_deep_file_count_as_string (CajaFile *file)
6490{
6491 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), FALSE(0), TRUE(!(0)));
6492}
6493
6494/**
6495 * caja_file_get_deep_directory_count_as_string:
6496 *
6497 * Get a user-displayable string representing the count of all contained
6498 * directories. It only makes sense to call this
6499 * function on a directory. The caller
6500 * is responsible for g_free-ing this string.
6501 * @file: CajaFile representing the file in question.
6502 *
6503 * Returns: Newly allocated string ready to display to the user.
6504 *
6505 **/
6506static char *
6507caja_file_get_deep_directory_count_as_string (CajaFile *file)
6508{
6509 return caja_file_get_deep_count_as_string_internal (file, FALSE(0), FALSE(0), TRUE(!(0)), FALSE(0));
6510}
6511
6512/**
6513 * caja_file_get_string_attribute:
6514 *
6515 * Get a user-displayable string from a named attribute. Use g_free to
6516 * free this string. If the value is unknown, returns NULL. You can call
6517 * caja_file_get_string_attribute_with_default if you want a non-NULL
6518 * default.
6519 *
6520 * @file: CajaFile representing the file in question.
6521 * @attribute_name: The name of the desired attribute. The currently supported
6522 * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
6523 * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
6524 * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
6525 * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
6526 *
6527 * Returns: Newly allocated string ready to display to the user, or NULL
6528 * if the value is unknown or @attribute_name is not supported.
6529 *
6530 **/
6531char *
6532caja_file_get_string_attribute_q (CajaFile *file, GQuark attribute_q)
6533{
6534 char *extension_attribute;
6535
6536 if (attribute_q == attribute_name_q) {
6537 return caja_file_get_display_name (file);
6538 }
6539 if (attribute_q == attribute_type_q) {
6540 return caja_file_get_type_as_string (file);
6541 }
6542 if (attribute_q == attribute_mime_type_q) {
6543 return caja_file_get_mime_type (file);
6544 }
6545 if (attribute_q == attribute_size_q) {
6546 return caja_file_get_size_as_string (file, FALSE(0));
6547 }
6548 if (attribute_q == attribute_size_on_disk_q) {
6549 return caja_file_get_size_as_string (file, TRUE(!(0)));
6550 }
6551 if (attribute_q == attribute_size_detail_q) {
6552 return caja_file_get_size_as_string_with_real_size (file, FALSE(0));
6553 }
6554 if (attribute_q == attribute_size_on_disk_detail_q) {
6555 return caja_file_get_size_as_string_with_real_size (file, TRUE(!(0)));
6556 }
6557 if (attribute_q == attribute_deep_size_q) {
6558 return caja_file_get_deep_size_as_string (file, FALSE(0));
6559 }
6560 if (attribute_q == attribute_deep_size_on_disk_q) {
6561 return caja_file_get_deep_size_as_string (file, TRUE(!(0)));
6562 }
6563 if (attribute_q == attribute_deep_file_count_q) {
6564 return caja_file_get_deep_file_count_as_string (file);
6565 }
6566 if (attribute_q == attribute_deep_directory_count_q) {
6567 return caja_file_get_deep_directory_count_as_string (file);
6568 }
6569 if (attribute_q == attribute_deep_total_count_q) {
6570 return caja_file_get_deep_total_count_as_string (file);
6571 }
6572 if (attribute_q == attribute_trash_orig_path_q) {
6573 return caja_file_get_trash_original_file_parent_as_string (file);
6574 }
6575 if (attribute_q == attribute_date_modified_q) {
6576 return caja_file_get_date_as_string (file,
6577 CAJA_DATE_TYPE_MODIFIED);
6578 }
6579 if (attribute_q == attribute_date_changed_q) {
6580 return caja_file_get_date_as_string (file,
6581 CAJA_DATE_TYPE_CHANGED);
6582 }
6583 if (attribute_q == attribute_date_accessed_q) {
6584 return caja_file_get_date_as_string (file,
6585 CAJA_DATE_TYPE_ACCESSED);
6586 }
6587 if (attribute_q == attribute_date_created_q) {
6588 return caja_file_get_date_as_string (file,
6589 CAJA_DATE_TYPE_CREATED);
6590 }
6591 if (attribute_q == attribute_trashed_on_q) {
6592 return caja_file_get_date_as_string (file,
6593 CAJA_DATE_TYPE_TRASHED);
6594 }
6595 if (attribute_q == attribute_date_permissions_q) {
6596 return caja_file_get_date_as_string (file,
6597 CAJA_DATE_TYPE_PERMISSIONS_CHANGED);
6598 }
6599 if (attribute_q == attribute_extension_q) {
6600 return caja_file_get_extension_as_string (file);
6601 }
6602 if (attribute_q == attribute_permissions_q) {
6603 return caja_file_get_permissions_as_string (file);
6604 }
6605 if (attribute_q == attribute_selinux_context_q) {
6606 return caja_file_get_selinux_context (file);
6607 }
6608 if (attribute_q == attribute_octal_permissions_q) {
6609 return caja_file_get_octal_permissions_as_string (file);
6610 }
6611 if (attribute_q == attribute_owner_q) {
6612 return caja_file_get_owner_as_string (file, TRUE(!(0)));
6613 }
6614 if (attribute_q == attribute_group_q) {
6615 return caja_file_get_group_name (file);
6616 }
6617 if (attribute_q == attribute_uri_q) {
6618 return caja_file_get_uri (file);
6619 }
6620 if (attribute_q == attribute_where_q) {
6621 return caja_file_get_where_string (file);
6622 }
6623 if (attribute_q == attribute_link_target_q) {
6624 return caja_file_get_symbolic_link_target_path (file);
6625 }
6626 if (attribute_q == attribute_volume_q) {
6627 return caja_file_get_volume_name (file);
6628 }
6629 if (attribute_q == attribute_free_space_q) {
6630 return caja_file_get_volume_free_space (file);
6631 }
6632
6633 extension_attribute = NULL((void*)0);
6634
6635 if (file->details->pending_extension_attributes) {
6636 extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes,
6637 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6638 }
6639
6640 if (extension_attribute == NULL((void*)0) && file->details->extension_attributes) {
6641 extension_attribute = g_hash_table_lookup (file->details->extension_attributes,
6642 GINT_TO_POINTER (attribute_q)((gpointer) (glong) (attribute_q)));
6643 }
6644
6645 return g_strdup (extension_attribute)g_strdup_inline (extension_attribute);
6646}
6647
6648char *
6649caja_file_get_string_attribute (CajaFile *file, const char *attribute_name)
6650{
6651 return caja_file_get_string_attribute_q (file, g_quark_from_string (attribute_name));
6652}
6653
6654
6655/**
6656 * caja_file_get_string_attribute_with_default:
6657 *
6658 * Get a user-displayable string from a named attribute. Use g_free to
6659 * free this string. If the value is unknown, returns a string representing
6660 * the unknown value, which varies with attribute. You can call
6661 * caja_file_get_string_attribute if you want NULL instead of a default
6662 * result.
6663 *
6664 * @file: CajaFile representing the file in question.
6665 * @attribute_name: The name of the desired attribute. See the description of
6666 * caja_file_get_string for the set of available attributes.
6667 *
6668 * Returns: Newly allocated string ready to display to the user, or a string
6669 * such as "unknown" if the value is unknown or @attribute_name is not supported.
6670 *
6671 **/
6672char *
6673caja_file_get_string_attribute_with_default_q (CajaFile *file, GQuark attribute_q)
6674{
6675 char *result;
6676 guint item_count;
6677 gboolean count_unreadable;
6678 CajaRequestStatus status;
6679
6680 result = caja_file_get_string_attribute_q (file, attribute_q);
6681 if (result != NULL((void*)0)) {
6682 return result;
6683 }
6684
6685 /* Supply default values for the ones we know about. */
6686 /* FIXME bugzilla.gnome.org 40646:
6687 * Use hash table and switch statement or function pointers for speed?
6688 */
6689 if (attribute_q == attribute_size_q) {
6690 if (!caja_file_should_show_directory_item_count (file)) {
6691 return g_strdup ("--")g_strdup_inline ("--");
6692 }
6693 count_unreadable = FALSE(0);
6694 if (caja_file_is_directory (file)) {
6695 caja_file_get_directory_item_count (file, &item_count, &count_unreadable);
6696 }
6697 return g_strdup (count_unreadable ? _("? items") : "...")g_strdup_inline (count_unreadable ? dcgettext (((void*)0), "? items"
, 5) : "...")
;
6698 }
6699 if (attribute_q == attribute_deep_size_q) {
6700 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6701 if (status == CAJA_REQUEST_DONE) {
6702 /* This means no contents at all were readable */
6703 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6704 }
6705 return g_strdup ("...")g_strdup_inline ("...");
6706 }
6707 if (attribute_q == attribute_deep_size_on_disk_q) {
6708 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6709 if (status == CAJA_REQUEST_DONE) {
6710 /* This means no contents at all were readable */
6711 return g_strdup (_("? bytes"))g_strdup_inline (dcgettext (((void*)0), "? bytes", 5));
6712 }
6713 return g_strdup ("...")g_strdup_inline ("...");
6714 }
6715 if (attribute_q == attribute_deep_file_count_q
6716 || attribute_q == attribute_deep_directory_count_q
6717 || attribute_q == attribute_deep_total_count_q) {
6718 status = caja_file_get_deep_counts (file, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), FALSE(0));
6719 if (status == CAJA_REQUEST_DONE) {
6720 /* This means no contents at all were readable */
6721 return g_strdup (_("? items"))g_strdup_inline (dcgettext (((void*)0), "? items", 5));
6722 }
6723 return g_strdup ("...")g_strdup_inline ("...");
6724 }
6725 if (attribute_q == attribute_type_q) {
6726 return g_strdup (_("unknown type"))g_strdup_inline (dcgettext (((void*)0), "unknown type", 5));
6727 }
6728 if (attribute_q == attribute_mime_type_q) {
6729 return g_strdup (_("unknown MIME type"))g_strdup_inline (dcgettext (((void*)0), "unknown MIME type", 5
))
;
6730 }
6731 if (attribute_q == attribute_trashed_on_q) {
6732 /* If n/a */
6733 return g_strdup ("")g_strdup_inline ("");
6734 }
6735 if (attribute_q == attribute_trash_orig_path_q) {
6736 /* If n/a */
6737 return g_strdup ("")g_strdup_inline ("");
6738 }
6739
6740 /* Fallback, use for both unknown attributes and attributes
6741 * for which we have no more appropriate default.
6742 */
6743 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
6744}
6745
6746char *
6747caja_file_get_string_attribute_with_default (CajaFile *file, const char *attribute_name)
6748{
6749 return caja_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name));
6750}
6751
6752gboolean
6753caja_file_is_date_sort_attribute_q (GQuark attribute_q)
6754{
6755 if (attribute_q == attribute_modification_date_q ||
6756 attribute_q == attribute_date_modified_q ||
6757 attribute_q == attribute_creation_date_q ||
6758 attribute_q == attribute_date_created_q ||
6759 attribute_q == attribute_accessed_date_q ||
6760 attribute_q == attribute_date_accessed_q ||
6761 attribute_q == attribute_date_changed_q ||
6762 attribute_q == attribute_trashed_on_q ||
6763 attribute_q == attribute_date_permissions_q) {
6764 return TRUE(!(0));
6765 }
6766
6767 return FALSE(0);
6768}
6769
6770/**
6771 * get_description:
6772 *
6773 * Get a user-displayable string representing a file type. The caller
6774 * is responsible for g_free-ing this string.
6775 * @file: CajaFile representing the file in question.
6776 *
6777 * Returns: Newly allocated string ready to display to the user.
6778 *
6779 **/
6780static char *
6781get_description (CajaFile *file)
6782{
6783 const char *mime_type;
6784 char *description;
6785
6786 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_258
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_258
= 1; else _g_boolean_var_258 = 0; _g_boolean_var_258; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6786, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
6787
6788 mime_type = file->details->mime_type;
6789 if (eel_str_is_empty (mime_type)) {
6790 return NULL((void*)0);
6791 }
6792
6793 if (g_content_type_is_unknown (mime_type) &&
6794 caja_file_is_executable (file)) {
6795 return g_strdup (_("program"))g_strdup_inline (dcgettext (((void*)0), "program", 5));
6796 }
6797
6798 description = g_content_type_get_description (mime_type);
6799 if (!eel_str_is_empty (description)) {
6800 return description;
6801 }
6802
6803 return g_strdup (mime_type)g_strdup_inline (mime_type);
6804}
6805
6806/* Takes ownership of string */
6807static char *
6808update_description_for_link (CajaFile *file, char *string)
6809{
6810 if (caja_file_is_symbolic_link (file)) {
6811 char *res;
6812
6813 g_assert (!caja_file_is_broken_symbolic_link (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_259
; if (!caja_file_is_broken_symbolic_link (file)) _g_boolean_var_259
= 1; else _g_boolean_var_259 = 0; _g_boolean_var_259; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 6813, ((const char*) (__func__)), "!caja_file_is_broken_symbolic_link (file)"
); } while (0)
;
6814 if (string == NULL((void*)0)) {
6815 return g_strdup (_("link"))g_strdup_inline (dcgettext (((void*)0), "link", 5));
6816 }
6817 /* Note to localizers: convert file type string for file
6818 * (e.g. "folder", "plain text") to file type for symbolic link
6819 * to that kind of file (e.g. "link to folder").
6820 */
6821 res = g_strdup_printf (_("Link to %s")dcgettext (((void*)0), "Link to %s", 5), string);
6822 g_free (string);
6823 return res;
6824 }
6825
6826 return string;
6827}
6828
6829static char *
6830caja_file_get_type_as_string (CajaFile *file)
6831{
6832 if (file == NULL((void*)0)) {
6833 return NULL((void*)0);
6834 }
6835
6836 if (caja_file_is_broken_symbolic_link (file)) {
6837 return g_strdup (_("link (broken)"))g_strdup_inline (dcgettext (((void*)0), "link (broken)", 5));
6838 }
6839
6840 return update_description_for_link (file, get_description (file));
6841}
6842
6843/**
6844 * caja_file_get_file_type
6845 *
6846 * Return this file's type.
6847 * @file: CajaFile representing the file in question.
6848 *
6849 * Returns: The type.
6850 *
6851 **/
6852GFileType
6853caja_file_get_file_type (CajaFile *file)
6854{
6855 if (file == NULL((void*)0)) {
6856 return G_FILE_TYPE_UNKNOWN;
6857 }
6858
6859 return file->details->type;
6860}
6861
6862/**
6863 * caja_file_get_mime_type
6864 *
6865 * Return this file's default mime type.
6866 * @file: CajaFile representing the file in question.
6867 *
6868 * Returns: The mime type.
6869 *
6870 **/
6871char *
6872caja_file_get_mime_type (CajaFile *file)
6873{
6874 if (file != NULL((void*)0)) {
6875 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_260
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_260
= 1; else _g_boolean_var_260 = 0; _g_boolean_var_260; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6876 if (file->details->mime_type != NULL((void*)0)) {
6877 return g_strdup (file->details->mime_type)g_strdup_inline (file->details->mime_type);
6878 }
6879 }
6880 return g_strdup ("application/octet-stream")g_strdup_inline ("application/octet-stream");
6881}
6882
6883/**
6884 * caja_file_is_mime_type
6885 *
6886 * Check whether a file is of a particular MIME type, or inherited
6887 * from it.
6888 * @file: CajaFile representing the file in question.
6889 * @mime_type: The MIME-type string to test (e.g. "text/plain")
6890 *
6891 * Return value: TRUE if @mime_type exactly matches the
6892 * file's MIME type.
6893 *
6894 **/
6895gboolean
6896caja_file_is_mime_type (CajaFile *file, const char *mime_type)
6897{
6898 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_261
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_261
= 1; else _g_boolean_var_261 = 0; _g_boolean_var_261; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
6899 g_return_val_if_fail (mime_type != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_262
; if (mime_type != ((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__)), "mime_type != NULL"
); return ((0)); } } while (0)
;
6900
6901 if (file->details->mime_type == NULL((void*)0)) {
6902 return FALSE(0);
6903 }
6904 return g_content_type_is_a (file->details->mime_type,
6905 mime_type);
6906}
6907
6908gboolean
6909caja_file_is_launchable (CajaFile *file)
6910{
6911 gboolean type_can_be_executable;
6912
6913 type_can_be_executable = FALSE(0);
6914 if (file->details->mime_type != NULL((void*)0)) {
6915 type_can_be_executable =
6916 g_content_type_can_be_executable (file->details->mime_type);
6917 }
6918
6919 return type_can_be_executable &&
6920 caja_file_can_get_permissions (file) &&
6921 caja_file_can_execute (file) &&
6922 caja_file_is_executable (file) &&
6923 !caja_file_is_directory (file);
6924}
6925
6926
6927/**
6928 * caja_file_get_emblem_icons
6929 *
6930 * Return the list of names of emblems that this file should display,
6931 * in canonical order.
6932 * @file: CajaFile representing the file in question.
6933 *
6934 * Returns: A list of emblem names.
6935 *
6936 **/
6937GList *
6938caja_file_get_emblem_icons (CajaFile *file,
6939 char **exclude)
6940{
6941 GList *keywords, *l;
6942 GList *icons;
6943 char *icon_names[2];
6944 char *keyword;
6945 int i;
6946 GIcon *icon;
6947
6948 if (file == NULL((void*)0)) {
6949 return NULL((void*)0);
6950 }
6951
6952 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_263
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_263
= 1; else _g_boolean_var_263 = 0; _g_boolean_var_263; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
6953
6954 keywords = caja_file_get_keywords (file);
6955 keywords = prepend_automatic_keywords (file, keywords);
6956
6957 icons = NULL((void*)0);
6958 for (l = keywords; l != NULL((void*)0); l = l->next) {
6959 keyword = l->data;
6960
6961#ifdef TRASH_IS_FAST_ENOUGH
6962 if (strcmp (keyword, CAJA_FILE_EMBLEM_NAME_TRASH"trash") == 0) {
6963 char *uri;
6964 gboolean file_is_trash;
6965 /* Leave out the trash emblem for the trash itself, since
6966 * putting a trash emblem on a trash icon is gilding the
6967 * lily.
6968 */
6969 uri = caja_file_get_uri (file);
6970 file_is_trash = strcmp (uri, EEL_TRASH_URI"trash:") == 0;
6971 g_free (uri);
6972 if (file_is_trash) {
6973 continue;
6974 }
6975 }
6976#endif
6977 if (exclude) {
6978 for (i = 0; exclude[i] != NULL((void*)0); i++) {
6979 if (strcmp (exclude[i], keyword) == 0) {
6980 continue;
6981 }
6982 }
6983 }
6984
6985
6986 icon_names[0] = g_strconcat ("emblem-", keyword, NULL((void*)0));
6987 icon_names[1] = keyword;
6988 icon = g_themed_icon_new_from_names (icon_names, 2);
6989 g_free (icon_names[0]);
6990
6991 icons = g_list_prepend (icons, icon);
6992 }
6993
6994 g_list_free_full (keywords, g_free);
6995
6996 return icons;
6997}
6998
6999GList *
7000caja_file_get_emblem_pixbufs (CajaFile *file,
7001 int size,
7002 gboolean force_size,
7003 char **exclude)
7004{
7005 GList *icons, *l;
7006 GList *pixbufs;
7007 GdkPixbuf *pixbuf;
7008 GIcon *icon = NULL((void*)0);
7009 CajaIconInfo *icon_info = NULL((void*)0);
7010
7011 icons = caja_file_get_emblem_icons (file, exclude);
7012 pixbufs = NULL((void*)0);
7013
7014 for (l = icons; l != NULL((void*)0); l = l->next) {
7015 icon = l->data;
7016
7017 icon_info = caja_icon_info_lookup (icon, size, 1);
7018 if (force_size) {
7019 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (icon_info, size);
7020 } else {
7021 pixbuf = caja_icon_info_get_pixbuf_nodefault (icon_info);
7022 }
7023
7024 if (pixbuf) {
7025 pixbufs = g_list_prepend (pixbufs, pixbuf);
7026 }
7027
7028
7029 g_object_unref (icon_info);
7030 g_object_unref (icon);
7031 }
7032 g_list_free (icons);
7033
7034 return g_list_reverse (pixbufs);
7035
7036
7037}
7038
7039static GList *
7040sort_keyword_list_and_remove_duplicates (GList *keywords)
7041{
7042 GList *p;
7043
7044 if (keywords != NULL((void*)0)) {
7045 GList *duplicate_link = NULL((void*)0);
7046
7047 keywords = eel_g_str_list_alphabetize (keywords);
7048
7049 p = keywords;
7050 while (p->next != NULL((void*)0)) {
7051 if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) {
7052 duplicate_link = p->next;
7053 keywords = g_list_remove_link (keywords, duplicate_link);
7054 g_list_free_full (duplicate_link, g_free);
7055 } else {
7056 p = p->next;
7057 }
7058 }
7059 }
7060
7061 return keywords;
7062}
7063
7064/**
7065 * caja_file_get_keywords
7066 *
7067 * Return this file's keywords.
7068 * @file: CajaFile representing the file in question.
7069 *
7070 * Returns: A list of keywords.
7071 *
7072 **/
7073GList *
7074caja_file_get_keywords (CajaFile *file)
7075{
7076 GList *keywords;
7077
7078 if (file == NULL((void*)0)) {
7079 return NULL((void*)0);
7080 }
7081
7082 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_264
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_264
= 1; else _g_boolean_var_264 = 0; _g_boolean_var_264; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7083
7084 /* Put all the keywords into a list. */
7085 keywords = caja_file_get_metadata_list
7086 (file, CAJA_METADATA_KEY_EMBLEMS"emblems");
7087
7088 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7089 keywords = g_list_concat (keywords, g_list_copy_deep (file->details->pending_extension_emblems, (GCopyFunc) g_strdup, NULL((void*)0)));
7090
7091 return sort_keyword_list_and_remove_duplicates (keywords);
7092}
7093
7094/**
7095 * caja_file_set_keywords
7096 *
7097 * Change this file's keywords.
7098 * @file: CajaFile representing the file in question.
7099 * @keywords: New set of keywords (a GList of strings).
7100 *
7101 **/
7102void
7103caja_file_set_keywords (CajaFile *file, GList *keywords)
7104{
7105 GList *canonical_keywords;
7106
7107 /* Invalidate the emblem compare cache */
7108 g_free (file->details->compare_by_emblem_cache);
7109 file->details->compare_by_emblem_cache = NULL((void*)0);
7110
7111 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_265
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_265
= 1; else _g_boolean_var_265 = 0; _g_boolean_var_265; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7112
7113 canonical_keywords = sort_keyword_list_and_remove_duplicates
7114 (g_list_copy (keywords));
7115 caja_file_set_metadata_list
7116 (file, CAJA_METADATA_KEY_EMBLEMS"emblems", canonical_keywords);
7117 g_list_free (canonical_keywords);
7118}
7119
7120/**
7121 * caja_file_is_symbolic_link
7122 *
7123 * Check if this file is a symbolic link.
7124 * @file: CajaFile representing the file in question.
7125 *
7126 * Returns: True if the file is a symbolic link.
7127 *
7128 **/
7129gboolean
7130caja_file_is_symbolic_link (CajaFile *file)
7131{
7132 return file->details->is_symlink;
7133}
7134
7135gboolean
7136caja_file_is_mountpoint (CajaFile *file)
7137{
7138 return file->details->is_mountpoint;
7139}
7140
7141GMount *
7142caja_file_get_mount (CajaFile *file)
7143{
7144 if (file->details->mount) {
7145 return g_object_ref (file->details->mount)((__typeof__ (file->details->mount)) (g_object_ref) (file
->details->mount))
;
7146 }
7147 return NULL((void*)0);
7148}
7149
7150static void
7151file_mount_unmounted (GMount *mount,
7152 gpointer data)
7153{
7154 CajaFile *file;
7155
7156 file = CAJA_FILE (data)((((CajaFile*) (void *) ((data)))));
7157
7158 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_MOUNT);
7159}
7160
7161void
7162caja_file_set_mount (CajaFile *file,
7163 GMount *mount)
7164{
7165 if (file->details->mount) {
7166 g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file)g_signal_handlers_disconnect_matched ((file->details->mount
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (file_mount_unmounted), (file))
;
7167 g_object_unref (file->details->mount);
7168 file->details->mount = NULL((void*)0);
7169 }
7170
7171 if (mount) {
7172 file->details->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
7173 g_signal_connect (mount, "unmounted",g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
7174 G_CALLBACK (file_mount_unmounted), file)g_signal_connect_data ((mount), ("unmounted"), (((GCallback) (
file_mount_unmounted))), (file), ((void*)0), (GConnectFlags) 0
)
;
7175 }
7176}
7177
7178/**
7179 * caja_file_is_broken_symbolic_link
7180 *
7181 * Check if this file is a symbolic link with a missing target.
7182 * @file: CajaFile representing the file in question.
7183 *
7184 * Returns: True if the file is a symbolic link with a missing target.
7185 *
7186 **/
7187gboolean
7188caja_file_is_broken_symbolic_link (CajaFile *file)
7189{
7190 if (file == NULL((void*)0)) {
7191 return FALSE(0);
7192 }
7193
7194 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_266
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_266
= 1; else _g_boolean_var_266 = 0; _g_boolean_var_266; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7195
7196 /* Non-broken symbolic links return the target's type for get_file_type. */
7197 return caja_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK;
7198}
7199
7200static void
7201get_fs_free_cb (GObject *source_object,
7202 GAsyncResult *res,
7203 gpointer user_data)
7204{
7205 CajaDirectory *directory;
7206 guint64 free_space;
7207 GFileInfo *info;
7208
7209 directory = CAJA_DIRECTORY (user_data)((((CajaDirectory*) (void *) ((user_data)))));
7210
7211 free_space = (guint64)-1;
7212 info = g_file_query_filesystem_info_finish (G_FILE (source_object)((((GFile*) (void *) ((source_object))))),
7213 res, NULL((void*)0));
7214 if (info) {
7215 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
7216 free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
7217 }
7218 g_object_unref (info);
7219 }
7220
7221 if (directory->details->free_space != free_space) {
7222 CajaFile *file;
7223
7224 directory->details->free_space = free_space;
7225 file = caja_directory_get_existing_corresponding_file (directory);
7226 if (file) {
7227 caja_file_emit_changed (file);
7228 caja_file_unref (file);
7229 }
7230 }
7231 caja_directory_unref (directory);
7232}
7233
7234/**
7235 * caja_file_get_volume_free_space
7236 * Get a nicely formatted char with free space on the file's volume
7237 * @file: CajaFile representing the file in question.
7238 *
7239 * Returns: newly-allocated copy of file size in a formatted string
7240 */
7241char *
7242caja_file_get_volume_free_space (CajaFile *file)
7243{
7244 CajaDirectory *directory;
7245 char *res;
7246 time_t now;
7247
7248 directory = caja_directory_get_for_file (file);
7249
7250 now = time (NULL((void*)0));
7251 /* Update first time and then every 2 seconds */
7252 if (directory->details->free_space_read == 0 ||
7253 (now - directory->details->free_space_read) > 2) {
7254 GFile *location;
7255
7256 directory->details->free_space_read = now;
7257 location = caja_file_get_location (file);
7258 g_file_query_filesystem_info_async (location,
7259 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free",
7260 0, NULL((void*)0),
7261 get_fs_free_cb,
7262 directory); /* Inherits ref */
7263 g_object_unref (location);
7264 } else {
7265 caja_directory_unref (directory);
7266 }
7267
7268
7269 res = NULL((void*)0);
7270
7271 if (directory->details->free_space != (guint64) -1)
7272 {
7273 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
7274 res = g_format_size_full (directory->details->free_space, G_FORMAT_SIZE_IEC_UNITS);
7275 else
7276 res = g_format_size(directory->details->free_space);
7277 }
7278
7279 return res;
7280}
7281
7282/**
7283 * caja_file_get_volume_name
7284 * Get the path of the volume the file resides on
7285 * @file: CajaFile representing the file in question.
7286 *
7287 * Returns: newly-allocated copy of the volume name of the target file,
7288 * if the volume name isn't set, it returns the mount path of the volume
7289 */
7290char *
7291caja_file_get_volume_name (CajaFile *file)
7292{
7293 GFile *location;
7294 char *res;
7295 GMount *mount;
7296
7297 res = NULL((void*)0);
7298
7299 location = caja_file_get_location (file);
7300 mount = g_file_find_enclosing_mount (location, NULL((void*)0), NULL((void*)0));
7301 if (mount) {
7302 res = g_strdup (g_mount_get_name (mount))g_strdup_inline (g_mount_get_name (mount));
7303 g_object_unref (mount);
7304 }
7305 g_object_unref (location);
7306
7307 return res;
7308}
7309
7310/**
7311 * caja_file_get_symbolic_link_target_path
7312 *
7313 * Get the file path of the target of a symbolic link. It is an error
7314 * to call this function on a file that isn't a symbolic link.
7315 * @file: CajaFile representing the symbolic link in question.
7316 *
7317 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
7318 */
7319char *
7320caja_file_get_symbolic_link_target_path (CajaFile *file)
7321{
7322 if (!caja_file_is_symbolic_link (file)) {
7323 g_warning ("File has symlink target, but is not marked as symlink");
7324 }
7325
7326 return g_strdup (file->details->symlink_name)g_strdup_inline (file->details->symlink_name);
7327}
7328
7329/**
7330 * caja_file_get_symbolic_link_target_uri
7331 *
7332 * Get the uri of the target of a symbolic link. It is an error
7333 * to call this function on a file that isn't a symbolic link.
7334 * @file: CajaFile representing the symbolic link in question.
7335 *
7336 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
7337 */
7338char *
7339caja_file_get_symbolic_link_target_uri (CajaFile *file)
7340{
7341 if (!caja_file_is_symbolic_link (file)) {
7342 g_warning ("File has symlink target, but is not marked as symlink");
7343 }
7344
7345 if (file->details->symlink_name == NULL((void*)0)) {
7346 return NULL((void*)0);
7347 } else {
7348 GFile *location, *parent, *target;
7349 char *target_uri;
7350
7351 target = NULL((void*)0);
7352
7353 location = caja_file_get_location (file);
7354 parent = g_file_get_parent (location);
7355 g_object_unref (location);
7356 if (parent) {
7357 target = g_file_resolve_relative_path (parent, file->details->symlink_name);
7358 g_object_unref (parent);
7359 }
7360
7361 target_uri = NULL((void*)0);
7362 if (target) {
7363 target_uri = g_file_get_uri (target);
7364 g_object_unref (target);
7365 }
7366 return target_uri;
7367 }
7368}
7369
7370/**
7371 * caja_file_is_caja_link
7372 *
7373 * Check if this file is a "caja link", meaning a historical
7374 * caja xml link file or a desktop file.
7375 * @file: CajaFile representing the file in question.
7376 *
7377 * Returns: True if the file is a caja link.
7378 *
7379 **/
7380gboolean
7381caja_file_is_caja_link (CajaFile *file)
7382{
7383 if (file->details->mime_type == NULL((void*)0))
7384 {
7385 return FALSE(0);
7386 }
7387 return g_content_type_equals (file->details->mime_type,
7388 "application/x-desktop");
7389}
7390
7391/**
7392 * caja_file_is_directory
7393 *
7394 * Check if this file is a directory.
7395 * @file: CajaFile representing the file in question.
7396 *
7397 * Returns: TRUE if @file is a directory.
7398 *
7399 **/
7400gboolean
7401caja_file_is_directory (CajaFile *file)
7402{
7403 return caja_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY;
7404}
7405
7406/**
7407 * caja_file_is_user_special_directory
7408 *
7409 * Check if this file is a special platform directory.
7410 * @file: CajaFile representing the file in question.
7411 * @special_directory: GUserDirectory representing the type to test for
7412 *
7413 * Returns: TRUE if @file is a special directory of the given kind.
7414 */
7415gboolean
7416caja_file_is_user_special_directory (CajaFile *file,
7417 GUserDirectory special_directory)
7418{
7419 gboolean is_special_dir;
7420 const gchar *special_dir;
7421
7422 special_dir = g_get_user_special_dir (special_directory);
7423 is_special_dir = FALSE(0);
7424
7425 if (special_dir) {
7426 GFile *loc;
7427 GFile *special_gfile;
7428
7429 loc = caja_file_get_location (file);
7430 special_gfile = g_file_new_for_path (special_dir);
7431 is_special_dir = g_file_equal (loc, special_gfile);
7432 g_object_unref (special_gfile);
7433 g_object_unref (loc);
7434 }
7435
7436 return is_special_dir;
7437}
7438
7439gboolean
7440caja_file_is_archive (CajaFile *file)
7441{
7442 char *mime_type;
7443 int i;
7444 static const char * archive_mime_types[] = { "application/x-gtar",
7445 "application/x-zip",
7446 "application/x-zip-compressed",
7447 "application/zip",
7448 "application/x-zip",
7449 "application/x-tar",
7450 "application/x-7z-compressed",
7451 "application/x-rar",
7452 "application/x-rar-compressed",
7453 "application/x-jar",
7454 "application/x-java-archive",
7455 "application/x-war",
7456 "application/x-ear",
7457 "application/x-arj",
7458 "application/x-gzip",
7459 "application/x-bzip-compressed-tar",
7460 "application/x-compressed-tar" };
7461
7462 g_return_val_if_fail (file != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (file != ((void*)0)) _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__)), "file != NULL"); return
((0)); } } while (0)
;
7463
7464 mime_type = caja_file_get_mime_type (file);
7465 for (i = 0; i < G_N_ELEMENTS (archive_mime_types)(sizeof (archive_mime_types) / sizeof ((archive_mime_types)[0
]))
; i++) {
7466 if (!strcmp (mime_type, archive_mime_types[i])) {
7467 g_free (mime_type);
7468 return TRUE(!(0));
7469 }
7470 }
7471 g_free (mime_type);
7472
7473 return FALSE(0);
7474}
7475
7476
7477/**
7478 * caja_file_is_in_trash
7479 *
7480 * Check if this file is a file in trash.
7481 * @file: CajaFile representing the file in question.
7482 *
7483 * Returns: TRUE if @file is in a trash.
7484 *
7485 **/
7486gboolean
7487caja_file_is_in_trash (CajaFile *file)
7488{
7489 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_268
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_268
= 1; else _g_boolean_var_268 = 0; _g_boolean_var_268; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7489, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7490
7491 return caja_directory_is_in_trash (file->details->directory);
7492}
7493
7494GError *
7495caja_file_get_file_info_error (CajaFile *file)
7496{
7497 if (!file->details->get_info_failed) {
7498 return NULL((void*)0);
7499 }
7500
7501 return file->details->get_info_error;
7502}
7503
7504/**
7505 * caja_file_contains_text
7506 *
7507 * Check if this file contains text.
7508 * This is private and is used to decide whether or not to read the top left text.
7509 * @file: CajaFile representing the file in question.
7510 *
7511 * Returns: TRUE if @file has a text MIME type.
7512 *
7513 **/
7514gboolean
7515caja_file_contains_text (CajaFile *file)
7516{
7517 if (file == NULL((void*)0)) {
7518 return FALSE(0);
7519 }
7520
7521 /* All text files inherit from text/plain */
7522 return caja_file_is_mime_type (file, "text/plain");
7523}
7524
7525/**
7526 * caja_file_is_binary
7527 *
7528 * Check if this file is a binary file.
7529 * This is private and is used to decide whether or not to show the diff
7530 * button in the file conflict dialog.
7531 * @file: CajaFile representing the file in question.
7532 *
7533 * Returns: TRUE if @file is a binary file.
7534 *
7535 **/
7536gboolean
7537caja_file_is_binary (CajaFile *file)
7538{
7539 if (!caja_file_can_read(file))
7540 {
7541 return FALSE(0);
7542 }
7543
7544 gboolean is_binary = FALSE(0);
7545 int i = 0;
7546 FILE *fp;
7547
7548 /* Check the first 4096 bytes of the files. If these contains a 0,
7549 * we can assume the file is binary.
7550 * This idea is taken from python code of meld.
7551 */
7552
7553 fp = g_fopenfopen (g_file_get_path (caja_file_get_location (file)), "r");
7554 if (fp == NULL((void*)0))
7555 {
7556 return FALSE(0);
7557 }
7558
7559 while (!feof (fp)) {
7560 int c;
7561
7562 if (i > 4096) {
7563 break;
7564 }
7565 c = fgetc(fp);
7566 if (c == 0) {
7567 is_binary = TRUE(!(0));
7568 break;
7569 }
7570 i++;
7571 }
7572 fclose(fp);
7573
7574 return is_binary;
7575}
7576
7577/**
7578 * caja_file_is_executable
7579 *
7580 * Check if this file is executable at all.
7581 * @file: CajaFile representing the file in question.
7582 *
7583 * Returns: TRUE if any of the execute bits are set. FALSE if
7584 * not, or if the permissions are unknown.
7585 *
7586 **/
7587gboolean
7588caja_file_is_executable (CajaFile *file)
7589{
7590 if (!file->details->has_permissions) {
7591 /* File's permissions field is not valid.
7592 * Can't access specific permissions, so return FALSE.
7593 */
7594 return FALSE(0);
7595 }
7596
7597 return file->details->can_execute;
7598}
7599
7600/**
7601 * caja_file_peek_top_left_text
7602 *
7603 * Peek at the text from the top left of the file.
7604 * @file: CajaFile representing the file in question.
7605 *
7606 * Returns: NULL if there is no text readable, otherwise, the text.
7607 * This string is owned by the file object and should not
7608 * be kept around or freed.
7609 *
7610 **/
7611char *
7612caja_file_peek_top_left_text (CajaFile *file,
7613 gboolean need_large_text,
7614 gboolean *needs_loading)
7615{
7616 g_return_val_if_fail (CAJA_IS_FILE (file), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_269
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_269
= 1; else _g_boolean_var_269 = 0; _g_boolean_var_269; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return (((void*)
0)); } } while (0)
;
7617
7618 if (!caja_file_should_get_top_left_text (file)) {
7619 if (needs_loading) {
7620 *needs_loading = FALSE(0);
7621 }
7622 return NULL((void*)0);
7623 }
7624
7625 if (needs_loading) {
7626 *needs_loading = !file->details->top_left_text_is_up_to_date;
7627 if (need_large_text) {
7628 *needs_loading |= file->details->got_top_left_text != file->details->got_large_top_left_text;
7629 }
7630 }
7631
7632 /* Show " ..." in the file until we read the contents in. */
7633 if (!file->details->got_top_left_text) {
7634
7635 if (caja_file_contains_text (file)) {
7636 return " ...";
7637 }
7638 return NULL((void*)0);
7639 }
7640
7641 /* Show what we read in. */
7642 return file->details->top_left_text;
7643}
7644
7645/**
7646 * caja_file_get_top_left_text
7647 *
7648 * Get the text from the top left of the file.
7649 * @file: CajaFile representing the file in question.
7650 *
7651 * Returns: NULL if there is no text readable, otherwise, the text.
7652 *
7653 **/
7654char *
7655caja_file_get_top_left_text (CajaFile *file)
7656{
7657 return g_strdup (caja_file_peek_top_left_text (file, FALSE, NULL))g_strdup_inline (caja_file_peek_top_left_text (file, (0), ((void
*)0)))
;
7658}
7659
7660char *
7661caja_file_get_filesystem_id (CajaFile *file)
7662{
7663 return g_strdup (file->details->filesystem_id)g_strdup_inline (file->details->filesystem_id);
7664}
7665
7666CajaFile *
7667caja_file_get_trash_original_file (CajaFile *file)
7668{
7669 CajaFile *original_file;
7670
7671 original_file = NULL((void*)0);
7672
7673 if (file->details->trash_orig_path != NULL((void*)0)) {
7674 GFile *location;
7675
7676 location = g_file_new_for_path (file->details->trash_orig_path);
7677 original_file = caja_file_get (location);
7678 g_object_unref (location);
7679 }
7680
7681 return original_file;
7682
7683}
7684
7685void
7686caja_file_mark_gone (CajaFile *file)
7687{
7688 CajaDirectory *directory;
7689
7690 if (file->details->is_gone)
7691 return;
7692
7693 file->details->is_gone = TRUE(!(0));
7694
7695 update_links_if_target (file);
7696
7697 /* Drop it from the symlink hash ! */
7698 remove_from_link_hash_table (file);
7699
7700 /* Let the directory know it's gone. */
7701 directory = file->details->directory;
7702 if (!caja_file_is_self_owned (file)) {
7703 caja_directory_remove_file (directory, file);
7704 }
7705
7706 caja_file_clear_info (file);
7707
7708 /* FIXME bugzilla.gnome.org 42429:
7709 * Maybe we can get rid of the name too eventually, but
7710 * for now that would probably require too many if statements
7711 * everywhere anyone deals with the name. Maybe we can give it
7712 * a hard-coded "<deleted>" name or something.
7713 */
7714}
7715
7716/**
7717 * caja_file_changed
7718 *
7719 * Notify the user that this file has changed.
7720 * @file: CajaFile representing the file in question.
7721 **/
7722void
7723caja_file_changed (CajaFile *file)
7724{
7725 GList fake_list;
7726
7727 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_270
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_270
= 1; else _g_boolean_var_270 = 0; _g_boolean_var_270; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7728
7729 if (caja_file_is_self_owned (file)) {
7730 caja_file_emit_changed (file);
7731 } else {
7732 fake_list.data = file;
7733 fake_list.next = NULL((void*)0);
7734 fake_list.prev = NULL((void*)0);
7735 caja_directory_emit_change_signals
7736 (file->details->directory, &fake_list);
7737 }
7738}
7739
7740/**
7741 * caja_file_updated_deep_count_in_progress
7742 *
7743 * Notify clients that a newer deep count is available for
7744 * the directory in question.
7745 */
7746void
7747caja_file_updated_deep_count_in_progress (CajaFile *file) {
7748 GList *link_files, *node;
7749
7750 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_271
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_271
= 1; else _g_boolean_var_271 = 0; _g_boolean_var_271; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7750, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7751 g_assert (caja_file_is_directory (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if (caja_file_is_directory (file)) _g_boolean_var_272 = 1; else
_g_boolean_var_272 = 0; _g_boolean_var_272; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file.c", 7751, ((const char*) (__func__
)), "caja_file_is_directory (file)"); } while (0)
;
7752
7753 /* Send out a signal. */
7754 g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file);
7755
7756 /* Tell link files pointing to this object about the change. */
7757 link_files = get_link_files (file);
7758 for (node = link_files; node != NULL((void*)0); node = node->next) {
7759 caja_file_updated_deep_count_in_progress (CAJA_FILE (node->data)((((CajaFile*) (void *) ((node->data))))));
7760 }
7761 caja_file_list_free (link_files);
7762}
7763
7764/**
7765 * caja_file_emit_changed
7766 *
7767 * Emit a file changed signal.
7768 * This can only be called by the directory, since the directory
7769 * also has to emit a files_changed signal.
7770 *
7771 * @file: CajaFile representing the file in question.
7772 **/
7773void
7774caja_file_emit_changed (CajaFile *file)
7775{
7776 GList *link_files, *p;
7777
7778 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_273
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_273
= 1; else _g_boolean_var_273 = 0; _g_boolean_var_273; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "caja-file.c"
, 7778, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
7779
7780
7781 /* Invalidate the emblem compare cache. -- This is not the cleanest
7782 * place to do it but it is the one guaranteed bottleneck through
7783 * which all change notifications pass.
7784 */
7785 g_free (file->details->compare_by_emblem_cache);
7786 file->details->compare_by_emblem_cache = NULL((void*)0);
7787
7788 /* Send out a signal. */
7789 g_signal_emit (file, signals[CHANGED], 0, file);
7790
7791 /* Tell link files pointing to this object about the change. */
7792 link_files = get_link_files (file);
7793 for (p = link_files; p != NULL((void*)0); p = p->next) {
7794 if (p->data != file) {
7795 caja_file_changed (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
7796 }
7797 }
7798 caja_file_list_free (link_files);
7799}
7800
7801/**
7802 * caja_file_is_gone
7803 *
7804 * Check if a file has already been deleted.
7805 * @file: CajaFile representing the file in question.
7806 *
7807 * Returns: TRUE if the file is already gone.
7808 **/
7809gboolean
7810caja_file_is_gone (CajaFile *file)
7811{
7812 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_274
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_274
= 1; else _g_boolean_var_274 = 0; _g_boolean_var_274; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7813
7814 return file->details->is_gone;
7815}
7816
7817/**
7818 * caja_file_is_not_yet_confirmed
7819 *
7820 * Check if we're in a state where we don't know if a file really
7821 * exists or not, before the initial I/O is complete.
7822 * @file: CajaFile representing the file in question.
7823 *
7824 * Returns: TRUE if the file is already gone.
7825 **/
7826gboolean
7827caja_file_is_not_yet_confirmed (CajaFile *file)
7828{
7829 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_275
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_275
= 1; else _g_boolean_var_275 = 0; _g_boolean_var_275; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7830
7831 return !file->details->got_file_info;
7832}
7833
7834/**
7835 * caja_file_check_if_ready
7836 *
7837 * Check whether the values for a set of file attributes are
7838 * currently available, without doing any additional work. This
7839 * is useful for callers that want to reflect updated information
7840 * when it is ready but don't want to force the work required to
7841 * obtain the information, which might be slow network calls, e.g.
7842 *
7843 * @file: The file being queried.
7844 * @file_attributes: A bit-mask with the desired information.
7845 *
7846 * Return value: TRUE if all of the specified attributes are currently readable.
7847 */
7848gboolean
7849caja_file_check_if_ready (CajaFile *file,
7850 CajaFileAttributes file_attributes)
7851{
7852 /* To be parallel with call_when_ready, return
7853 * TRUE for NULL file.
7854 */
7855 if (file == NULL((void*)0)) {
7856 return TRUE(!(0));
7857 }
7858
7859 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_276
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_276
= 1; else _g_boolean_var_276 = 0; _g_boolean_var_276; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
7860
7861 return EEL_CALL_METHOD_WITH_RETURN_VALUE(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7862 (CAJA_FILE_CLASS, file,(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
7863 check_if_ready, (file, file_attributes))(((((CajaFileClass*) (void *) ((((((GObjectClass*) (((GTypeInstance
*) ((file)))->g_class)))))))))->check_if_ready == ((void
*)0)) ? 0 : ((* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->check_if_ready
) (file, file_attributes))
;
7864}
7865
7866void
7867caja_file_call_when_ready (CajaFile *file,
7868 CajaFileAttributes file_attributes,
7869 CajaFileCallback callback,
7870 gpointer callback_data)
7871
7872{
7873 if (file == NULL((void*)0)) {
7874 (* callback) (file, callback_data);
7875 return;
7876 }
7877
7878 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_277
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_277
= 1; else _g_boolean_var_277 = 0; _g_boolean_var_277; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7879
7880 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7881 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7882 call_when_ready, (file, file_attributes,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
7883 callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->call_when_ready
) (file, file_attributes, callback, callback_data); } } while
(0)
;
7884}
7885
7886void
7887caja_file_cancel_call_when_ready (CajaFile *file,
7888 CajaFileCallback callback,
7889 gpointer callback_data)
7890{
7891 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_278
; if (callback != ((void*)0)) _g_boolean_var_278 = 1; else _g_boolean_var_278
= 0; _g_boolean_var_278; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
7892
7893 if (file == NULL((void*)0)) {
7894 return;
7895 }
7896
7897 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_279
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_279
= 1; else _g_boolean_var_279 = 0; _g_boolean_var_279; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
7898
7899 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7900 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
7901 cancel_call_when_ready, (file, callback, callback_data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, callback, callback_data); } } while (0)
;
7902}
7903
7904static void
7905invalidate_directory_count (CajaFile *file)
7906{
7907 file->details->directory_count_is_up_to_date = FALSE(0);
7908}
7909
7910static void
7911invalidate_deep_counts (CajaFile *file)
7912{
7913 file->details->deep_counts_status = CAJA_REQUEST_NOT_STARTED;
7914}
7915
7916static void
7917invalidate_mime_list (CajaFile *file)
7918{
7919 file->details->mime_list_is_up_to_date = FALSE(0);
7920}
7921
7922static void
7923invalidate_top_left_text (CajaFile *file)
7924{
7925 file->details->top_left_text_is_up_to_date = FALSE(0);
7926}
7927
7928static void
7929invalidate_file_info (CajaFile *file)
7930{
7931 file->details->file_info_is_up_to_date = FALSE(0);
7932}
7933
7934static void
7935invalidate_link_info (CajaFile *file)
7936{
7937 file->details->link_info_is_up_to_date = FALSE(0);
7938}
7939
7940static void
7941invalidate_thumbnail (CajaFile *file)
7942{
7943 file->details->thumbnail_is_up_to_date = FALSE(0);
7944}
7945
7946static void
7947invalidate_mount (CajaFile *file)
7948{
7949 file->details->mount_is_up_to_date = FALSE(0);
7950}
7951
7952void
7953caja_file_invalidate_extension_info_internal (CajaFile *file)
7954{
7955 if (file->details->pending_info_providers)
7956 g_list_free_full (file->details->pending_info_providers, g_object_unref);
7957
7958 file->details->pending_info_providers =
7959 caja_extensions_get_for_type (CAJA_TYPE_INFO_PROVIDER(caja_info_provider_get_type ()));
7960}
7961
7962void
7963caja_file_invalidate_attributes_internal (CajaFile *file,
7964 CajaFileAttributes file_attributes)
7965{
7966 Request request;
7967
7968 if (file == NULL((void*)0)) {
7969 return;
7970 }
7971
7972 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
7973 /* Desktop icon files are always up to date.
7974 * If we invalidate their attributes they
7975 * will lose data, so we just ignore them.
7976 */
7977 return;
7978 }
7979
7980 request = caja_directory_set_up_request (file_attributes);
7981
7982 if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)((request) & (1<<(REQUEST_DIRECTORY_COUNT)))) {
7983 invalidate_directory_count (file);
7984 }
7985 if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)((request) & (1<<(REQUEST_DEEP_COUNT)))) {
7986 invalidate_deep_counts (file);
7987 }
7988 if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)((request) & (1<<(REQUEST_MIME_LIST)))) {
7989 invalidate_mime_list (file);
7990 }
7991 if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)((request) & (1<<(REQUEST_FILE_INFO)))) {
7992 invalidate_file_info (file);
7993 }
7994 if (REQUEST_WANTS_TYPE (request, REQUEST_TOP_LEFT_TEXT)((request) & (1<<(REQUEST_TOP_LEFT_TEXT)))) {
7995 invalidate_top_left_text (file);
7996 }
7997 if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)((request) & (1<<(REQUEST_LINK_INFO)))) {
7998 invalidate_link_info (file);
7999 }
8000 if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)((request) & (1<<(REQUEST_EXTENSION_INFO)))) {
8001 caja_file_invalidate_extension_info_internal (file);
8002 }
8003 if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)((request) & (1<<(REQUEST_THUMBNAIL)))) {
8004 invalidate_thumbnail (file);
8005 }
8006 if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)((request) & (1<<(REQUEST_MOUNT)))) {
8007 invalidate_mount (file);
8008 }
8009
8010 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
8011}
8012
8013gboolean
8014caja_file_has_open_window (CajaFile *file)
8015{
8016 return file->details->has_open_window;
8017}
8018
8019void
8020caja_file_set_has_open_window (CajaFile *file,
8021 gboolean has_open_window)
8022{
8023 has_open_window = (has_open_window != FALSE(0));
8024
8025 if (file->details->has_open_window != has_open_window) {
8026 file->details->has_open_window = has_open_window;
8027 caja_file_changed (file);
8028 }
8029}
8030
8031
8032gboolean
8033caja_file_is_thumbnailing (CajaFile *file)
8034{
8035 g_return_val_if_fail (CAJA_IS_FILE (file), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_280
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_280
= 1; else _g_boolean_var_280 = 0; _g_boolean_var_280; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return ((0)); } }
while (0)
;
8036
8037 return file->details->is_thumbnailing;
8038}
8039
8040void
8041caja_file_set_is_thumbnailing (CajaFile *file,
8042 gboolean is_thumbnailing)
8043{
8044 g_return_if_fail (CAJA_IS_FILE (file))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_281
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_281
= 1; else _g_boolean_var_281 = 0; _g_boolean_var_281; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CAJA_IS_FILE (file)"); return; } } while
(0)
;
8045
8046 file->details->is_thumbnailing = is_thumbnailing;
8047}
8048
8049
8050/**
8051 * caja_file_invalidate_attributes
8052 *
8053 * Invalidate the specified attributes and force a reload.
8054 * @file: CajaFile representing the file in question.
8055 * @file_attributes: attributes to froget.
8056 **/
8057
8058void
8059caja_file_invalidate_attributes (CajaFile *file,
8060 CajaFileAttributes file_attributes)
8061{
8062 /* Cancel possible in-progress loads of any of these attributes */
8063 caja_directory_cancel_loading_file_attributes (file->details->directory,
8064 file,
8065 file_attributes);
8066
8067 /* Actually invalidate the values */
8068 caja_file_invalidate_attributes_internal (file, file_attributes);
8069
8070 caja_directory_add_file_to_work_queue (file->details->directory, file);
8071
8072 /* Kick off I/O if necessary */
8073 caja_directory_async_state_changed (file->details->directory);
8074}
8075
8076CajaFileAttributes
8077caja_file_get_all_attributes (void)
8078{
8079 return CAJA_FILE_ATTRIBUTE_INFO |
8080 CAJA_FILE_ATTRIBUTE_LINK_INFO |
8081 CAJA_FILE_ATTRIBUTE_DEEP_COUNTS |
8082 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
8083 CAJA_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES |
8084 CAJA_FILE_ATTRIBUTE_TOP_LEFT_TEXT |
8085 CAJA_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
8086 CAJA_FILE_ATTRIBUTE_EXTENSION_INFO |
8087 CAJA_FILE_ATTRIBUTE_THUMBNAIL |
8088 CAJA_FILE_ATTRIBUTE_MOUNT;
8089}
8090
8091void
8092caja_file_invalidate_all_attributes (CajaFile *file)
8093{
8094 CajaFileAttributes all_attributes;
8095
8096 all_attributes = caja_file_get_all_attributes ();
8097 caja_file_invalidate_attributes (file, all_attributes);
8098}
8099
8100
8101/**
8102 * caja_file_dump
8103 *
8104 * Debugging call, prints out the contents of the file
8105 * fields.
8106 *
8107 * @file: file to dump.
8108 **/
8109void
8110caja_file_dump (CajaFile *file)
8111{
8112 long size = file->details->deep_size;
8113 long size_on_disk = file->details->deep_size_on_disk;
8114 char *uri;
8115 const char *file_kind;
8116
8117 uri = caja_file_get_uri (file);
8118 g_print ("uri: %s \n", uri);
8119 if (!file->details->got_file_info) {
8120 g_print ("no file info \n");
8121 } else if (file->details->get_info_failed) {
8122 g_print ("failed to get file info \n");
8123 } else {
8124 g_print ("size: %ld \n", size);
8125 g_print ("disk size: %ld \n", size_on_disk);
8126 switch (file->details->type) {
8127 case G_FILE_TYPE_REGULAR:
8128 file_kind = "regular file";
8129 break;
8130 case G_FILE_TYPE_DIRECTORY:
8131 file_kind = "folder";
8132 break;
8133 case G_FILE_TYPE_SPECIAL:
8134 file_kind = "special";
8135 break;
8136 case G_FILE_TYPE_SYMBOLIC_LINK:
8137 file_kind = "symbolic link";
8138 break;
8139 case G_FILE_TYPE_UNKNOWN:
8140 default:
8141 file_kind = "unknown";
8142 break;
8143 }
8144 g_print ("kind: %s \n", file_kind);
8145 if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) {
8146 g_print ("link to %s \n", file->details->symlink_name);
8147 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
8148 }
8149 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
8150 }
8151 g_free (uri);
8152}
8153
8154/**
8155 * caja_file_list_ref
8156 *
8157 * Ref all the files in a list.
8158 * @list: GList of files.
8159 **/
8160GList *
8161caja_file_list_ref (GList *list)
8162{
8163 g_list_foreach (list, (GFunc) caja_file_ref, NULL((void*)0));
8164 return list;
8165}
8166
8167/**
8168 * caja_file_list_unref
8169 *
8170 * Unref all the files in a list.
8171 * @list: GList of files.
8172 **/
8173void
8174caja_file_list_unref (GList *list)
8175{
8176 g_list_foreach (list, (GFunc) caja_file_unref, NULL((void*)0));
8177}
8178
8179/**
8180 * caja_file_list_free
8181 *
8182 * Free a list of files after unrefing them.
8183 * @list: GList of files.
8184 **/
8185void
8186caja_file_list_free (GList *list)
8187{
8188 caja_file_list_unref (list);
8189 g_list_free (list);
8190}
8191
8192/**
8193 * caja_file_list_copy
8194 *
8195 * Copy the list of files, making a new ref of each,
8196 * @list: GList of files.
8197 **/
8198GList *
8199caja_file_list_copy (GList *list)
8200{
8201 return g_list_copy (caja_file_list_ref (list));
8202}
8203
8204static gboolean
8205get_attributes_for_default_sort_type (CajaFile *file,
8206 gboolean *is_download,
8207 gboolean *is_trash)
8208{
8209 gboolean is_download_dir, is_desktop_dir, is_trash_dir, retval;
8210
8211 *is_download = FALSE(0);
8212 *is_trash = FALSE(0);
8213 retval = FALSE(0);
8214
8215 /* special handling for certain directories */
8216 if (file && caja_file_is_directory (file)) {
8217 is_download_dir =
8218 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD);
8219 is_desktop_dir =
8220 caja_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP);
8221 is_trash_dir =
8222 caja_file_is_in_trash (file);
8223
8224 if (is_download_dir && !is_desktop_dir) {
8225 *is_download = TRUE(!(0));
8226 retval = TRUE(!(0));
8227 } else if (is_trash_dir) {
8228 *is_trash = TRUE(!(0));
8229 retval = TRUE(!(0));
8230 }
8231 }
8232
8233 return retval;
8234}
8235
8236CajaFileSortType
8237caja_file_get_default_sort_type (CajaFile *file,
8238 gboolean *reversed)
8239{
8240 CajaFileSortType retval;
8241 gboolean is_download, is_trash, res;
8242
8243 retval = CAJA_FILE_SORT_NONE;
8244 is_download = is_trash = FALSE(0);
8245 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8246
8247 if (res) {
8248 if (is_download) {
8249 retval = CAJA_FILE_SORT_BY_MTIME;
8250 } else if (is_trash) {
8251 retval = CAJA_FILE_SORT_BY_TRASHED_TIME;
8252 }
8253
8254 if (reversed != NULL((void*)0)) {
8255 *reversed = res;
8256 }
8257 }
8258
8259 return retval;
8260}
8261
8262const gchar *
8263caja_file_get_default_sort_attribute (CajaFile *file,
8264 gboolean *reversed)
8265{
8266 const gchar *retval;
8267 gboolean is_download, is_trash, res;
8268
8269 retval = NULL((void*)0);
8270 is_download = is_trash = FALSE(0);
8271 res = get_attributes_for_default_sort_type (file, &is_download, &is_trash);
8272
8273 if (res) {
8274 if (is_download) {
8275 retval = g_quark_to_string (attribute_date_modified_q);
8276 } else if (is_trash) {
8277 retval = g_quark_to_string (attribute_trashed_on_q);
8278 }
8279
8280 if (reversed != NULL((void*)0)) {
8281 *reversed = res;
8282 }
8283 }
8284
8285 return retval;
8286}
8287
8288static int
8289compare_by_display_name_cover (gconstpointer a, gconstpointer b)
8290{
8291 return compare_by_display_name (CAJA_FILE (a)((((CajaFile*) (void *) ((a))))), CAJA_FILE (b)((((CajaFile*) (void *) ((b))))));
8292}
8293
8294/**
8295 * caja_file_list_sort_by_display_name
8296 *
8297 * Sort the list of files by file name.
8298 * @list: GList of files.
8299 **/
8300GList *
8301caja_file_list_sort_by_display_name (GList *list)
8302{
8303 return g_list_sort (list, compare_by_display_name_cover);
8304}
8305
8306static GList *ready_data_list = NULL((void*)0);
8307
8308typedef struct
8309{
8310 GList *file_list;
8311 GList *remaining_files;
8312 CajaFileListCallback callback;
8313 gpointer callback_data;
8314} FileListReadyData;
8315
8316static void
8317file_list_ready_data_free (FileListReadyData *data)
8318{
8319 GList *l;
8320
8321 l = g_list_find (ready_data_list, data);
8322 if (l != NULL((void*)0)) {
8323 ready_data_list = g_list_delete_link (ready_data_list, l);
8324
8325 caja_file_list_free (data->file_list);
8326 g_list_free (data->remaining_files);
8327 g_free (data);
8328 }
8329}
8330
8331static FileListReadyData *
8332file_list_ready_data_new (GList *file_list,
8333 CajaFileListCallback callback,
8334 gpointer callback_data)
8335{
8336 FileListReadyData *data;
8337
8338 data = g_new0 (FileListReadyData, 1)(FileListReadyData *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (FileListReadyData); 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; }))
;
8339 data->file_list = caja_file_list_copy (file_list);
8340 data->remaining_files = g_list_copy (file_list);
8341 data->callback = callback;
8342 data->callback_data = callback_data;
8343
8344 ready_data_list = g_list_prepend (ready_data_list, data);
8345
8346 return data;
8347}
8348
8349static void
8350file_list_file_ready_callback (CajaFile *file,
8351 gpointer user_data)
8352{
8353 FileListReadyData *data;
8354
8355 data = user_data;
8356 data->remaining_files = g_list_remove (data->remaining_files, file);
8357
8358 if (data->remaining_files == NULL((void*)0)) {
8359 if (data->callback) {
8360 (*data->callback) (data->file_list, data->callback_data);
8361 }
8362
8363 file_list_ready_data_free (data);
8364 }
8365}
8366
8367void
8368caja_file_list_call_when_ready (GList *file_list,
8369 CajaFileAttributes attributes,
8370 CajaFileListHandle **handle,
8371 CajaFileListCallback callback,
8372 gpointer callback_data)
8373{
8374 GList *l;
8375 FileListReadyData *data;
8376 CajaFile *file = NULL((void*)0);
8377
8378 g_return_if_fail (file_list != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if (file_list != ((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__)), "file_list != NULL"
); return; } } while (0)
;
8379
8380 data = file_list_ready_data_new
8381 (file_list, callback, callback_data);
8382
8383 if (handle) {
8384 *handle = (CajaFileListHandle *) data;
8385 }
8386
8387
8388 l = file_list;
8389 while (l != NULL((void*)0)) {
8390 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8391 /* Need to do this here, as the list can be modified by this call */
8392 l = l->next;
8393
8394 if (file)
8395 caja_file_call_when_ready (file,
8396 attributes,
8397 file_list_file_ready_callback,
8398 data);
8399 }
8400}
8401
8402void
8403caja_file_list_cancel_call_when_ready (CajaFileListHandle *handle)
8404{
8405 GList *l;
8406 FileListReadyData *data;
8407
8408 g_return_if_fail (handle != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_283
; if (handle != ((void*)0)) _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__)), "handle != NULL")
; return; } } while (0)
;
8409
8410 data = (FileListReadyData *) handle;
8411
8412 l = g_list_find (ready_data_list, data);
8413 if (l != NULL((void*)0)) {
8414 CajaFile *file = NULL((void*)0);
8415
8416 for (l = data->remaining_files; l != NULL((void*)0); l = l->next) {
8417 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
8418
8419 EEL_CALL_METHODdo { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8420 (CAJA_FILE_CLASS, file,do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
8421 cancel_call_when_ready, (file, file_list_file_ready_callback, data))do { if (((((CajaFileClass*) (void *) ((((((GObjectClass*) ((
(GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
!= ((void*)0)) { (* ((((CajaFileClass*) (void *) ((((((GObjectClass
*) (((GTypeInstance*) ((file)))->g_class)))))))))->cancel_call_when_ready
) (file, file_list_file_ready_callback, data); } } while (0)
;
8422 }
8423
8424 file_list_ready_data_free (data);
8425 }
8426}
8427
8428static char *
8429try_to_make_utf8 (const char *text, int *length)
8430{
8431 static const char *encodings_to_try[2];
8432 static int n_encodings_to_try = 0;
8433 gsize converted_length;
8434 GError *conversion_error;
8435 char *utf8_text;
8436 int i;
8437
8438 if (n_encodings_to_try == 0) {
8439 const char *charset;
8440 gboolean charset_is_utf8;
8441
8442 charset_is_utf8 = g_get_charset (&charset);
8443 if (!charset_is_utf8) {
8444 encodings_to_try[n_encodings_to_try++] = charset;
8445 }
8446
8447 if (g_ascii_strcasecmp (charset, "ISO-8859-1") != 0) {
8448 encodings_to_try[n_encodings_to_try++] = "ISO-8859-1";
8449 }
8450 }
8451
8452 utf8_text = NULL((void*)0);
8453 for (i = 0; i < n_encodings_to_try; i++) {
8454 conversion_error = NULL((void*)0);
8455 utf8_text = g_convert (text, *length,
8456 "UTF-8", encodings_to_try[i],
8457 NULL((void*)0), &converted_length, &conversion_error);
8458 if (utf8_text != NULL((void*)0)) {
8459 *length = converted_length;
8460 break;
8461 }
8462 g_error_free (conversion_error);
8463 }
8464
8465 return utf8_text;
8466}
8467
8468
8469
8470/* Extract the top left part of the read-in text. */
8471char *
8472caja_extract_top_left_text (const char *text,
8473 gboolean large,
8474 int length)
8475{
8476 GString* buffer;
8477 const gchar *in;
8478 const gchar *end;
8479 int line, i;
8480 gunichar c;
8481 char *text_copy;
8482 const char *utf8_end;
8483 gboolean validated;
8484 int max_bytes, max_lines, max_cols;
8485
8486 if (large) {
8487 max_bytes = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES10000;
8488 max_lines = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES24;
8489 max_cols = CAJA_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE80;
8490 } else {
8491 max_bytes = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES1024;
8492 max_lines = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES5;
8493 max_cols = CAJA_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE10;
8494 }
8495
8496
8497
8498 text_copy = NULL((void*)0);
8499 if (text != NULL((void*)0)) {
8500 /* Might be a partial utf8 character at the end if we didn't read whole file */
8501 validated = g_utf8_validate (text, length, &utf8_end);
8502 if (!validated &&
8503 !(length >= max_bytes &&
8504 text + length - utf8_end < 6)) {
8505 text_copy = try_to_make_utf8 (text, &length);
8506 text = text_copy;
8507 } else if (!validated) {
8508 length = utf8_end - text;
8509 }
8510 }
8511
8512 if (text == NULL((void*)0) || length == 0) {
8513 return NULL((void*)0);
8514 }
8515
8516 buffer = g_string_new ("");
8517 end = text + length; in = text;
8518
8519 for (line = 0; line < max_lines; line++) {
8520 /* Extract one line. */
8521 for (i = 0; i < max_cols; ) {
8522 if (*in == '\n') {
8523 break;
8524 }
8525
8526 c = g_utf8_get_char (in);
8527
8528 if (g_unichar_isprint (c)) {
8529 g_string_append_unichar (buffer, c);
8530 i++;
8531 }
8532
8533 in = g_utf8_next_char (in)(char *)((in) + g_utf8_skip[*(const guchar *)(in)]);
8534 if (in == end) {
8535 goto done;
8536 }
8537 }
8538
8539 /* Skip the rest of the line. */
8540 while (*in != '\n') {
8541 if (++in == end) {
8542 goto done;
8543 }
8544 }
8545 if (++in == end) {
8546 goto done;
8547 }
8548
8549 /* Put a new-line separator in. */
8550 g_string_append_c(buffer, '\n')g_string_append_c_inline (buffer, '\n');
8551 }
8552 done:
8553 g_free (text_copy);
8554
8555 return g_string_free(buffer, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((buffer
), ((0))) : g_string_free_and_steal (buffer)) : (g_string_free
) ((buffer), ((0))))
;
8556}
8557
8558static void
8559thumbnail_limit_changed_callback (gpointer user_data)
8560{
8561 g_settings_get (caja_preferences,
8562 CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT"thumbnail-limit",
8563 "t", &cached_thumbnail_limit);
8564
8565 /* Tell the world that icons might have changed. We could invent a narrower-scope
8566 * signal to mean only "thumbnails might have changed" if this ends up being slow
8567 * for some reason.
8568 */
8569 emit_change_signals_for_all_files_in_all_directories ();
8570}
8571
8572static void
8573thumbnail_size_changed_callback (gpointer user_data)
8574{
8575 cached_thumbnail_size = g_settings_get_int (caja_icon_view_preferences, CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE"thumbnail-size");
8576
8577 /* Tell the world that icons might have changed. We could invent a narrower-scope
8578 * signal to mean only "thumbnails might have changed" if this ends up being slow
8579 * for some reason.
8580 */
8581 emit_change_signals_for_all_files_in_all_directories ();
8582}
8583
8584static void
8585show_thumbnails_changed_callback (gpointer user_data)
8586{
8587 show_image_thumbs = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS"show-image-thumbnails");
8588
8589 /* Tell the world that icons might have changed. We could invent a narrower-scope
8590 * signal to mean only "thumbnails might have changed" if this ends up being slow
8591 * for some reason.
8592 */
8593 emit_change_signals_for_all_files_in_all_directories ();
8594}
8595
8596static void
8597mime_type_data_changed_callback (GObject *signaller, gpointer user_data)
8598{
8599 /* Tell the world that icons might have changed. We could invent a narrower-scope
8600 * signal to mean only "thumbnails might have changed" if this ends up being slow
8601 * for some reason.
8602 */
8603 emit_change_signals_for_all_files_in_all_directories ();
8604}
8605
8606static void
8607icon_theme_changed_callback (GtkIconTheme *icon_theme,
8608 gpointer user_data)
8609{
8610 /* Clear all pixmap caches as the icon => pixmap lookup changed */
8611 caja_icon_info_clear_caches ();
8612
8613 /* Tell the world that icons might have changed. We could invent a narrower-scope
8614 * signal to mean only "thumbnails might have changed" if this ends up being slow
8615 * for some reason.
8616 */
8617 emit_change_signals_for_all_files_in_all_directories ();
8618}
8619
8620static void
8621caja_file_class_init (CajaFileClass *class)
8622{
8623 GtkIconTheme *icon_theme;
8624
8625 caja_file_info_getter = caja_file_get_internal;
8626
8627 attribute_name_q = g_quark_from_static_string ("name");
8628 attribute_size_q = g_quark_from_static_string ("size");
8629 attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
8630 attribute_type_q = g_quark_from_static_string ("type");
8631 attribute_modification_date_q = g_quark_from_static_string ("modification_date");
8632 attribute_date_modified_q = g_quark_from_static_string ("date_modified");
8633 attribute_creation_date_q = g_quark_from_static_string ("creation_date");
8634 attribute_date_created_q = g_quark_from_static_string ("date_created");
8635 attribute_accessed_date_q = g_quark_from_static_string ("accessed_date");
8636 attribute_date_accessed_q = g_quark_from_static_string ("date_accessed");
8637 attribute_emblems_q = g_quark_from_static_string ("emblems");
8638 attribute_extension_q = g_quark_from_static_string ("extension");
8639 attribute_mime_type_q = g_quark_from_static_string ("mime_type");
8640 attribute_size_detail_q = g_quark_from_static_string ("size_detail");
8641 attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
8642 attribute_deep_size_q = g_quark_from_static_string ("deep_size");
8643 attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
8644 attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
8645 attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
8646 attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");
8647 attribute_date_changed_q = g_quark_from_static_string ("date_changed");
8648 attribute_trashed_on_q = g_quark_from_static_string ("trashed_on");
8649 attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path");
8650 attribute_date_permissions_q = g_quark_from_static_string ("date_permissions");
8651 attribute_permissions_q = g_quark_from_static_string ("permissions");
8652 attribute_selinux_context_q = g_quark_from_static_string ("selinux_context");
8653 attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions");
8654 attribute_owner_q = g_quark_from_static_string ("owner");
8655 attribute_group_q = g_quark_from_static_string ("group");
8656 attribute_uri_q = g_quark_from_static_string ("uri");
8657 attribute_where_q = g_quark_from_static_string ("where");
8658 attribute_link_target_q = g_quark_from_static_string ("link_target");
8659 attribute_volume_q = g_quark_from_static_string ("volume");
8660 attribute_free_space_q = g_quark_from_static_string ("free_space");
8661
8662 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = finalize;
8663 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->constructor = caja_file_constructor;
8664
8665 signals[CHANGED] =
8666 g_signal_new ("changed",
8667 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8668 G_SIGNAL_RUN_LAST,
8669 G_STRUCT_OFFSET (CajaFileClass, changed)((glong) __builtin_offsetof(CajaFileClass, changed)),
8670 NULL((void*)0), NULL((void*)0),
8671 g_cclosure_marshal_VOID__VOID,
8672 G_TYPE_NONE((GType) ((1) << (2))), 0);
8673
8674 signals[UPDATED_DEEP_COUNT_IN_PROGRESS] =
8675 g_signal_new ("updated_deep_count_in_progress",
8676 G_TYPE_FROM_CLASS (class)(((GTypeClass*) (class))->g_type),
8677 G_SIGNAL_RUN_LAST,
8678 G_STRUCT_OFFSET (CajaFileClass, updated_deep_count_in_progress)((glong) __builtin_offsetof(CajaFileClass, updated_deep_count_in_progress
))
,
8679 NULL((void*)0), NULL((void*)0),
8680 g_cclosure_marshal_VOID__VOID,
8681 G_TYPE_NONE((GType) ((1) << (2))), 0);
8682
8683 eel_g_settings_add_auto_enum (caja_preferences,
8684 CAJA_PREFERENCES_DATE_FORMAT"date-format",
8685 &date_format_pref);
8686
8687 thumbnail_limit_changed_callback (NULL((void*)0));
8688 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8689 "changed::" CAJA_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT,g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8690 G_CALLBACK (thumbnail_limit_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8691 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "thumbnail-limit"
), (((GCallback) (thumbnail_limit_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8692 thumbnail_size_changed_callback (NULL((void*)0));
8693 g_signal_connect_swapped (caja_icon_view_preferences,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8694 "changed::" CAJA_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE,g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8695 G_CALLBACK (thumbnail_size_changed_callback),g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
8696 NULL)g_signal_connect_data ((caja_icon_view_preferences), ("changed::"
"thumbnail-size"), (((GCallback) (thumbnail_size_changed_callback
))), (((void*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8697 show_thumbnails_changed_callback (NULL((void*)0));
8698 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8699 "changed::" CAJA_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8700 G_CALLBACK (show_thumbnails_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
8701 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "show-image-thumbnails"
), (((GCallback) (show_thumbnails_changed_callback))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
8702
8703 icon_theme = gtk_icon_theme_get_default ();
8704 g_signal_connect_object (icon_theme,
8705 "changed",
8706 G_CALLBACK (icon_theme_changed_callback)((GCallback) (icon_theme_changed_callback)),
8707 NULL((void*)0), 0);
8708
8709 g_signal_connect (caja_signaller_get_current (),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8710 "mime_data_changed",g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8711 G_CALLBACK (mime_type_data_changed_callback),g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
8712 NULL)g_signal_connect_data ((caja_signaller_get_current ()), ("mime_data_changed"
), (((GCallback) (mime_type_data_changed_callback))), (((void
*)0)), ((void*)0), (GConnectFlags) 0)
;
8713}
8714
8715static void
8716caja_file_add_emblem (CajaFile *file,
8717 const char *emblem_name)
8718{
8719 if (file->details->pending_info_providers) {
8720 file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems,
8721 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8722 } else {
8723 file->details->extension_emblems = g_list_prepend (file->details->extension_emblems,
8724 g_strdup (emblem_name)g_strdup_inline (emblem_name));
8725 }
8726
8727 caja_file_changed (file);
8728}
8729
8730static void
8731caja_file_add_string_attribute (CajaFile *file,
8732 const char *attribute_name,
8733 const char *value)
8734{
8735 if (file->details->pending_info_providers) {
8736 /* Lazily create hashtable */
8737 if (!file->details->pending_extension_attributes) {
8738 file->details->pending_extension_attributes =
8739 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8740 NULL((void*)0),
8741 (GDestroyNotify)g_free);
8742 }
8743 g_hash_table_insert (file->details->pending_extension_attributes,
8744 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8745 g_strdup (value)g_strdup_inline (value));
8746 } else {
8747 if (!file->details->extension_attributes) {
8748 file->details->extension_attributes =
8749 g_hash_table_new_full (g_direct_hash, g_direct_equal,
8750 NULL((void*)0),
8751 (GDestroyNotify)g_free);
8752 }
8753 g_hash_table_insert (file->details->extension_attributes,
8754 GINT_TO_POINTER (g_quark_from_string (attribute_name))((gpointer) (glong) (g_quark_from_string (attribute_name))),
8755 g_strdup (value)g_strdup_inline (value));
8756 }
8757
8758 caja_file_changed (file);
8759}
8760
8761static void
8762caja_file_invalidate_extension_info (CajaFile *file)
8763{
8764 caja_file_invalidate_attributes (file, CAJA_FILE_ATTRIBUTE_EXTENSION_INFO);
8765}
8766
8767void
8768caja_file_info_providers_done (CajaFile *file)
8769{
8770 g_list_free_full (file->details->extension_emblems, g_free);
8771 file->details->extension_emblems = file->details->pending_extension_emblems;
8772 file->details->pending_extension_emblems = NULL((void*)0);
8773
8774 if (file->details->extension_attributes) {
8775 g_hash_table_destroy (file->details->extension_attributes);
8776 }
8777
8778 file->details->extension_attributes = file->details->pending_extension_attributes;
8779 file->details->pending_extension_attributes = NULL((void*)0);
8780
8781 caja_file_changed (file);
8782}
8783
8784static void
8785caja_file_info_iface_init (CajaFileInfoIface *iface)
8786{
8787 iface->is_gone = caja_file_is_gone;
8788 iface->get_name = caja_file_get_name;
8789 iface->get_file_type = caja_file_get_file_type;
8790 iface->get_location = caja_file_get_location;
8791 iface->get_uri = caja_file_get_uri;
8792 iface->get_parent_location = caja_file_get_parent_location;
8793 iface->get_parent_uri = caja_file_get_parent_uri;
8794 iface->get_parent_info = caja_file_get_parent;
8795 iface->get_mount = caja_file_get_mount;
8796 iface->get_uri_scheme = caja_file_get_uri_scheme;
8797 iface->get_activation_uri = caja_file_get_activation_uri;
8798 iface->get_mime_type = caja_file_get_mime_type;
8799 iface->is_mime_type = caja_file_is_mime_type;
8800 iface->is_directory = caja_file_is_directory;
8801 iface->can_write = caja_file_can_write;
8802 iface->add_emblem = caja_file_add_emblem;
8803 iface->get_string_attribute = caja_file_get_string_attribute;
8804 iface->add_string_attribute = caja_file_add_string_attribute;
8805 iface->invalidate_extension_info = caja_file_invalidate_extension_info;
8806}
8807
8808#if !defined (CAJA_OMIT_SELF_CHECK)
8809
8810void
8811caja_self_check_file (void)
8812{
8813 CajaFile *file_1;
8814 CajaFile *file_2;
8815 GList *list;
8816
8817 /* refcount checks */
8818
8819 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8819); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8820
8821 file_1 = caja_file_get_by_uri ("file:///home/");
8822
8823 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8823); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8824 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1->details->directory)))))->ref_count"
, "caja-file.c", 8824); eel_check_integer_result (((((GObject
*) (void *) ((file_1->details->directory)))))->ref_count
, 1); } while (0)
;
8825 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 1)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8825); eel_check_integer_result (caja_directory_number_outstanding
(), 1); } while (0)
;
8826
8827 caja_file_unref (file_1);
8828
8829 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8829); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8830
8831 file_1 = caja_file_get_by_uri ("file:///etc");
8832 file_2 = caja_file_get_by_uri ("file:///usr");
8833
8834 list = NULL((void*)0);
8835 list = g_list_prepend (list, file_1);
8836 list = g_list_prepend (list, file_2);
8837
8838 caja_file_list_ref (list);
8839
8840 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8840); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 2); } while (0)
;
8841 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8841); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 2); } while (0)
;
8842
8843 caja_file_list_unref (list);
8844
8845 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8845); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8846 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8846); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8847
8848 caja_file_list_free (list);
8849
8850 EEL_CHECK_INTEGER_RESULT (caja_directory_number_outstanding (), 0)do { eel_before_check ("caja_directory_number_outstanding ()"
, "caja-file.c", 8850); eel_check_integer_result (caja_directory_number_outstanding
(), 0); } while (0)
;
8851
8852
8853 /* name checks */
8854 file_1 = caja_file_get_by_uri ("file:///home/");
8855
8856 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8856); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8857
8858 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home/") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home/\") == file_1"
, "caja-file.c", 8858); eel_check_boolean_result (caja_file_get_by_uri
("file:///home/") == file_1, (!(0))); } while (0)
;
8859 caja_file_unref (file_1);
8860
8861 EEL_CHECK_BOOLEAN_RESULT (caja_file_get_by_uri ("file:///home") == file_1, TRUE)do { eel_before_check ("caja_file_get_by_uri (\"file:///home\") == file_1"
, "caja-file.c", 8861); eel_check_boolean_result (caja_file_get_by_uri
("file:///home") == file_1, (!(0))); } while (0)
;
8862 caja_file_unref (file_1);
8863
8864 caja_file_unref (file_1);
8865
8866 file_1 = caja_file_get_by_uri ("file:///home");
8867 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "home")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8867); eel_check_string_result (caja_file_get_name (file_1)
, "home"); } while (0)
;
8868 caja_file_unref (file_1);
8869
8870#if 0
8871 /* ALEX: I removed this, because it was breaking distchecks.
8872 * It used to work, but when canonical uris changed from
8873 * foo: to foo:/// it broke. I don't expect it to matter
8874 * in real life */
8875 file_1 = caja_file_get_by_uri (":");
8876 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), ":")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8876); eel_check_string_result (caja_file_get_name (file_1)
, ":"); } while (0)
;
8877 caja_file_unref (file_1);
8878#endif
8879
8880 file_1 = caja_file_get_by_uri ("eazel:");
8881 EEL_CHECK_STRING_RESULT (caja_file_get_name (file_1), "eazel")do { eel_before_check ("caja_file_get_name (file_1)", "caja-file.c"
, 8881); eel_check_string_result (caja_file_get_name (file_1)
, "eazel"); } while (0)
;
8882 caja_file_unref (file_1);
8883
8884 /* sorting */
8885 file_1 = caja_file_get_by_uri ("file:///etc");
8886 file_2 = caja_file_get_by_uri ("file:///usr");
8887
8888 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_1)))))->ref_count"
, "caja-file.c", 8888); eel_check_integer_result (((((GObject
*) (void *) ((file_1)))))->ref_count, 1); } while (0)
;
8889 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1)do { eel_before_check ("((((GObject*) (void *) ((file_2)))))->ref_count"
, "caja-file.c", 8889); eel_check_integer_result (((((GObject
*) (void *) ((file_2)))))->ref_count, 1); } while (0)
;
8890
8891 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) < 0"
, "caja-file.c", 8891); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) <
0, (!(0))); } while (0)
;
8892 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) > 0"
, "caja-file.c", 8892); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_2, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) > 0, (!(0))); } while (0)
;
8893 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) == 0"
, "caja-file.c", 8893); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (0)) ==
0, (!(0))); } while (0)
;
8894 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)) == 0"
, "caja-file.c", 8894); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (0)
) == 0, (!(0))); } while (0)
;
8895 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))) == 0"
, "caja-file.c", 8895); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (0), (!(0))
) == 0, (!(0))); } while (0)
;
8896 EEL_CHECK_BOOLEAN_RESULT (caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE)do { eel_before_check ("caja_file_compare_for_sort (file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(0))) == 0"
, "caja-file.c", 8896); eel_check_boolean_result (caja_file_compare_for_sort
(file_1, file_1, CAJA_FILE_SORT_BY_DISPLAY_NAME, (!(0)), (!(
0))) == 0, (!(0))); } while (0)
;
8897
8898 caja_file_unref (file_1);
8899 caja_file_unref (file_2);
8900}
8901
8902#endif /* !CAJA_OMIT_SELF_CHECK */
diff --git a/2024-07-29-023715-6438-1/report-ca1b2c.html b/2024-07-29-023715-6438-1/report-ca1b2c.html new file mode 100644 index 000000000..0f17ac74b --- /dev/null +++ b/2024-07-29-023715-6438-1/report-ca1b2c.html @@ -0,0 +1,3064 @@ + + + +caja-application.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-application.c
Warning:line 2246, column 5
Value stored to 'exit_with_last_window' 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 caja-application.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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-application.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2
3/*
4 * Caja
5 *
6 * Copyright (C) 1999, 2000 Red Hat, Inc.
7 * Copyright (C) 2000, 2001 Eazel, Inc.
8 *
9 * Caja is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * Caja 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 GNU
17 * 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, Boston, MA 02110-1301, USA.
22 *
23 * Authors: Elliot Lee <sopwith@redhat.com>,
24 * Darin Adler <darin@bentspoon.com>,
25 * Cosimo Cecchi <cosimoc@gnome.org>
26 *
27 */
28
29#include <config.h>
30#include <fcntl.h>
31#include <string.h>
32#include <unistd.h>
33#include <fcntl.h>
34
35#include <libxml/parser.h>
36#include <libxml/xmlsave.h>
37#include <glib/gstdio.h>
38#include <glib/gi18n.h>
39#include <gio/gio.h>
40#include <gdk/gdkx.h>
41#include <gtk/gtk.h>
42#include <libnotify/notify.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#define MATE_DESKTOP_USE_UNSTABLE_API
46#include <libmate-desktop/mate-bg.h>
47
48#include <eel/eel-gtk-extensions.h>
49#include <eel/eel-gtk-macros.h>
50#include <eel/eel-stock-dialogs.h>
51
52#include <libcaja-private/caja-debug-log.h>
53#include <libcaja-private/caja-file-utilities.h>
54#include <libcaja-private/caja-global-preferences.h>
55#include <libcaja-private/caja-lib-self-check-functions.h>
56#include <libcaja-private/caja-extensions.h>
57#include <libcaja-private/caja-module.h>
58#include <libcaja-private/caja-desktop-link-monitor.h>
59#include <libcaja-private/caja-directory-private.h>
60#include <libcaja-private/caja-signaller.h>
61#include <libcaja-extension/caja-menu-provider.h>
62#include <libcaja-private/caja-autorun.h>
63
64#if ENABLE_EMPTY_VIEW1
65#include "file-manager/fm-empty-view.h"
66#endif /* ENABLE_EMPTY_VIEW */
67#include "file-manager/fm-desktop-icon-view.h"
68#include "file-manager/fm-icon-view.h"
69#include "file-manager/fm-list-view.h"
70#include "file-manager/fm-tree-view.h"
71#include "file-manager/fm-widget-view.h"
72
73#include "caja-application.h"
74#include "caja-information-panel.h"
75#include "caja-history-sidebar.h"
76#include "caja-places-sidebar.h"
77#include "caja-self-check-functions.h"
78#include "caja-notes-viewer.h"
79#include "caja-emblem-sidebar.h"
80#include "caja-bookmarks-sidebar.h"
81#include "caja-image-properties-page.h"
82#include "caja-desktop-window.h"
83#include "caja-spatial-window.h"
84#include "caja-navigation-window.h"
85#include "caja-window-slot.h"
86#include "caja-navigation-window-slot.h"
87#include "caja-window-bookmarks.h"
88#include "libcaja-private/caja-file-operations.h"
89#include "caja-window-private.h"
90#include "caja-window-manage-views.h"
91#include "caja-freedesktop-dbus.h"
92
93/* Keep window from shrinking down ridiculously small; numbers are somewhat arbitrary */
94#define APPLICATION_WINDOW_MIN_WIDTH300 300
95#define APPLICATION_WINDOW_MIN_HEIGHT100 100
96
97#define CAJA_ACCEL_MAP_SAVE_DELAY30 30
98
99/* Keeps track of all the desktop windows. */
100static GList *caja_application_desktop_windows;
101
102/* Keeps track of all the object windows */
103static GList *caja_application_spatial_window_list;
104
105/* The saving of the accelerator map was requested */
106static gboolean save_of_accel_map_requested = FALSE(0);
107
108/* File Manager DBus Interface */
109static CajaFreedesktopDBus *fdb_manager = NULL((void*)0);
110
111static char * caja_application_get_session_data (CajaApplication *self);
112void caja_application_quit (CajaApplication *self);
113
114struct _CajaApplicationPrivate {
115 GVolumeMonitor *volume_monitor;
116 gboolean no_desktop;
117 gboolean force_desktop;
118 gboolean autostart;
119 gchar *geometry;
120};
121
122G_DEFINE_TYPE_WITH_PRIVATE (CajaApplication, caja_application, GTK_TYPE_APPLICATION)static void caja_application_init (CajaApplication *self); static
void caja_application_class_init (CajaApplicationClass *klass
); static GType caja_application_get_type_once (void); static
gpointer caja_application_parent_class = ((void*)0); static gint
CajaApplication_private_offset; static void caja_application_class_intern_init
(gpointer klass) { caja_application_parent_class = g_type_class_peek_parent
(klass); if (CajaApplication_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaApplication_private_offset); caja_application_class_init
((CajaApplicationClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer caja_application_get_instance_private
(CajaApplication *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CajaApplication_private_offset)))); } GType caja_application_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_application_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_application_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((gtk_application_get_type ()), g_intern_static_string ("CajaApplication"
), sizeof (CajaApplicationClass), (GClassInitFunc)(void (*)(void
)) caja_application_class_intern_init, sizeof (CajaApplication
), (GInstanceInitFunc)(void (*)(void)) caja_application_init,
(GTypeFlags) 0); { {{ CajaApplication_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CajaApplicationPrivate)); };} } return
g_define_type_id; }
;
123
124static GList *
125caja_application_get_spatial_window_list (void)
126{
127 return caja_application_spatial_window_list;
128}
129
130static void
131startup_volume_mount_cb (GObject *source_object,
132 GAsyncResult *res,
133 gpointer user_data)
134{
135 g_volume_mount_finish (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))), res, NULL((void*)0));
136}
137
138static void
139automount_all_volumes (CajaApplication *application)
140{
141 GList *volumes, *l;
142
143 if (g_settings_get_boolean (caja_media_preferences, CAJA_PREFERENCES_MEDIA_AUTOMOUNT"automount"))
144 {
145 /* automount all mountable volumes at start-up */
146
147 GVolume *volume = NULL((void*)0);
148 GMount *mount = NULL((void*)0);
149
150 volumes = g_volume_monitor_get_volumes (application->priv->volume_monitor);
151
152 for (l = volumes; l != NULL((void*)0); l = l->next)
153 {
154 volume = l->data;
155
156 if (!g_volume_should_automount (volume) ||
157 !g_volume_can_mount (volume))
158 {
159 continue;
160 }
161
162 mount = g_volume_get_mount (volume);
163 if (mount != NULL((void*)0))
164 {
165 g_object_unref (mount);
166 continue;
167 }
168
169 /* pass NULL as GMountOperation to avoid user interaction */
170 g_volume_mount (volume, 0, NULL((void*)0), NULL((void*)0), startup_volume_mount_cb, NULL((void*)0));
171 }
172 g_list_free_full (volumes, g_object_unref);
173 }
174
175}
176
177static void
178smclient_save_state_cb (EggSMClient *client,
179 GKeyFile *state_file,
180 CajaApplication *application)
181{
182 char *data;
183 data = caja_application_get_session_data (application);
184
185 if (data != NULL((void*)0))
186 {
187 g_key_file_set_string (state_file,
188 "Caja",
189 "documents",
190 data);
191 }
192 g_free (data);
193}
194
195static void
196smclient_quit_cb (EggSMClient *client,
197 CajaApplication *application)
198{
199 caja_application_quit (application);
200}
201
202static void
203caja_application_smclient_initialize (CajaApplication *self)
204{
205 g_signal_connect (self->smclient, "save_state",g_signal_connect_data ((self->smclient), ("save_state"), (
((GCallback) (smclient_save_state_cb))), (self), ((void*)0), (
GConnectFlags) 0)
206 G_CALLBACK (smclient_save_state_cb),g_signal_connect_data ((self->smclient), ("save_state"), (
((GCallback) (smclient_save_state_cb))), (self), ((void*)0), (
GConnectFlags) 0)
207 self)g_signal_connect_data ((self->smclient), ("save_state"), (
((GCallback) (smclient_save_state_cb))), (self), ((void*)0), (
GConnectFlags) 0)
;
208 g_signal_connect (self->smclient, "quit",g_signal_connect_data ((self->smclient), ("quit"), (((GCallback
) (smclient_quit_cb))), (self), ((void*)0), (GConnectFlags) 0
)
209 G_CALLBACK (smclient_quit_cb),g_signal_connect_data ((self->smclient), ("quit"), (((GCallback
) (smclient_quit_cb))), (self), ((void*)0), (GConnectFlags) 0
)
210 self)g_signal_connect_data ((self->smclient), ("quit"), (((GCallback
) (smclient_quit_cb))), (self), ((void*)0), (GConnectFlags) 0
)
;
211
212 /* TODO: Should connect to quit_requested and block logout on active transfer? */
213}
214
215static void
216caja_application_smclient_startup (CajaApplication *self)
217{
218 g_assert (self->smclient == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (self->smclient == ((void*)0)) _g_boolean_var_18 = 1;
else _g_boolean_var_18 = 0; _g_boolean_var_18; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-application.c"
, 218, ((const char*) (__func__)), "self->smclient == NULL"
); } while (0)
;
219 self->smclient = egg_sm_client_get ();
220}
221
222static void
223caja_empty_callback_to_ensure_read (CajaApplication *self) {
224/*do nothing, just exist to suppress runtime error*/
225 (void) self;
226}
227
228static void
229open_window (CajaApplication *application,
230 GFile *location,
231 GdkScreen *screen,
232 const char *geometry,
233 gboolean browser_window)
234{
235 CajaApplication *self = CAJA_APPLICATION (application)((((CajaApplication*) (void *) ((application)))));
236 CajaWindow *window;
237 gchar *uri;
238
239 uri = g_file_get_uri (location);
240 g_debug ("Opening new window at uri %s", uri);
241
242 /*monitor the preference to use browser or spatial windows */
243 /*connect before trying to read or this preference won't be read by root or after change*/
244 g_signal_connect_swapped(caja_preferences, "changed::"CAJA_PREFERENCES_ALWAYS_USE_BROWSER,g_signal_connect_data ((caja_preferences), ("changed::""always-use-browser"
), (((GCallback) (caja_empty_callback_to_ensure_read))), (self
), ((void*)0), G_CONNECT_SWAPPED)
245 G_CALLBACK (caja_empty_callback_to_ensure_read),g_signal_connect_data ((caja_preferences), ("changed::""always-use-browser"
), (((GCallback) (caja_empty_callback_to_ensure_read))), (self
), ((void*)0), G_CONNECT_SWAPPED)
246 self)g_signal_connect_data ((caja_preferences), ("changed::""always-use-browser"
), (((GCallback) (caja_empty_callback_to_ensure_read))), (self
), ((void*)0), G_CONNECT_SWAPPED)
;
247
248 if (browser_window ||g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
249 window = caja_application_create_navigation_window (application,
250 screen);
251 } else {
252 window = caja_application_get_spatial_window (application,
253 NULL((void*)0),
254 NULL((void*)0),
255 location,
256 screen,
257 NULL((void*)0));
258 }
259
260 caja_window_go_to (window, location);
261
262 if (geometry != NULL((void*)0) && !gtk_widget_get_visible (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))))) {
263 /* never maximize windows opened from shell if a
264 * custom geometry has been requested. */
265 gtk_window_unmaximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
266 eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
267 geometry,
268 APPLICATION_WINDOW_MIN_WIDTH300,
269 APPLICATION_WINDOW_MIN_HEIGHT100,
270 FALSE(0));
271 }
272
273 g_free (uri);
274}
275
276static void
277open_tabs (CajaApplication *application,
278 GFile **locations,
279 guint n_files,
280 GdkScreen *screen,
281 const char *geometry,
282 gboolean browser_window)
283{
284 CajaApplication *self = CAJA_APPLICATION (application)((((CajaApplication*) (void *) ((application)))));
285 CajaWindow *window;
286 gchar *uri = NULL((void*)0);
287
288 /* monitor the preference to use browser or spatial windows */
289 /* connect before trying to read or this preference won't be read by root or after change */
290 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::""always-use-browser"
), (((GCallback) (caja_empty_callback_to_ensure_read))), (self
), ((void*)0), G_CONNECT_SWAPPED)
291 "changed::"CAJA_PREFERENCES_ALWAYS_USE_BROWSER,g_signal_connect_data ((caja_preferences), ("changed::""always-use-browser"
), (((GCallback) (caja_empty_callback_to_ensure_read))), (self
), ((void*)0), G_CONNECT_SWAPPED)
292 G_CALLBACK (caja_empty_callback_to_ensure_read),g_signal_connect_data ((caja_preferences), ("changed::""always-use-browser"
), (((GCallback) (caja_empty_callback_to_ensure_read))), (self
), ((void*)0), G_CONNECT_SWAPPED)
293 self)g_signal_connect_data ((caja_preferences), ("changed::""always-use-browser"
), (((GCallback) (caja_empty_callback_to_ensure_read))), (self
), ((void*)0), G_CONNECT_SWAPPED)
;
294
295 if (browser_window ||g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
296 window = caja_application_create_navigation_window (application, screen);
297 } else {
298 window = caja_application_get_spatial_window (application,
299 NULL((void*)0),
300 NULL((void*)0),
301 locations[0],
302 screen,
303 NULL((void*)0));
304 }
305
306 /* open all locations */
307 uri = g_file_get_uri (locations[0]);
308 g_debug ("Opening new tab at uri %s\n", uri);
309 caja_window_go_to (window, locations[0]);
310 g_free (uri);
311 for (int i = 1; i< n_files;i++) {
312 /* open tabs in reverse order because each
313 * tab is opened before the previous one */
314 guint tab = n_files-i;
315 uri = g_file_get_uri (locations[tab]);
316 g_debug ("Opening new tab at uri %s\n", uri);
317 caja_window_go_to_tab (window, locations[tab]);
318 g_free (uri);
319 }
320
321 if (geometry != NULL((void*)0) && !gtk_widget_get_visible (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))))) {
322 /* never maximize windows opened from shell if a
323 * custom geometry has been requested. */
324 gtk_window_unmaximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
325 eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
326 geometry,
327 APPLICATION_WINDOW_MIN_WIDTH300,
328 APPLICATION_WINDOW_MIN_HEIGHT100,
329 FALSE(0));
330 }
331}
332
333static void
334open_windows (CajaApplication *application,
335 GFile **files,
336 GdkScreen *screen,
337 const char *geometry,
338 guint n_files,
339 gboolean browser_window,
340 gboolean open_in_tabs)
341{
342 guint i;
343
344 if (files == NULL((void*)0) || files[0] == NULL((void*)0)) {
345 /* Open a window pointing at the default location. */
346 open_window (application, NULL((void*)0), screen, geometry, browser_window);
347 } else {
348 if (open_in_tabs) {
349 /* Open one window with one tab at each requested location */
350 open_tabs (application, files, n_files, screen, geometry, browser_window);
351 } else {
352 /* Open windows at each requested location. */
353 i = 0;
354 while (i < n_files) {
355 open_window (application, files[i], screen, geometry, browser_window);
356 i++ ;
357 }
358 }
359 }
360}
361
362static void
363caja_application_open (GApplication *app,
364 GFile **files,
365 gint n_files,
366 const gchar *options)
367{
368 CajaApplication *self = CAJA_APPLICATION (app)((((CajaApplication*) (void *) ((app)))));
369 gboolean browser_window = FALSE(0);
370 gboolean open_in_tabs = FALSE(0);
371 const gchar *geometry = NULL((void*)0);
372
373 g_debug ("Open called on the GApplication instance; %d files", n_files);
374
375 /* Check if local command line passed --browser, --geometry or --tabs */
376 if (strlen (options) > 0) {
377 gchar** splitedOptions = g_strsplit (options, "=", 3);
378 sscanf (splitedOptions[0], "%d", &browser_window);
379 if (strcmp (splitedOptions[1], "NULL") != 0) {
380 geometry = splitedOptions[1];
381 }
382 sscanf (splitedOptions[2], "%d", &open_in_tabs);
383
384 open_windows (self, files,
385 gdk_screen_get_default (),
386 geometry,
387 n_files,
388 browser_window,
389 open_in_tabs);
390
391 /* Reset this or 3ed and later invocations will use same
392 * geometry even if the user has resized open window */
393 self->priv->geometry = NULL((void*)0);
394 g_strfreev (splitedOptions);
395 }
396 else
397 open_windows (self, files,
398 gdk_screen_get_default (),
399 geometry,
400 n_files,
401 browser_window,
402 open_in_tabs);
403}
404
405void
406caja_application_open_location (CajaApplication *application,
407 GFile *location,
408 GFile *selection,
409 const char *startup_id,
410 const gboolean open_in_tabs)
411{
412 CajaWindow *window;
413 GList *sel_list = NULL((void*)0);
414
415 window = caja_application_create_navigation_window (application, gdk_screen_get_default ());
416
417 if (selection != NULL((void*)0)) {
418 sel_list = g_list_prepend (NULL((void*)0), g_object_ref (selection)((__typeof__ (selection)) (g_object_ref) (selection)));
419 }
420
421 caja_window_slot_open_location_full (caja_window_get_active_slot (window), location,
422 open_in_tabs, CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW,
423 sel_list, NULL((void*)0), NULL((void*)0));
424
425 if (sel_list != NULL((void*)0)) {
426 caja_file_list_free (sel_list);
427 }
428}
429
430void
431caja_application_quit (CajaApplication *self)
432{
433 GApplication *app = G_APPLICATION (self)((((GApplication*) (void *) ((self)))));
434 GList *windows;
435
436 windows = gtk_application_get_windows (GTK_APPLICATION (app)((((GtkApplication*) (void *) ((app))))));
437 g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL((void*)0));
438 /* we have been asked to force quit */
439 g_application_quit (G_APPLICATION (self)((((GApplication*) (void *) ((self))))));
440}
441
442static void
443caja_application_init (CajaApplication *application)
444{
445 GSimpleAction *action;
446 application->priv = caja_application_get_instance_private (application);
447 action = g_simple_action_new ("quit", NULL((void*)0));
448
449 g_action_map_add_action (G_ACTION_MAP (application)((((GActionMap*) (void *) ((application))))), G_ACTION (action)((((GAction*) (void *) ((action))))));
450
451 g_signal_connect_swapped (action, "activate",g_signal_connect_data ((action), ("activate"), (((GCallback) (
caja_application_quit))), (application), ((void*)0), G_CONNECT_SWAPPED
)
452 G_CALLBACK (caja_application_quit), application)g_signal_connect_data ((action), ("activate"), (((GCallback) (
caja_application_quit))), (application), ((void*)0), G_CONNECT_SWAPPED
)
;
453
454 g_object_unref (action);
455}
456
457static void
458caja_application_finalize (GObject *object)
459{
460 CajaApplication *application;
461
462 application = CAJA_APPLICATION (object)((((CajaApplication*) (void *) ((object)))));
463
464 caja_bookmarks_exiting ();
465
466 if (application->volume_monitor)
467 {
468 g_object_unref (application->priv->volume_monitor);
469 application->priv->volume_monitor = NULL((void*)0);
470 }
471
472 g_free (application->priv->geometry);
473
474 if (application->ss_watch_id > 0)
475 {
476 g_bus_unwatch_name (application->ss_watch_id);
477 }
478
479 if (application->volume_queue != NULL((void*)0))
480 {
481 g_list_free_full (application->volume_queue, g_object_unref);
482 application->volume_queue = NULL((void*)0);
483 }
484
485 if (application->automount_idle_id != 0)
486 {
487 g_source_remove (application->automount_idle_id);
488 application->automount_idle_id = 0;
489 }
490
491 if (fdb_manager != NULL((void*)0))
492 {
493 g_object_unref (fdb_manager);
494 fdb_manager = NULL((void*)0);
495 }
496
497 if (application->ss_proxy != NULL((void*)0))
498 {
499 g_object_unref (application->ss_proxy);
500 application->ss_proxy = NULL((void*)0);
501 }
502
503 notify_uninit ();
504
505 G_OBJECT_CLASS (caja_application_parent_class)((((GObjectClass*) (void *) ((caja_application_parent_class))
)))
->finalize (object);
506}
507
508static gboolean
509check_required_directories (CajaApplication *application)
510{
511 char *user_directory;
512 char *desktop_directory;
513 GSList *directories;
514 gboolean ret;
515
516 g_assert (CAJA_IS_APPLICATION (application))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((application)); GType __t = (caja_application_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_assertion_message_expr (((gchar*) 0), "caja-application.c"
, 516, ((const char*) (__func__)), "CAJA_IS_APPLICATION (application)"
); } while (0)
;
517
518 ret = TRUE(!(0));
519
520 user_directory = caja_get_user_directory ();
521 desktop_directory = caja_get_desktop_directory ();
522
523 directories = NULL((void*)0);
524
525 if (!g_file_test (user_directory, G_FILE_TEST_IS_DIR))
526 {
527 directories = g_slist_prepend (directories, user_directory);
528 }
529
530 if (!g_file_test (desktop_directory, G_FILE_TEST_IS_DIR))
531 {
532 directories = g_slist_prepend (directories, desktop_directory);
533 }
534
535 if (directories != NULL((void*)0))
536 {
537 int failed_count;
538 GString *directories_as_string;
539 GSList *l;
540 char *error_string;
541 const char *detail_string;
542 GtkDialog *dialog;
543
544 ret = FALSE(0);
545
546 failed_count = g_slist_length (directories);
547
548 directories_as_string = g_string_new ((const char *)directories->data);
549 for (l = directories->next; l != NULL((void*)0); l = l->next)
550 {
551 g_string_append_printf (directories_as_string, ", %s", (const char *)l->data);
552 }
553
554 if (failed_count == 1)
555 {
556 error_string = g_strdup_printf (_("Caja could not create the required folder \"%s\".")dcgettext (((void*)0), "Caja could not create the required folder \"%s\"."
, 5)
,
557 directories_as_string->str);
558 detail_string = _("Before running Caja, please create the following folder, or "dcgettext (((void*)0), "Before running Caja, please create the following folder, or "
"set permissions such that Caja can create it.", 5)
559 "set permissions such that Caja can create it.")dcgettext (((void*)0), "Before running Caja, please create the following folder, or "
"set permissions such that Caja can create it.", 5)
;
560 }
561 else
562 {
563 error_string = g_strdup_printf (_("Caja could not create the following required folders: "dcgettext (((void*)0), "Caja could not create the following required folders: "
"%s.", 5)
564 "%s.")dcgettext (((void*)0), "Caja could not create the following required folders: "
"%s.", 5)
, directories_as_string->str);
565 detail_string = _("Before running Caja, please create these folders, or "dcgettext (((void*)0), "Before running Caja, please create these folders, or "
"set permissions such that Caja can create them.", 5)
566 "set permissions such that Caja can create them.")dcgettext (((void*)0), "Before running Caja, please create these folders, or "
"set permissions such that Caja can create them.", 5)
;
567 }
568
569 dialog = eel_show_error_dialog (error_string, detail_string, NULL((void*)0));
570 /* We need the main event loop so the user has a chance to see the dialog. */
571
572 gtk_application_add_window (GTK_APPLICATION (application)((((GtkApplication*) (void *) ((application))))),
573 GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))));
574
575 g_string_free (directories_as_string, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(directories_as_string), ((!(0)))) : g_string_free_and_steal (
directories_as_string)) : (g_string_free) ((directories_as_string
), ((!(0)))))
;
576 g_free (error_string);
577 }
578
579 g_slist_free (directories);
580 g_free (user_directory);
581 g_free (desktop_directory);
582
583 return ret;
584}
585
586static void
587menu_provider_items_updated_handler (CajaMenuProvider *provider, GtkWidget* parent_window, gpointer data)
588{
589
590 g_signal_emit_by_name (caja_signaller_get_current (),
591 "popup_menu_changed");
592}
593
594static void
595menu_provider_init_callback (void)
596{
597 GList *providers;
598 GList *l;
599
600 providers = caja_extensions_get_for_type (CAJA_TYPE_MENU_PROVIDER(caja_menu_provider_get_type ()));
601
602 for (l = providers; l != NULL((void*)0); l = l->next)
603 {
604 CajaMenuProvider *provider = CAJA_MENU_PROVIDER (l->data)((((CajaMenuProvider*) (void *) ((l->data)))));
605
606 g_signal_connect_after (G_OBJECT (provider), "items_updated",g_signal_connect_data ((((((GObject*) (void *) ((provider))))
)), ("items_updated"), ((GCallback)menu_provider_items_updated_handler
), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
607 (GCallback)menu_provider_items_updated_handler,g_signal_connect_data ((((((GObject*) (void *) ((provider))))
)), ("items_updated"), ((GCallback)menu_provider_items_updated_handler
), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
608 NULL)g_signal_connect_data ((((((GObject*) (void *) ((provider))))
)), ("items_updated"), ((GCallback)menu_provider_items_updated_handler
), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
;
609 }
610
611 caja_module_extension_list_free (providers);
612}
613
614static gboolean
615automount_all_volumes_idle_cb (gpointer data)
616{
617 CajaApplication *application = CAJA_APPLICATION (data)((((CajaApplication*) (void *) ((data)))));
618
619 automount_all_volumes (application);
620
621 application->automount_idle_id = 0;
622 return FALSE(0);
623}
624
625static void
626selection_get_cb (GtkWidget *widget,
627 GtkSelectionData *selection_data,
628 guint info,
629 guint time)
630{
631 /* No extra targets atm */
632}
633
634static GtkWidget *
635get_desktop_manager_selection (GdkDisplay *display)
636{
637 char selection_name[32];
638 GdkAtom selection_atom;
639 Window selection_owner;
640 GtkWidget *selection_widget;
641
642 g_snprintf (selection_name, sizeof (selection_name), "_NET_DESKTOP_MANAGER_S0");
643 selection_atom = gdk_atom_intern (selection_name, FALSE(0));
644
645 selection_owner = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display)(gdk_x11_display_get_xdisplay (display)),
646 gdk_x11_atom_to_xatom_for_display (display,
647 selection_atom));
648 if (selection_owner != None0L)
649 {
650 return NULL((void*)0);
651 }
652
653 selection_widget = gtk_invisible_new_for_screen (gdk_display_get_default_screen (display));
654 /* We need this for gdk_x11_get_server_time() */
655 gtk_widget_add_events (selection_widget, GDK_PROPERTY_CHANGE_MASK);
656
657 if (gtk_selection_owner_set_for_display (display,
658 selection_widget,
659 selection_atom,
660 gdk_x11_get_server_time (gtk_widget_get_window (selection_widget))))
661 {
662
663 g_signal_connect (selection_widget, "selection_get",g_signal_connect_data ((selection_widget), ("selection_get"),
(((GCallback) (selection_get_cb))), (((void*)0)), ((void*)0)
, (GConnectFlags) 0)
664 G_CALLBACK (selection_get_cb), NULL)g_signal_connect_data ((selection_widget), ("selection_get"),
(((GCallback) (selection_get_cb))), (((void*)0)), ((void*)0)
, (GConnectFlags) 0)
;
665 return selection_widget;
666 }
667
668 gtk_widget_destroy (selection_widget);
669
670 return NULL((void*)0);
671}
672
673static void
674desktop_unrealize_cb (GtkWidget *widget,
675 GtkWidget *selection_widget)
676{
677 gtk_widget_destroy (selection_widget);
678}
679
680static gboolean
681selection_clear_event_cb (GtkWidget *widget,
682 GdkEventSelection *event,
683 CajaDesktopWindow *window)
684{
685 gtk_widget_destroy (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
686
687 caja_application_desktop_windows =
688 g_list_remove (caja_application_desktop_windows, window);
689
690 return TRUE(!(0));
691}
692
693static void
694caja_application_create_desktop_windows (CajaApplication *application)
695{
696 GdkDisplay *display;
697 GtkWidget *selection_widget;
698
699 g_return_if_fail (caja_application_desktop_windows == NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (caja_application_desktop_windows == ((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__)), "caja_application_desktop_windows == NULL"); return
; } } while (0)
;
700 g_return_if_fail (CAJA_IS_APPLICATION (application))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((application)); GType __t = (caja_application_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_21 = 1; else _g_boolean_var_21 = 0; _g_boolean_var_21
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "CAJA_IS_APPLICATION (application)"
); return; } } while (0)
;
701 display = gdk_display_get_default ();
702
703 selection_widget = get_desktop_manager_selection (display);
704
705 if (selection_widget != NULL((void*)0))
706 {
707 CajaDesktopWindow *window;
708
709 window = caja_desktop_window_new (application, gdk_display_get_default_screen (display));
710
711 g_signal_connect (selection_widget, "selection_clear_event",g_signal_connect_data ((selection_widget), ("selection_clear_event"
), (((GCallback) (selection_clear_event_cb))), (window), ((void
*)0), (GConnectFlags) 0)
712 G_CALLBACK (selection_clear_event_cb), window)g_signal_connect_data ((selection_widget), ("selection_clear_event"
), (((GCallback) (selection_clear_event_cb))), (window), ((void
*)0), (GConnectFlags) 0)
;
713
714 g_signal_connect (window, "unrealize",g_signal_connect_data ((window), ("unrealize"), (((GCallback)
(desktop_unrealize_cb))), (selection_widget), ((void*)0), (GConnectFlags
) 0)
715 G_CALLBACK (desktop_unrealize_cb), selection_widget)g_signal_connect_data ((window), ("unrealize"), (((GCallback)
(desktop_unrealize_cb))), (selection_widget), ((void*)0), (GConnectFlags
) 0)
;
716
717 /* We realize it immediately so that the CAJA_DESKTOP_WINDOW_ID
718 property is set so mate-settings-daemon doesn't try to set the
719 background. And we do a gdk_display_flush() to be sure X gets it. */
720 gtk_widget_realize (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
721 gdk_display_flush (display);
722
723 caja_application_desktop_windows =
724 g_list_prepend (caja_application_desktop_windows, window);
725 gtk_application_add_window (GTK_APPLICATION (application)((((GtkApplication*) (void *) ((application))))),
726 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
727 }
728}
729
730static void
731caja_application_open_desktop (CajaApplication *application)
732{
733 if (caja_application_desktop_windows == NULL((void*)0))
734 {
735 caja_application_create_desktop_windows (application);
736 }
737}
738static void
739caja_application_close_desktop (void)
740{
741 if (caja_application_desktop_windows != NULL((void*)0))
742 {
743 g_list_free_full (caja_application_desktop_windows, (GDestroyNotify) gtk_widget_destroy);
744 caja_application_desktop_windows = NULL((void*)0);
745 }
746}
747
748void
749caja_application_close_all_navigation_windows (CajaApplication *self)
750{
751 GList *list_copy;
752 GList *l;
753 list_copy = g_list_copy (gtk_application_get_windows (GTK_APPLICATION (self)((((GtkApplication*) (void *) ((self)))))));
754 /* First hide all window to get the feeling of quick response */
755 for (l = list_copy; l != NULL((void*)0); l = l->next)
756 {
757 CajaWindow *window;
758
759 window = CAJA_WINDOW (l->data)((((CajaWindow*) (void *) ((l->data)))));
760
761 if (CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
)
762 {
763 gtk_widget_hide (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
764 }
765 }
766
767 for (l = list_copy; l != NULL((void*)0); l = l->next)
768 {
769 CajaWindow *window;
770
771 window = CAJA_WINDOW (l->data)((((CajaWindow*) (void *) ((l->data)))));
772
773 if (CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
)
774 {
775 caja_window_close (window);
776 }
777 }
778 g_list_free (list_copy);
779}
780
781static CajaSpatialWindow *
782caja_application_get_existing_spatial_window (GFile *location)
783{
784 GList *l;
785 CajaWindowSlot *slot;
786 GFile *window_location = NULL((void*)0);
787
788 for (l = caja_application_get_spatial_window_list ();
789 l != NULL((void*)0); l = l->next) {
790 slot = CAJA_WINDOW (l->data)((((CajaWindow*) (void *) ((l->data)))))->details->active_pane->active_slot;
791
792 window_location = slot->pending_location;
793
794 if (window_location == NULL((void*)0)) {
795 window_location = slot->location;
796 }
797
798 if (window_location != NULL((void*)0)) {
799 if (g_file_equal (location, window_location)) {
800 return CAJA_SPATIAL_WINDOW (l->data)((((CajaSpatialWindow*) (void *) ((l->data)))));
801 }
802 }
803 }
804
805 return NULL((void*)0);
806}
807
808static CajaSpatialWindow *
809find_parent_spatial_window (CajaSpatialWindow *window)
810{
811 CajaFile *file;
812 CajaFile *parent_file;
813 CajaWindowSlot *slot;
814 GFile *location;
815
816 slot = CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->active_pane->active_slot;
817
818 location = slot->location;
819 if (location == NULL((void*)0))
820 {
821 return NULL((void*)0);
822 }
823 file = caja_file_get (location);
824
825 if (!file)
826 {
827 return NULL((void*)0);
828 }
829
830 parent_file = caja_file_get_parent (file);
831 caja_file_unref (file);
832 while (parent_file)
833 {
834 CajaSpatialWindow *parent_window;
835
836 location = caja_file_get_location (parent_file);
837 parent_window = caja_application_get_existing_spatial_window (location);
838 g_object_unref (location);
839
840 /* Stop at the desktop directory if it's not explicitely opened
841 * in a spatial window of its own.
842 */
843 if (caja_file_is_desktop_directory (parent_file) && !parent_window)
844 {
845 caja_file_unref (parent_file);
846 return NULL((void*)0);
847 }
848
849 if (parent_window)
850 {
851 caja_file_unref (parent_file);
852 return parent_window;
853 }
854 file = parent_file;
855 parent_file = caja_file_get_parent (file);
856 caja_file_unref (file);
857 }
858
859 return NULL((void*)0);
860}
861
862void
863caja_application_close_parent_windows (CajaSpatialWindow *window)
864{
865 CajaSpatialWindow *parent_window;
866 CajaSpatialWindow *new_parent_window;
867
868 g_return_if_fail (CAJA_IS_SPATIAL_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_spatial_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__)), "CAJA_IS_SPATIAL_WINDOW (window)"); return; }
} while (0)
;
869
870 parent_window = find_parent_spatial_window (window);
871
872 while (parent_window)
873 {
874
875 new_parent_window = find_parent_spatial_window (parent_window);
876 caja_window_close (CAJA_WINDOW (parent_window)((((CajaWindow*) (void *) ((parent_window))))));
877 parent_window = new_parent_window;
878 }
879}
880
881void
882caja_application_close_all_spatial_windows (void)
883{
884 GList *list_copy;
885 GList *l;
886
887 list_copy = g_list_copy (caja_application_spatial_window_list);
888 /* First hide all window to get the feeling of quick response */
889 for (l = list_copy; l != NULL((void*)0); l = l->next)
890 {
891 CajaWindow *window;
892
893 window = CAJA_WINDOW (l->data)((((CajaWindow*) (void *) ((l->data)))));
894
895 if (CAJA_IS_SPATIAL_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_spatial_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; }))))
)
896 {
897 gtk_widget_hide (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
898 }
899 }
900
901 for (l = list_copy; l != NULL((void*)0); l = l->next)
902 {
903 CajaWindow *window;
904
905 window = CAJA_WINDOW (l->data)((((CajaWindow*) (void *) ((l->data)))));
906
907 if (CAJA_IS_SPATIAL_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_spatial_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; }))))
)
908 {
909 caja_window_close (window);
910 }
911 }
912 g_list_free (list_copy);
913}
914
915static gboolean
916caja_window_delete_event_callback (GtkWidget *widget,
917 GdkEvent *event,
918 gpointer user_data)
919{
920 CajaWindow *window;
921
922 window = CAJA_WINDOW (widget)((((CajaWindow*) (void *) ((widget)))));
923 caja_window_close (window);
924
925 return TRUE(!(0));
926}
927
928
929static CajaWindow *
930create_window (CajaApplication *application,
931 GType window_type,
932 GdkScreen *screen)
933{
934 CajaWindow *window;
935
936 g_return_val_if_fail (CAJA_IS_APPLICATION (application), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((application)); GType __t = (caja_application_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_23 = 1; else _g_boolean_var_23 = 0; _g_boolean_var_23
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "CAJA_IS_APPLICATION (application)"
); return (((void*)0)); } } while (0)
;
937
938 window = CAJA_WINDOW (gtk_widget_new (window_type,((((CajaWindow*) (void *) ((gtk_widget_new (window_type, "app"
, application, "screen", screen, ((void*)0)))))))
939 "app", application,((((CajaWindow*) (void *) ((gtk_widget_new (window_type, "app"
, application, "screen", screen, ((void*)0)))))))
940 "screen", screen,((((CajaWindow*) (void *) ((gtk_widget_new (window_type, "app"
, application, "screen", screen, ((void*)0)))))))
941 NULL))((((CajaWindow*) (void *) ((gtk_widget_new (window_type, "app"
, application, "screen", screen, ((void*)0)))))))
;
942 g_signal_connect_data (window, "delete_event",
943 G_CALLBACK (caja_window_delete_event_callback)((GCallback) (caja_window_delete_event_callback)), NULL((void*)0), NULL((void*)0),
944 G_CONNECT_AFTER);
945
946 gtk_application_add_window (GTK_APPLICATION (application)((((GtkApplication*) (void *) ((application))))),
947 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
948
949 /* Do not yet show the window. It will be shown later on if it can
950 * successfully display its initial URI. Otherwise it will be destroyed
951 * without ever having seen the light of day.
952 */
953
954 return window;
955}
956
957static void
958spatial_window_destroyed_callback (void *user_data, GObject *window)
959{
960 caja_application_spatial_window_list = g_list_remove (caja_application_spatial_window_list, window);
961
962}
963
964CajaWindow *
965caja_application_get_spatial_window (CajaApplication *application,
966 CajaWindow *requesting_window,
967 const char *startup_id,
968 GFile *location,
969 GdkScreen *screen,
970 gboolean *existing)
971{
972 CajaWindow *window;
973 gchar *uri;
974
975 g_return_val_if_fail (CAJA_IS_APPLICATION (application), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((application)); GType __t = (caja_application_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_24 = 1; else _g_boolean_var_24 = 0; _g_boolean_var_24
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "CAJA_IS_APPLICATION (application)"
); return (((void*)0)); } } while (0)
;
976 window = CAJA_WINDOW((((CajaWindow*) (void *) ((caja_application_get_existing_spatial_window
(location))))))
977 (caja_application_get_existing_spatial_window (location))((((CajaWindow*) (void *) ((caja_application_get_existing_spatial_window
(location))))))
;
978
979 if (window != NULL((void*)0)) {
980 if (existing != NULL((void*)0)) {
981 *existing = TRUE(!(0));
982 }
983
984 return window;
985 }
986
987 if (existing != NULL((void*)0)) {
988 *existing = FALSE(0);
989 }
990 window = create_window (application, CAJA_TYPE_SPATIAL_WINDOWcaja_spatial_window_get_type(), screen);
991
992 if (requesting_window)
993 {
994 /* Center the window over the requesting window by default */
995 int orig_x, orig_y, orig_width, orig_height;
996 int new_x, new_y, new_width, new_height;
997
998 gtk_window_get_position (GTK_WINDOW (requesting_window)((((GtkWindow*) (void *) ((requesting_window))))),
999 &orig_x, &orig_y);
1000 gtk_window_get_size (GTK_WINDOW (requesting_window)((((GtkWindow*) (void *) ((requesting_window))))),
1001 &orig_width, &orig_height);
1002 gtk_window_get_default_size (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
1003 &new_width, &new_height);
1004
1005 new_x = orig_x + (orig_width - new_width) / 2;
1006 new_y = orig_y + (orig_height - new_height) / 2;
1007
1008 if (orig_width - new_width < 10)
1009 {
1010 new_x += 10;
1011 new_y += 10;
1012 }
1013
1014 gtk_window_move (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), new_x, new_y);
1015 }
1016
1017 caja_application_spatial_window_list = g_list_prepend (caja_application_spatial_window_list, window);
1018 g_object_weak_ref (G_OBJECT (window)((((GObject*) (void *) ((window))))),
1019 spatial_window_destroyed_callback, NULL((void*)0));
1020
1021 uri = g_file_get_uri (location);
1022 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1023 "present NEW spatial window=%p: %s",
1024 window, uri);
1025 g_free (uri);
1026
1027 return window;
1028}
1029
1030CajaWindow *
1031caja_application_create_navigation_window (CajaApplication *application,
1032 GdkScreen *screen)
1033{
1034 CajaWindow *window;
1035 char *geometry_string;
1036 gboolean maximized;
1037
1038 g_return_val_if_fail (CAJA_IS_APPLICATION (application), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((application)); GType __t = (caja_application_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_25 = 1; else _g_boolean_var_25 = 0; _g_boolean_var_25
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "CAJA_IS_APPLICATION (application)"
); return (((void*)0)); } } while (0)
;
1039 window = create_window (application, CAJA_TYPE_NAVIGATION_WINDOWcaja_navigation_window_get_type(), screen);
1040
1041 maximized = g_settings_get_boolean (caja_window_state,
1042 CAJA_WINDOW_STATE_MAXIMIZED"maximized");
1043 if (maximized)
1044 {
1045 gtk_window_maximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1046 }
1047 else
1048 {
1049 gtk_window_unmaximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1050 }
1051
1052 geometry_string = g_settings_get_string (caja_window_state,
1053 CAJA_WINDOW_STATE_GEOMETRY"geometry");
1054 if (geometry_string != NULL((void*)0) &&
1055 geometry_string[0] != 0)
1056 {
1057 eel_gtk_window_set_initial_geometry_from_string
1058 (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
1059 geometry_string,
1060 CAJA_NAVIGATION_WINDOW_MIN_WIDTH200,
1061 CAJA_NAVIGATION_WINDOW_MIN_HEIGHT200,
1062 TRUE(!(0)));
1063 }
1064 g_free (geometry_string);
1065
1066 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
1067 "create new navigation window=%p",
1068 window);
1069
1070 return window;
1071}
1072
1073/* callback for showing or hiding the desktop based on the user's preference */
1074static void
1075desktop_changed_callback (gpointer user_data)
1076{
1077 CajaApplication *application;
1078
1079 application = CAJA_APPLICATION (user_data)((((CajaApplication*) (void *) ((user_data)))));
1080 if (g_settings_get_boolean (mate_background_preferences, MATE_BG_KEY_SHOW_DESKTOP"show-desktop-icons"))
1081 {
1082 caja_application_open_desktop (application);
1083 }
1084 else
1085 {
1086 caja_application_close_desktop ();
1087 }
1088}
1089
1090static gboolean
1091window_can_be_closed (CajaWindow *window)
1092{
1093 if (!CAJA_IS_DESKTOP_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_desktop_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; }))))
)
1094 {
1095 return TRUE(!(0));
1096 }
1097
1098 return FALSE(0);
1099}
1100
1101static void
1102check_screen_lock_and_mount (CajaApplication *application,
1103 GVolume *volume)
1104{
1105 if (application->screensaver_active)
1106 {
1107 /* queue the volume, to mount it after the screensaver state changed */
1108 g_debug ("Queuing volume %p", volume);
1109 application->volume_queue = g_list_prepend (application->volume_queue,
1110 g_object_ref (volume)((__typeof__ (volume)) (g_object_ref) (volume)));
1111 } else {
1112 /* mount it immediately */
1113 caja_file_operations_mount_volume (NULL((void*)0), volume, TRUE(!(0)));
1114 }
1115}
1116
1117static void
1118volume_removed_callback (GVolumeMonitor *monitor,
1119 GVolume *volume,
1120 CajaApplication *application)
1121{
1122 g_debug ("Volume %p removed, removing from the queue", volume);
1123
1124 /* clear it from the queue, if present */
1125 application->volume_queue =
1126 g_list_remove (application->volume_queue, volume);
1127}
1128
1129static void
1130volume_added_callback (GVolumeMonitor *monitor,
1131 GVolume *volume,
1132 CajaApplication *application)
1133{
1134 if (g_settings_get_boolean (caja_media_preferences, CAJA_PREFERENCES_MEDIA_AUTOMOUNT"automount") &&
1135 g_volume_should_automount (volume) &&
1136 g_volume_can_mount (volume))
1137 {
1138 check_screen_lock_and_mount (application, volume);
1139 }
1140 else
1141 {
1142 /* Allow caja_autorun() to run. When the mount is later
1143 * added programmatically (i.e. for a blank CD),
1144 * caja_autorun() will be called by mount_added_callback(). */
1145 caja_allow_autorun_for_volume (volume);
1146 caja_allow_autorun_for_volume_finish (volume);
1147 }
1148}
1149
1150static void
1151drive_eject_cb (GObject *source_object,
1152 GAsyncResult *res,
1153 gpointer user_data)
1154{
1155 GError *error;
1156 error = NULL((void*)0);
1157
1158 if (!g_drive_eject_with_operation_finish (G_DRIVE (source_object)((((GDrive*) (void *) ((source_object))))), res, &error))
1159 {
1160 if (error->code != G_IO_ERROR_FAILED_HANDLED)
1161 {
1162 char *primary;
1163 char *name;
1164
1165 name = g_drive_get_name (G_DRIVE (source_object)((((GDrive*) (void *) ((source_object))))));
1166 primary = g_strdup_printf (_("Unable to eject %s")dcgettext (((void*)0), "Unable to eject %s", 5), name);
1167 g_free (name);
1168 eel_show_error_dialog (primary,
1169 error->message,
1170 NULL((void*)0));
1171 g_free (primary);
1172 }
1173 g_error_free (error);
1174 }
1175}
1176
1177static void
1178drive_eject_button_pressed (GDrive *drive,
1179 CajaApplication *application)
1180{
1181 GMountOperation *mount_op;
1182
1183 mount_op = gtk_mount_operation_new (NULL((void*)0));
1184 g_drive_eject_with_operation (drive, 0, mount_op, NULL((void*)0), drive_eject_cb, NULL((void*)0));
1185 g_object_unref (mount_op);
1186}
1187
1188static void
1189drive_listen_for_eject_button (GDrive *drive, CajaApplication *application)
1190{
1191 g_signal_connect (drive,g_signal_connect_data ((drive), ("eject-button"), (((GCallback
) (drive_eject_button_pressed))), (application), ((void*)0), (
GConnectFlags) 0)
1192 "eject-button",g_signal_connect_data ((drive), ("eject-button"), (((GCallback
) (drive_eject_button_pressed))), (application), ((void*)0), (
GConnectFlags) 0)
1193 G_CALLBACK (drive_eject_button_pressed),g_signal_connect_data ((drive), ("eject-button"), (((GCallback
) (drive_eject_button_pressed))), (application), ((void*)0), (
GConnectFlags) 0)
1194 application)g_signal_connect_data ((drive), ("eject-button"), (((GCallback
) (drive_eject_button_pressed))), (application), ((void*)0), (
GConnectFlags) 0)
;
1195}
1196
1197static void
1198drive_connected_callback (GVolumeMonitor *monitor,
1199 GDrive *drive,
1200 CajaApplication *application)
1201{
1202 drive_listen_for_eject_button (drive, application);
1203}
1204
1205static void
1206autorun_show_window (GMount *mount, gpointer user_data)
1207{
1208 GFile *location;
1209 CajaApplication *application = user_data;
1210 CajaWindow *window;
1211
1212 location = g_mount_get_root (mount);
1213
1214 /* There should probably be an easier way to do this */
1215 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser")) {
1216 window = caja_application_create_navigation_window (application,
1217 gdk_screen_get_default ());
1218 }
1219 else
1220 {
1221 window = caja_application_get_spatial_window (application,
1222 NULL((void*)0),
1223 NULL((void*)0),
1224 location,
1225 gdk_screen_get_default (),
1226 NULL((void*)0));
1227 }
1228
1229 caja_window_go_to (window, location);
1230
1231 g_object_unref (location);
1232}
1233
1234static void
1235mount_added_callback (GVolumeMonitor *monitor,
1236 GMount *mount,
1237 CajaApplication *application)
1238{
1239 CajaDirectory *directory;
1240 GFile *root;
1241 gchar *uri;
1242
1243 root = g_mount_get_root (mount);
1244 uri = g_file_get_uri (root);
1245
1246 g_debug ("Added mount at uri %s", uri);
1247 g_free (uri);
1248
1249 directory = caja_directory_get_existing (root);
1250 g_object_unref (root);
1251 if (directory != NULL((void*)0)) {
1252 caja_directory_force_reload (directory);
1253 caja_directory_unref (directory);
1254 }
1255 caja_autorun (mount, autorun_show_window, application);
1256}
1257
1258static CajaWindowSlot *
1259get_first_navigation_slot (GList *slot_list)
1260{
1261 GList *l;
1262
1263 for (l = slot_list; l != NULL((void*)0); l = l->next)
1264 {
1265 if (CAJA_IS_NAVIGATION_WINDOW_SLOT (l->data)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(l->data)); GType __t = ((caja_navigation_window_slot_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; }))))
)
1266 {
1267 return l->data;
1268 }
1269 }
1270
1271 return NULL((void*)0);
1272}
1273
1274/* We redirect some slots and close others */
1275static gboolean
1276should_close_slot_with_mount (CajaWindow *window,
1277 CajaWindowSlot *slot,
1278 GMount *mount)
1279{
1280 if (CAJA_IS_SPATIAL_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_spatial_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; }))))
)
1281 {
1282 return TRUE(!(0));
1283 }
1284 return caja_navigation_window_slot_should_close_with_mount (CAJA_NAVIGATION_WINDOW_SLOT (slot)((((CajaNavigationWindowSlot*) (void *) ((slot))))),
1285 mount);
1286}
1287
1288/* Called whenever a mount is unmounted. Check and see if there are
1289 * any windows open displaying contents on the mount. If there are,
1290 * close them. It would also be cool to save open window and position
1291 * info.
1292 *
1293 * This is also called on pre_unmount.
1294 */
1295static void
1296mount_removed_callback (GVolumeMonitor *monitor,
1297 GMount *mount,
1298 CajaApplication *application)
1299{
1300 GList *window_list, *node, *close_list;
1301 CajaWindow *window;
1302 CajaWindowSlot *slot;
1303 CajaWindowSlot *force_no_close_slot;
1304 GFile *root, *computer;
1305 gboolean unclosed_slot;
1306
1307 close_list = NULL((void*)0);
1308 force_no_close_slot = NULL((void*)0);
1309 unclosed_slot = FALSE(0);
1310
1311 /* Check and see if any of the open windows are displaying contents from the unmounted mount */
1312 window_list = gtk_application_get_windows (GTK_APPLICATION (application)((((GtkApplication*) (void *) ((application))))));
1313 root = g_mount_get_root (mount);
1314 /* Construct a list of windows to be closed. Do not add the non-closable windows to the list. */
1315 for (node = window_list; node != NULL((void*)0); node = node->next)
1316 {
1317 window = CAJA_WINDOW (node->data)((((CajaWindow*) (void *) ((node->data)))));
1318 if (window != NULL((void*)0) && window_can_be_closed (window))
1319 {
1320 GList *l;
1321 GList *lp;
1322 GFile *location;
1323
1324 for (lp = window->details->panes; lp != NULL((void*)0); lp = lp->next)
1325 {
1326 CajaWindowPane *pane;
1327 pane = (CajaWindowPane*) lp->data;
1328 for (l = pane->slots; l != NULL((void*)0); l = l->next)
1329 {
1330 slot = l->data;
1331 location = slot->location;
1332 if (g_file_has_prefix (location, root) ||
1333 g_file_equal (location, root))
1334 {
1335 close_list = g_list_prepend (close_list, slot);
1336
1337 if (!should_close_slot_with_mount (window, slot, mount))
1338 {
1339 /* We'll be redirecting this, not closing */
1340 unclosed_slot = TRUE(!(0));
1341 }
1342 }
1343 else
1344 {
1345 unclosed_slot = TRUE(!(0));
1346 }
1347 } /* for all slots */
1348 } /* for all panes */
1349 }
1350 }
1351
1352 if (caja_application_desktop_windows == NULL((void*)0) &&
1353 !unclosed_slot)
1354 {
1355 /* We are trying to close all open slots. Keep one navigation slot open. */
1356 force_no_close_slot = get_first_navigation_slot (close_list);
1357 }
1358
1359 /* Handle the windows in the close list. */
1360 for (node = close_list; node != NULL((void*)0); node = node->next)
1361 {
1362 slot = node->data;
1363 window = slot->pane->window;
1364
1365 if (should_close_slot_with_mount (window, slot, mount) &&
1366 slot != force_no_close_slot)
1367 {
1368 caja_window_slot_close (slot);
1369 }
1370 else
1371 {
1372 computer = g_file_new_for_uri ("computer:///");
1373 caja_window_slot_go_to (slot, computer, FALSE)caja_window_slot_open_location_full(slot, computer, CAJA_WINDOW_OPEN_ACCORDING_TO_MODE
, ((0) ? CAJA_WINDOW_OPEN_FLAG_NEW_TAB : 0), ((void*)0), ((void
*)0), ((void*)0))
;
1374 g_object_unref(computer);
1375 }
1376 }
1377
1378 g_list_free (close_list);
1379}
1380
1381static char *
1382caja_application_get_session_data (CajaApplication *self)
1383{
1384 xmlDocPtr doc;
1385 xmlNodePtr root_node, history_node;
1386 GList *l, *window_list;
1387
1388 char *data;
1389 unsigned n_processed;
1390 xmlSaveCtxtPtr ctx;
1391 xmlBufferPtr buffer;
1392
1393 doc = xmlNewDoc ((const xmlChar *) "1.0");
1394
1395 root_node = xmlNewNode (NULL((void*)0), (const xmlChar *) "session");
1396 xmlDocSetRootElement (doc, root_node);
1397
1398 history_node = xmlNewChild (root_node, NULL((void*)0), (const xmlChar *) "history", NULL((void*)0));
1399
1400 n_processed = 0;
1401 for (l = caja_get_history_list (); l != NULL((void*)0); l = l->next) {
1402 CajaBookmark *bookmark;
1403 xmlNodePtr bookmark_node;
1404 GIcon *icon;
1405 char *tmp;
1406
1407 bookmark = l->data;
1408
1409 bookmark_node = xmlNewChild (history_node, NULL((void*)0), (const xmlChar *) "bookmark", NULL((void*)0));
1410
1411 tmp = caja_bookmark_get_name (bookmark);
1412 xmlNewProp (bookmark_node, (const xmlChar *) "name", (const xmlChar *) tmp);
1413 g_free (tmp);
1414
1415 icon = caja_bookmark_get_icon (bookmark);
1416
1417 tmp = g_icon_to_string (icon);
1418 g_object_unref (icon);
1419 if (tmp) {
1420 xmlNewProp (bookmark_node, (const xmlChar *) "icon", (const xmlChar *) tmp);
1421 g_free (tmp);
1422 }
1423
1424 tmp = caja_bookmark_get_uri (bookmark);
1425 xmlNewProp (bookmark_node, (const xmlChar *) "uri", (const xmlChar *) tmp);
1426 g_free (tmp);
1427
1428 if (caja_bookmark_get_has_custom_name (bookmark)) {
1429 xmlNewProp (bookmark_node, (const xmlChar *) "has_custom_name", (const xmlChar *) "TRUE");
1430 }
1431
1432 if (++n_processed > 50) { /* prevent history list from growing arbitrarily large. */
1433 break;
1434 }
1435 }
1436 window_list = gtk_application_get_windows (GTK_APPLICATION (self)((((GtkApplication*) (void *) ((self))))));
1437 for (l = window_list; l != NULL((void*)0); l = l->next) {
1438 xmlNodePtr win_node, slot_node;
1439 CajaWindow *window;
1440 GList *slots, *m;
1441 char *tmp;
1442 CajaWindowSlot *active_slot;
1443 CajaWindowSlot *slot = NULL((void*)0);
1444
1445 window = l->data;
1446
1447 slots = caja_window_get_slots (window);
1448 active_slot = caja_window_get_active_slot (window);
1449
1450 /* store one slot as window location. Otherwise
1451 * older Caja versions will bail when reading the file. */
1452 tmp = caja_window_slot_get_location_uri (active_slot);
1453
1454 if (eel_uri_is_desktop (tmp)) {
1455 g_list_free (slots);
1456 g_free (tmp);
1457 continue;
1458 }
1459
1460 win_node = xmlNewChild (root_node, NULL((void*)0), (const xmlChar *) "window", NULL((void*)0));
1461
1462 xmlNewProp (win_node, (const xmlChar *) "location", (const xmlChar *) tmp);
1463 g_free (tmp);
1464
1465 xmlNewProp (win_node, (const xmlChar *) "type", CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
? (const xmlChar *) "navigation" : (const xmlChar *) "spatial");
1466
1467 if (CAJA_IS_NAVIGATION_WINDOW (window)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window)); GType __t = (caja_navigation_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; }))))
) { /* spatial windows store their state as file metadata */
1468 GdkWindow *gdk_window;
1469
1470 tmp = eel_gtk_window_get_geometry_string (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1471 xmlNewProp (win_node, (const xmlChar *) "geometry", (const xmlChar *) tmp);
1472 g_free (tmp);
1473
1474 gdk_window = gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
1475
1476 if (gdk_window &&
1477 gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_MAXIMIZED) {
1478 xmlNewProp (win_node, (const xmlChar *) "maximized", (const xmlChar *) "TRUE");
1479 }
1480
1481 if (gdk_window &&
1482 gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_STICKY) {
1483 xmlNewProp (win_node, (const xmlChar *) "sticky", (const xmlChar *) "TRUE");
1484 }
1485
1486 if (gdk_window &&
1487 gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_ABOVE) {
1488 xmlNewProp (win_node, (const xmlChar *) "keep-above", (const xmlChar *) "TRUE");
1489 }
1490 }
1491
1492 for (m = slots; m != NULL((void*)0); m = m->next) {
1493 slot = CAJA_WINDOW_SLOT (m->data)((((CajaWindowSlot*) (void *) ((m->data)))));
1494
1495 slot_node = xmlNewChild (win_node, NULL((void*)0), (const xmlChar *) "slot", NULL((void*)0));
1496
1497 tmp = caja_window_slot_get_location_uri (slot);
1498 xmlNewProp (slot_node, (const xmlChar *) "location", (const xmlChar *) tmp);
1499 g_free (tmp);
1500
1501 if (slot == active_slot) {
1502 xmlNewProp (slot_node, (const xmlChar *) "active", (const xmlChar *) "TRUE");
1503 }
1504 }
1505
1506 g_list_free (slots);
1507 }
1508
1509 buffer = xmlBufferCreate ();
1510 xmlIndentTreeOutput(*__xmlIndentTreeOutput()) = 1;
1511 ctx = xmlSaveToBuffer (buffer, "UTF-8", XML_SAVE_FORMAT);
1512 if (xmlSaveDoc (ctx, doc) < 0 ||
1513 xmlSaveFlush (ctx) < 0) {
1514 g_message ("failed to save session");
1515 }
1516
1517 xmlSaveClose(ctx);
1518 data = g_strndup ((const char *) buffer->content, buffer->use);
1519 xmlBufferFree (buffer);
1520
1521 xmlFreeDoc (doc);
1522
1523 return data;
1524}
1525
1526static void
1527caja_application_load_session (CajaApplication *application)
1528
1529{
1530 xmlDocPtr doc;
1531 gboolean bail;
1532 xmlNodePtr root_node;
1533 GKeyFile *state_file;
1534 char *data;
1535 caja_application_smclient_initialize (application);
1536 if (!egg_sm_client_is_resumed (application->smclient))
1537 {
1538 return;
1539 }
1540
1541 state_file = egg_sm_client_get_state_file (application->smclient);
1542 if (!state_file)
1543 {
1544 return;
1545 }
1546
1547 data = g_key_file_get_string (state_file,
1548 "Caja",
1549 "documents",
1550 NULL((void*)0));
1551 if (data == NULL((void*)0))
1552 {
1553 return;
1554 }
1555
1556 bail = TRUE(!(0));
1557
1558 doc = xmlReadMemory (data, strlen (data), NULL((void*)0), "UTF-8", 0);
1559 if (doc != NULL((void*)0) && (root_node = xmlDocGetRootElement (doc)) != NULL((void*)0))
1560 {
1561 xmlNodePtr node;
1562
1563 bail = FALSE(0);
1564
1565 for (node = root_node->children; node != NULL((void*)0); node = node->next)
1566 {
1567 if (node->name == NULL((void*)0) || *node->name == '\0' ||
1568 xmlStrcmp (node->name, (const xmlChar *) "text") == 0)
1569 {
1570 continue;
1571 }
1572
1573 if (xmlStrcmp (node->name, (const xmlChar *) "history") == 0)
1574 {
1575 xmlNodePtr bookmark_node;
1576 gboolean emit_change;
1577
1578 emit_change = FALSE(0);
1579
1580 for (bookmark_node = node->children; bookmark_node != NULL((void*)0); bookmark_node = bookmark_node->next)
1581 {
1582 if (bookmark_node->name == NULL((void*)0) || *bookmark_node->name == '\0' ||
1583 xmlStrcmp (bookmark_node->name, (const xmlChar *) "text") == 0)
1584 {
1585 continue;
1586 }
1587
1588 if (xmlStrcmp (bookmark_node->name, (const xmlChar *) "bookmark") == 0)
1589 {
1590 xmlChar *name, *icon_str, *uri;
1591 gboolean has_custom_name;
1592 GIcon *icon;
1593 GFile *location;
1594
1595 uri = xmlGetProp (bookmark_node, (const xmlChar *) "uri");
1596 name = xmlGetProp (bookmark_node, (const xmlChar *) "name");
1597 has_custom_name = xmlHasProp (bookmark_node, (const xmlChar *) "has_custom_name") ? TRUE(!(0)) : FALSE(0);
1598 icon_str = xmlGetProp (bookmark_node, (const xmlChar *) "icon");
1599 icon = NULL((void*)0);
1600 if (icon_str)
1601 {
1602 icon = g_icon_new_for_string ((const char *) icon_str, NULL((void*)0));
1603 }
1604 location = g_file_new_for_uri ((const char *) uri);
1605
1606 emit_change |= caja_add_to_history_list_no_notify (location, (const char *) name, has_custom_name, icon);
1607
1608 g_object_unref (location);
1609
1610 if (icon)
1611 {
1612 g_object_unref (icon);
1613 }
1614 xmlFree (name);
1615 xmlFree (uri);
1616 xmlFree (icon_str);
1617 }
1618 else
1619 {
1620 g_message ("unexpected bookmark node %s while parsing session data", bookmark_node->name);
1621 bail = TRUE(!(0));
1622 continue;
1623 }
1624 }
1625
1626 if (emit_change)
1627 {
1628 caja_send_history_list_changed ();
1629 }
1630 }
1631
1632 else if (xmlStrcmp (node->name, (const xmlChar *) "window") == 0)
1633
1634 {
1635 CajaWindow *window;
1636 xmlChar *type, *location_uri;
1637 xmlNodePtr slot_node;
1638 GFile *location;
1639
1640 type = xmlGetProp (node, (const xmlChar *) "type");
1641 if (type == NULL((void*)0))
1642 {
1643 g_message ("empty type node while parsing session data");
1644 bail = TRUE(!(0));
1645 continue;
1646 }
1647
1648 location_uri = xmlGetProp (node, (const xmlChar *) "location");
1649 if (location_uri == NULL((void*)0))
1650 {
1651 g_message ("empty location node while parsing session data");
1652 bail = TRUE(!(0));
1653 xmlFree (type);
1654 continue;
1655 }
1656
1657 if (xmlStrcmp (type, (const xmlChar *) "navigation") == 0)
1658 {
1659 xmlChar *geometry;
1660 int i;
1661
1662 window = caja_application_create_navigation_window (application, gdk_screen_get_default ());
1663 geometry = xmlGetProp (node, (const xmlChar *) "geometry");
1664 if (geometry != NULL((void*)0) && *geometry != '\0')
1665 {
1666 eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
1667 (const char *) geometry,
1668 CAJA_NAVIGATION_WINDOW_MIN_WIDTH200,
1669 CAJA_NAVIGATION_WINDOW_MIN_HEIGHT200,
1670 FALSE(0));
1671 }
1672 xmlFree (geometry);
1673
1674 if (xmlHasProp (node, (const xmlChar *) "maximized"))
1675 {
1676 gtk_window_maximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1677 }
1678 else
1679 {
1680 gtk_window_unmaximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1681 }
1682
1683 if (xmlHasProp (node, (const xmlChar *) "sticky"))
1684 {
1685 gtk_window_stick (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1686 }
1687 else
1688 {
1689 gtk_window_unstick (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1690 }
1691
1692 if (xmlHasProp (node, (const xmlChar *) "keep-above"))
1693 {
1694 gtk_window_set_keep_above (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), TRUE(!(0)));
1695 }
1696 else
1697 {
1698 gtk_window_set_keep_above (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), FALSE(0));
1699 }
1700
1701 for (i = 0, slot_node = node->children; slot_node != NULL((void*)0); slot_node = slot_node->next)
1702 {
1703 if (slot_node->name && xmlStrcmp (slot_node->name, (const xmlChar *) "slot") == 0)
1704 {
1705 xmlChar *slot_uri;
1706
1707 slot_uri = xmlGetProp (slot_node, (const xmlChar *) "location");
1708 if (slot_uri != NULL((void*)0))
1709 {
1710 CajaWindowSlot *slot;
1711
1712 if (i == 0)
1713 {
1714 slot = window->details->active_pane->active_slot;
1715 }
1716 else
1717 {
1718 slot = caja_window_open_slot (window->details->active_pane, CAJA_WINDOW_OPEN_SLOT_APPEND);
1719 }
1720
1721 location = g_file_new_for_uri ((const char *) slot_uri);
1722 caja_window_slot_open_location (slot, location, FALSE(0));
1723
1724 if (xmlHasProp (slot_node, (const xmlChar *) "active"))
1725 {
1726 caja_window_set_active_slot (slot->pane->window, slot);
1727 }
1728
1729 i++;
1730 }
1731 xmlFree (slot_uri);
1732 }
1733 }
1734
1735 if (i == 0)
1736 {
1737 /* This may be an old session file */
1738 location = g_file_new_for_uri ((const char *) location_uri);
1739 caja_window_slot_open_location (window->details->active_pane->active_slot, location, FALSE(0));
1740 g_object_unref (location);
1741 }
1742 }
1743 else if (xmlStrcmp (type, (const xmlChar *) "spatial") == 0)
1744 {
1745 location = g_file_new_for_uri ((const char *) location_uri);
1746 window = caja_application_get_spatial_window (application, NULL((void*)0), NULL((void*)0),
1747 location, gdk_screen_get_default (),
1748 NULL((void*)0));
1749 caja_window_go_to (window, location);
1750 g_object_unref (location);
1751 }
1752 else
1753 {
1754 g_message ("unknown window type \"%s\" while parsing session data", type);
1755 bail = TRUE(!(0));
1756 }
1757
1758 xmlFree (type);
1759 xmlFree (location_uri);
1760 }
1761 else
1762 {
1763 g_message ("unexpected node %s while parsing session data", node->name);
1764 bail = TRUE(!(0));
1765 continue;
1766 }
1767 }
1768 }
1769
1770 if (doc != NULL((void*)0))
1771 {
1772 xmlFreeDoc (doc);
1773 }
1774
1775 g_free (data);
1776
1777 if (bail)
1778 {
1779 g_message ("failed to load session");
1780 }
1781}
1782
1783static gboolean
1784do_cmdline_sanity_checks (CajaApplication *self,
1785 gboolean perform_self_check,
1786 gboolean version,
1787 gboolean kill_shell,
1788 gboolean select_uris,
1789 gchar **remaining)
1790{
1791 gboolean retval = FALSE(0);
1792
1793 if (perform_self_check && (remaining != NULL((void*)0) || kill_shell)) {
1794 g_printerr ("%s\n",
1795 _("--check cannot be used with other options.")dcgettext (((void*)0), "--check cannot be used with other options."
, 5)
);
1796 goto out;
1797 }
1798
1799 if (kill_shell && remaining != NULL((void*)0)) {
1800 g_printerr ("%s\n",
1801 _("--quit cannot be used with URIs.")dcgettext (((void*)0), "--quit cannot be used with URIs.", 5));
1802 goto out;
1803 }
1804
1805 if (self->priv->geometry != NULL((void*)0) &&
1806 remaining != NULL((void*)0) && remaining[0] != NULL((void*)0) && remaining[1] != NULL((void*)0)) {
1807 g_printerr ("%s\n",
1808 _("--geometry cannot be used with more than one URI.")dcgettext (((void*)0), "--geometry cannot be used with more than one URI."
, 5)
);
1809 goto out;
1810 }
1811
1812 if (select_uris && remaining == NULL((void*)0)) {
1813 g_printerr ("%s\n",
1814 _("--select must be used with at least an URI.")dcgettext (((void*)0), "--select must be used with at least an URI."
, 5)
);
1815 goto out;
1816 }
1817
1818 retval = TRUE(!(0));
1819
1820 out:
1821 return retval;
1822}
1823
1824static void
1825do_perform_self_checks (gint *exit_status)
1826{
1827#ifndef CAJA_OMIT_SELF_CHECK
1828 /* Run the checks (each twice) for caja and libcaja-private. */
1829
1830 caja_run_self_checks ();
1831 caja_run_lib_self_checks ();
1832 eel_exit_if_self_checks_failed ();
1833
1834 caja_run_self_checks ();
1835 caja_run_lib_self_checks ();
1836 eel_exit_if_self_checks_failed ();
1837#endif
1838
1839 *exit_status = EXIT_SUCCESS0;
1840}
1841
1842static void
1843select_items_ready_cb (GObject *source,
1844 GAsyncResult *res,
1845 gpointer user_data)
1846{
1847 GDBusConnection *connection = G_DBUS_CONNECTION (source)((((GDBusConnection*) (void *) ((source)))));
1848 CajaApplication *self = user_data;
1849 GError *error = NULL((void*)0);
1850
1851 g_dbus_connection_call_finish (connection, res, &error);
1852
1853 if (error != NULL((void*)0)) {
1854 g_warning ("Unable to select specified URIs %s\n", error->message);
1855 g_error_free (error);
1856
1857 /* open default location instead */
1858 g_application_open (G_APPLICATION (self)((((GApplication*) (void *) ((self))))), NULL((void*)0), 0, "");
1859 }
1860}
1861
1862static void
1863caja_application_select (CajaApplication *self,
1864 GFile **files,
1865 gint len)
1866{
1867 GDBusConnection *connection = g_application_get_dbus_connection (G_APPLICATION (self)((((GApplication*) (void *) ((self))))));
1868 GVariantBuilder builder;
1869 gint idx;
1870 gchar *uri;
1871
1872 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as")(g_variant_type_checked_ (("as"))));
1873 for (idx = 0; idx < len; idx++) {
1874 uri = g_file_get_uri (files[idx]);
1875 g_variant_builder_add (&builder, "s", uri);
1876 g_free (uri);
1877 }
1878
1879 g_dbus_connection_call (connection,
1880 CAJA_FDO_DBUS_NAME"org.freedesktop.FileManager1",
1881 CAJA_FDO_DBUS_PATH"/org/freedesktop/FileManager1",
1882 CAJA_FDO_DBUS_IFACE"org.freedesktop.FileManager1",
1883 "ShowItems",
1884 g_variant_new ("(ass)", &builder, ""), NULL((void*)0),
1885 G_DBUS_CALL_FLAGS_NONE, G_MAXINT2147483647, NULL((void*)0),
1886 select_items_ready_cb, self);
1887
1888 g_variant_builder_clear (&builder);
1889}
1890
1891static gboolean
1892running_in_mate (void)
1893{
1894 return (g_strcmp0 (g_getenv ("XDG_CURRENT_DESKTOP"), "MATE") == 0)
1895 || (g_strcmp0 (g_getenv ("XDG_SESSION_DESKTOP"), "mate") == 0)
1896 || (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "mate") == 0);
1897}
1898
1899static gboolean
1900running_as_root (void)
1901{
1902 return geteuid () == 0;
1903}
1904
1905static gboolean
1906caja_application_local_command_line (GApplication *application,
1907 gchar ***arguments,
1908 gint *exit_status)
1909{
1910 gboolean perform_self_check = FALSE(0);
1911 gboolean version = FALSE(0);
1912 gboolean browser_window = FALSE(0);
1913 gboolean open_in_tabs = FALSE(0);
1914 gboolean kill_shell = FALSE(0);
1915 const gchar *autostart_id;
1916 gboolean no_default_window = FALSE(0);
1917 gboolean select_uris = FALSE(0);
1918 gchar **remaining = NULL((void*)0);
1919 CajaApplication *self = CAJA_APPLICATION (application)((((CajaApplication*) (void *) ((application)))));
1920
1921 /*First set these FALSE */
1922 self->priv->force_desktop = FALSE(0);
1923 self->priv->no_desktop = FALSE(0);
1924
1925 const GOptionEntry options[] = {
1926#ifndef CAJA_OMIT_SELF_CHECK
1927 { "check", 'c', 0, G_OPTION_ARG_NONE, &perform_self_check,
1928 N_("Perform a quick set of self-check tests.")("Perform a quick set of self-check tests."), NULL((void*)0) },
1929#endif
1930 { "version", '\0', 0, G_OPTION_ARG_NONE, &version,
1931 N_("Show the version of the program.")("Show the version of the program."), NULL((void*)0) },
1932 { "geometry", 'g', 0, G_OPTION_ARG_STRING, &self->priv->geometry,
1933 N_("Create the initial window with the given geometry.")("Create the initial window with the given geometry."), N_("GEOMETRY")("GEOMETRY") },
1934 { "no-default-window", 'n', 0, G_OPTION_ARG_NONE, &no_default_window,
1935 N_("Only create windows for explicitly specified URIs.")("Only create windows for explicitly specified URIs."), NULL((void*)0) },
1936 { "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &self->priv->no_desktop,
1937 N_("Do not manage the desktop (ignore the preference set in the preferences dialog).")("Do not manage the desktop (ignore the preference set in the preferences dialog)."
)
, NULL((void*)0) },
1938 { "force-desktop", '\0', 0, G_OPTION_ARG_NONE, &self->priv->force_desktop,
1939 N_("Manage the desktop regardless of set preferences or environment (on new startup only)")("Manage the desktop regardless of set preferences or environment (on new startup only)"
)
, NULL((void*)0) },
1940 { "tabs", 't', 0, G_OPTION_ARG_NONE, &open_in_tabs,
1941 N_("Open URIs in tabs.")("Open URIs in tabs."), NULL((void*)0) },
1942 { "browser", '\0', 0, G_OPTION_ARG_NONE, &browser_window,
1943 N_("Open a browser window.")("Open a browser window."), NULL((void*)0) },
1944 { "quit", 'q', 0, G_OPTION_ARG_NONE, &kill_shell,
1945 N_("Quit Caja.")("Quit Caja."), NULL((void*)0) },
1946 { "select", 's', 0, G_OPTION_ARG_NONE, &select_uris,
1947 N_("Select specified URI in parent folder.")("Select specified URI in parent folder."), NULL((void*)0) },
1948 { G_OPTION_REMAINING"", 0, 0, G_OPTION_ARG_STRING_ARRAY, &remaining, NULL((void*)0), N_("[URI...]")("[URI...]") },
1949
1950 { NULL((void*)0) }
1951 };
1952 GOptionContext *context;
1953 GError *error = NULL((void*)0);
1954 gint argc = 0;
1955 gchar **argv = NULL((void*)0);
1956
1957 *exit_status = EXIT_SUCCESS0;
1958
1959 context = g_option_context_new (_("\n\nBrowse the file system with the file manager")dcgettext (((void*)0), "\n\nBrowse the file system with the file manager"
, 5)
);
1960 g_option_context_add_main_entries (context, options, NULL((void*)0));
1961 g_option_context_add_group (context, gtk_get_option_group (TRUE(!(0))));
1962
1963 g_option_context_add_group (context, egg_sm_client_get_option_group ());
1964
1965
1966 /* we need to do this here, as parsing the EggSMClient option context,
1967 * unsets this variable.
1968 */
1969 autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
1970 if (autostart_id != NULL((void*)0) && *autostart_id != '\0') {
1971 no_default_window = TRUE(!(0));
1972 self->priv->autostart = TRUE(!(0));
1973 }
1974
1975
1976 argv = *arguments;
1977 argc = g_strv_length (argv);
1978
1979 if (!g_option_context_parse (context, &argc, &argv, &error)) {
1980 g_printerr ("Could not parse arguments: %s\n", error->message);
1981 g_error_free (error);
1982
1983 *exit_status = EXIT_FAILURE1;
1984 goto out;
1985 }
1986
1987 if (version) {
1988 g_print ("MATE caja " PACKAGE_VERSION"1.26.4" "\n");
1989 goto out;
1990 }
1991
1992 if (!do_cmdline_sanity_checks (self, perform_self_check,
1993 version, kill_shell, select_uris, remaining)) {
1994 *exit_status = EXIT_FAILURE1;
1995 goto out;
1996 }
1997
1998 if (perform_self_check) {
1999 do_perform_self_checks (exit_status);
2000 goto out;
2001 }
2002
2003 g_debug ("Parsing local command line, no_default_window %d, quit %d, "
2004 "self checks %d, no_desktop %d",
2005 no_default_window, kill_shell, perform_self_check, self->priv->no_desktop);
2006
2007 g_application_register (application, NULL((void*)0), &error);
2008
2009 if (error != NULL((void*)0)) {
2010 g_printerr ("Could not register the application: %s\n", error->message);
2011 g_error_free (error);
2012
2013 *exit_status = EXIT_FAILURE1;
2014 goto out;
2015 }
2016
2017 if (kill_shell) {
2018 g_debug ("Killing application, as requested");
2019 g_action_group_activate_action (G_ACTION_GROUP (application)((((GActionGroup*) (void *) ((application))))),
2020 "quit", NULL((void*)0));
2021 goto out;
2022 }
2023
2024 /* Initialize and load session info if available */
2025 /* Load session if and only if autostarted */
2026 /* This avoids errors on command line invocation */
2027 if (autostart_id != NULL((void*)0) && self->smclient != NULL((void*)0) ) {
2028 caja_application_load_session (self);
2029 }
2030
2031 GFile **files;
2032 gint idx, len;
2033
2034 len = 0;
2035 files = NULL((void*)0);
2036
2037 /* Convert args to GFiles */
2038 if (remaining != NULL((void*)0)) {
2039 GPtrArray *file_array;
2040 GFile *file = NULL((void*)0);
2041
2042 file_array = g_ptr_array_new ();
2043
2044 for (idx = 0; remaining[idx] != NULL((void*)0); idx++) {
2045 file = g_file_new_for_commandline_arg (remaining[idx]);
2046 if (file != NULL((void*)0)) {
2047 g_ptr_array_add (file_array, file);
2048 }
2049 }
2050
2051 len = file_array->len;
2052 files = (GFile **) g_ptr_array_free (file_array, FALSE(0));
2053 g_strfreev (remaining);
2054 }
2055
2056 if (files == NULL((void*)0) && !no_default_window && !select_uris) {
2057 files = g_malloc0 (2 * sizeof (GFile *));
2058 len = 1;
2059
2060 files[0] = g_file_new_for_path (g_get_home_dir ());
2061 files[1] = NULL((void*)0);
2062 }
2063
2064 if (len == 0) {
2065 goto out;
2066 }
2067
2068 if (select_uris) {
2069 caja_application_select (self, files, len);
2070 } else {
2071 /*Set up --geometry, --browser and --tabs options */
2072 /*Invoke "Open" to create new windows */
2073 gchar* concatOptions = g_malloc0(64);
2074 if (self->priv->geometry == NULL((void*)0)) {
2075 g_snprintf (concatOptions, 64, "%d=NULL=%d", browser_window, open_in_tabs);
2076 } else {
2077 g_snprintf (concatOptions, 64, "%d=%s=%d", browser_window, self->priv->geometry, open_in_tabs);
2078 }
2079 g_application_open (application, files, len, concatOptions);
2080 g_free (concatOptions);
2081 }
2082
2083 if (files)
2084 for (idx = 0; idx < len; idx++) {
2085 g_object_unref (files[idx]);
2086 }
2087 g_free (files);
2088
2089 out:
2090 g_option_context_free (context);
2091
2092 return TRUE(!(0));
2093}
2094
2095static void
2096load_custom_css (GtkCssProvider *provider,
2097 const gchar *filename,
2098 guint priority)
2099{
2100 GError *error = NULL((void*)0);
2101 gchar *path = g_build_filename (CAJA_DATADIR"/usr/local/share/caja", filename, NULL((void*)0));
2102
2103 if (provider)
2104 g_object_ref (provider)((__typeof__ (provider)) (g_object_ref) (provider));
2105 else
2106 provider = gtk_css_provider_new ();
2107
2108 gtk_css_provider_load_from_path (provider, path, &error);
2109
2110 if (error != NULL((void*)0)) {
2111 g_warning ("Can't parse Caja' CSS custom description '%s': %s\n",
2112 filename, error->message);
2113 g_error_free (error);
2114 } else {
2115 gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
2116 GTK_STYLE_PROVIDER (provider)((((GtkStyleProvider*) (void *) ((provider))))),
2117 priority);
2118 }
2119
2120 g_object_unref (provider);
2121 g_free (path);
2122}
2123
2124static void
2125reload_theme_css (GtkSettings *settings,
2126 GParamSpec *unused G_GNUC_UNUSED__attribute__ ((__unused__)),
2127 GtkCssProvider *provider)
2128{
2129 gchar *theme_name;
2130 gchar *css_theme_name;
2131 gchar *path;
2132
2133 g_object_get (settings, "gtk-theme-name", &theme_name, NULL((void*)0));
2134 css_theme_name = g_strconcat ("caja-desktop-", theme_name, ".css", NULL((void*)0));
2135 path = g_build_filename (CAJA_DATADIR"/usr/local/share/caja", css_theme_name, NULL((void*)0));
2136
2137 if (g_file_test (path, G_FILE_TEST_EXISTS))
2138 load_custom_css (provider, css_theme_name, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION600);
2139 else /* just empty the provider */
2140 gtk_css_provider_load_from_data (provider, "", 0, NULL((void*)0));
2141
2142 g_free (path);
2143 g_free (css_theme_name);
2144 g_free (theme_name);
2145}
2146
2147static void
2148init_icons_and_styles (void)
2149{
2150 GtkSettings *settings = gtk_settings_get_default ();
2151 GtkCssProvider *provider;
2152
2153 /* add our custom CSS provider */
2154 load_custom_css (NULL((void*)0), "caja.css", GTK_STYLE_PROVIDER_PRIORITY_THEME200);
2155 /* add our desktop CSS provider, ensures the desktop background does not get covered */
2156 load_custom_css (NULL((void*)0), "caja-desktop.css", GTK_STYLE_PROVIDER_PRIORITY_APPLICATION600);
2157 /* add theme-specific desktop CSS */
2158 provider = gtk_css_provider_new ();
2159 reload_theme_css (settings, NULL((void*)0), provider);
2160 g_signal_connect_data (settings, "notify::gtk-theme-name", G_CALLBACK (reload_theme_css)((GCallback) (reload_theme_css)),
2161 provider, (GClosureNotify) g_object_unref, 0);
2162
2163 /* initialize search path for custom icons */
2164 gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
2165 CAJA_DATADIR"/usr/local/share/caja" G_DIR_SEPARATOR_S"/" "icons");
2166}
2167
2168static void
2169init_desktop (CajaApplication *self)
2170{
2171 /* Initialize the desktop link monitor singleton */
2172 caja_desktop_link_monitor_get ();
2173
2174 if (!self->priv->no_desktop &&
2175 !g_settings_get_boolean (mate_background_preferences,
2176 MATE_BG_KEY_SHOW_DESKTOP"show-desktop-icons")) {
2177 self->priv->no_desktop = TRUE(!(0));
2178 }
2179
2180 if (running_as_root () || !running_in_mate ())
2181 {
2182 /* do not manage desktop when running as root or on other desktops unless forced */
2183 self->priv->no_desktop = TRUE(!(0));
2184 }
2185
2186 if (!self->priv->no_desktop || self->priv->force_desktop) {
2187 caja_application_open_desktop (self);
2188 }
2189
2190 /* Monitor the preference to show or hide the desktop */
2191 g_signal_connect_swapped (mate_background_preferences, "changed::" MATE_BG_KEY_SHOW_DESKTOP,g_signal_connect_data ((mate_background_preferences), ("changed::"
"show-desktop-icons"), (((GCallback) (desktop_changed_callback
))), (self), ((void*)0), G_CONNECT_SWAPPED)
2192 G_CALLBACK (desktop_changed_callback),g_signal_connect_data ((mate_background_preferences), ("changed::"
"show-desktop-icons"), (((GCallback) (desktop_changed_callback
))), (self), ((void*)0), G_CONNECT_SWAPPED)
2193 self)g_signal_connect_data ((mate_background_preferences), ("changed::"
"show-desktop-icons"), (((GCallback) (desktop_changed_callback
))), (self), ((void*)0), G_CONNECT_SWAPPED)
;
2194}
2195
2196static gboolean
2197caja_application_save_accel_map (gpointer data)
2198{
2199 if (save_of_accel_map_requested) {
2200 char *accel_map_filename;
2201 accel_map_filename = caja_get_accel_map_file ();
2202 if (accel_map_filename) {
2203 gtk_accel_map_save (accel_map_filename);
2204 g_free (accel_map_filename);
2205 }
2206 save_of_accel_map_requested = FALSE(0);
2207 }
2208
2209 return FALSE(0);
2210}
2211
2212static void
2213queue_accel_map_save_callback (GtkAccelMap *object, gchar *accel_path,
2214 guint accel_key, GdkModifierType accel_mods,
2215 gpointer user_data)
2216{
2217 if (!save_of_accel_map_requested) {
2218 save_of_accel_map_requested = TRUE(!(0));
2219 g_timeout_add_seconds (CAJA_ACCEL_MAP_SAVE_DELAY30,
2220 caja_application_save_accel_map, NULL((void*)0));
2221 }
2222}
2223
2224static void
2225init_gtk_accels (void)
2226{
2227 char *accel_map_filename;
2228
2229 /* load accelerator map, and register save callback */
2230 accel_map_filename = caja_get_accel_map_file ();
2231 if (accel_map_filename) {
2232 gtk_accel_map_load (accel_map_filename);
2233 g_free (accel_map_filename);
2234 }
2235
2236 g_signal_connect (gtk_accel_map_get (), "changed",g_signal_connect_data ((gtk_accel_map_get ()), ("changed"), (
((GCallback) (queue_accel_map_save_callback))), (((void*)0)),
((void*)0), (GConnectFlags) 0)
2237 G_CALLBACK (queue_accel_map_save_callback), NULL)g_signal_connect_data ((gtk_accel_map_get ()), ("changed"), (
((GCallback) (queue_accel_map_save_callback))), (((void*)0)),
((void*)0), (GConnectFlags) 0)
;
2238}
2239
2240
2241static void
2242caja_application_startup (GApplication *app)
2243{
2244 CajaApplication *self = CAJA_APPLICATION (app)((((CajaApplication*) (void *) ((app)))));
2245 gboolean exit_with_last_window;
2246 exit_with_last_window = TRUE(!(0));
Value stored to 'exit_with_last_window' is never read
2247
2248 /* chain up to the GTK+ implementation early, so gtk_init()
2249 * is called for us.
2250 */
2251 G_APPLICATION_CLASS (caja_application_parent_class)((((GApplicationClass*) (void *) ((caja_application_parent_class
)))))
->startup (app);
2252
2253 /* Start the File Manager DBus Interface */
2254 fdb_manager = caja_freedesktop_dbus_new (self);
2255
2256 /* Initialize preferences. This is needed so that proper
2257 * defaults are available before any preference peeking
2258 * happens.
2259 */
2260 caja_global_preferences_init ();
2261
2262 /* initialize the session manager client */
2263 caja_application_smclient_startup (self);
2264
2265 /* register views */
2266 fm_icon_view_register ();
2267 fm_desktop_icon_view_register ();
2268 fm_list_view_register ();
2269 fm_compact_view_register ();
2270 fm_widget_view_register ();
2271#if ENABLE_EMPTY_VIEW1
2272 fm_empty_view_register ();
2273#endif /* ENABLE_EMPTY_VIEW */
2274
2275 /* register sidebars */
2276 caja_places_sidebar_register ();
2277 caja_information_panel_register ();
2278 fm_tree_view_register ();
2279 caja_history_sidebar_register ();
2280 caja_notes_viewer_register (); /* also property page */
2281 caja_emblem_sidebar_register ();
2282 caja_bookmarks_sidebar_register ();
2283
2284 /* register property pages */
2285 caja_image_properties_page_register ();
2286
2287 /* initialize theming */
2288 init_icons_and_styles ();
2289 init_gtk_accels ();
2290
2291 /* initialize caja modules */
2292 caja_module_setup ();
2293
2294 /* attach menu-provider module callback */
2295 menu_provider_init_callback ();
2296
2297 /* Initialize notifications for eject operations */
2298 notify_init (PACKAGE"caja");
2299
2300 /* Watch for unmounts so we can close open windows */
2301 /* TODO-gio: This should be using the UNMOUNTED feature of GFileMonitor instead */
2302 self->priv->volume_monitor = g_volume_monitor_get ();
2303 g_signal_connect_object ( self->priv->volume_monitor, "mount_removed",
2304 G_CALLBACK (mount_removed_callback)((GCallback) (mount_removed_callback)), self, 0);
2305 g_signal_connect_object ( self->priv->volume_monitor, "mount_pre_unmount",
2306 G_CALLBACK (mount_removed_callback)((GCallback) (mount_removed_callback)), self, 0);
2307 g_signal_connect_object ( self->priv->volume_monitor, "mount_added",
2308 G_CALLBACK (mount_added_callback)((GCallback) (mount_added_callback)), self, 0);
2309 g_signal_connect_object ( self->priv->volume_monitor, "volume_added",
2310 G_CALLBACK (volume_added_callback)((GCallback) (volume_added_callback)), self, 0);
2311 g_signal_connect_object ( self->priv->volume_monitor, "volume_removed",
2312 G_CALLBACK (volume_removed_callback)((GCallback) (volume_removed_callback)), self, 0);
2313 g_signal_connect_object ( self->priv->volume_monitor, "drive_connected",
2314 G_CALLBACK (drive_connected_callback)((GCallback) (drive_connected_callback)), self, 0);
2315
2316 /* listen for eject button presses */
2317 self->automount_idle_id =
2318 g_idle_add_full (G_PRIORITY_LOW300,
2319 automount_all_volumes_idle_cb,
2320 self, NULL((void*)0));
2321
2322 /* Check the user's ~/.caja directories and post warnings
2323 * if there are problems.
2324 */
2325 check_required_directories (self);
2326 init_desktop (self);
2327
2328 /* exit_with_last_window is already set to TRUE, and we need to keep that value
2329 * on other desktops, running from the command line, or when running caja as root.
2330 * Otherwise, we read the value from the configuration.
2331 */
2332
2333 if (running_in_mate () && !running_as_root())
2334 {
2335 GApplication *instance;
2336
2337 exit_with_last_window = g_settings_get_boolean (caja_preferences,
2338 CAJA_PREFERENCES_EXIT_WITH_LAST_WINDOW"exit-with-last-window");
2339 /*Keep this inside the running as mate/not as root block */
2340 /*So other desktop don't get unkillable caja instances holding open */
2341 instance = g_application_get_default ();
2342 if (exit_with_last_window == FALSE(0)){
2343 g_application_hold (G_APPLICATION (instance)((((GApplication*) (void *) ((instance))))));
2344 }
2345 }
2346
2347}
2348
2349static void
2350caja_application_quit_mainloop (GApplication *app)
2351{
2352 caja_icon_info_clear_caches ();
2353 caja_application_save_accel_map (NULL((void*)0));
2354
2355 G_APPLICATION_CLASS (caja_application_parent_class)((((GApplicationClass*) (void *) ((caja_application_parent_class
)))))
->quit_mainloop (app);
2356}
2357
2358static void
2359caja_application_class_init (CajaApplicationClass *class)
2360{
2361 GObjectClass *object_class;
2362 GApplicationClass *application_class;
2363
2364 object_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))));
2365 object_class->finalize = caja_application_finalize;
2366
2367 application_class = G_APPLICATION_CLASS (class)((((GApplicationClass*) (void *) ((class)))));
2368 application_class->startup = caja_application_startup;
2369 application_class->quit_mainloop = caja_application_quit_mainloop;
2370 application_class->open = caja_application_open;
2371 application_class->local_command_line = caja_application_local_command_line;
2372
2373}
2374
2375CajaApplication *
2376caja_application_new (void)
2377{
2378 return g_object_new (CAJA_TYPE_APPLICATIONcaja_application_get_type(),
2379 "application-id", "org.mate.Caja",
2380 "register-session", TRUE(!(0)),
2381 "flags", G_APPLICATION_HANDLES_OPEN,
2382 NULL((void*)0));
2383}
2384
diff --git a/2024-07-29-023715-6438-1/report-cb7be2.html b/2024-07-29-023715-6438-1/report-cb7be2.html new file mode 100644 index 000000000..3feabad83 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-cb7be2.html @@ -0,0 +1,2910 @@ + + + +caja-pathbar.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-pathbar.c
Warning:line 1091, column 32
Access to field 'data' results in a dereference of a null pointer (loaded from variable 'up_button')
+ +

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 caja-pathbar.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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-pathbar.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* caja-pathbar.c
3 * Copyright (C) 2004 Red Hat, Inc., Jonathan Blandford <jrb@gnome.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include <config.h>
22#include <string.h>
23
24#include <gtk/gtk.h>
25#include <glib/gi18n.h>
26#include <gio/gio.h>
27
28#include <libcaja-private/caja-file.h>
29#include <libcaja-private/caja-file-utilities.h>
30#include <libcaja-private/caja-global-preferences.h>
31#include <libcaja-private/caja-icon-names.h>
32#include <libcaja-private/caja-trash-monitor.h>
33#include <libcaja-private/caja-dnd.h>
34#include <libcaja-private/caja-icon-dnd.h>
35
36#include "caja-pathbar.h"
37
38enum
39{
40 PATH_CLICKED,
41 PATH_EVENT,
42 LAST_SIGNAL
43};
44
45typedef enum
46{
47 NORMAL_BUTTON,
48 ROOT_BUTTON,
49 HOME_BUTTON,
50 DESKTOP_BUTTON,
51 MOUNT_BUTTON,
52 DEFAULT_LOCATION_BUTTON,
53} ButtonType;
54
55#define BUTTON_DATA(x)((ButtonData *)(x)) ((ButtonData *)(x))
56
57#define SCROLL_TIMEOUT150 150
58#define INITIAL_SCROLL_TIMEOUT300 300
59
60static guint path_bar_signals [LAST_SIGNAL] = { 0 };
61
62static gboolean desktop_is_home;
63
64#define CAJA_PATH_BAR_ICON_SIZE16 16
65
66typedef struct _ButtonData ButtonData;
67
68struct _ButtonData
69{
70 GtkWidget *button;
71 ButtonType type;
72 char *dir_name;
73 GFile *path;
74 CajaFile *file;
75 unsigned int file_changed_signal_id;
76
77 /* custom icon */
78 cairo_surface_t *custom_icon;
79
80 /* flag to indicate its the base folder in the URI */
81 gboolean is_base_dir;
82
83 GtkWidget *image;
84 GtkWidget *label;
85 guint ignore_changes : 1;
86 guint file_is_hidden : 1;
87 guint fake_root : 1;
88
89 CajaDragSlotProxyInfo drag_info;
90};
91
92G_DEFINE_TYPE (CajaPathBar,static void caja_path_bar_init (CajaPathBar *self); static void
caja_path_bar_class_init (CajaPathBarClass *klass); static GType
caja_path_bar_get_type_once (void); static gpointer caja_path_bar_parent_class
= ((void*)0); static gint CajaPathBar_private_offset; static
void caja_path_bar_class_intern_init (gpointer klass) { caja_path_bar_parent_class
= g_type_class_peek_parent (klass); if (CajaPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaPathBar_private_offset
); caja_path_bar_class_init ((CajaPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer caja_path_bar_get_instance_private
(CajaPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CajaPathBar_private_offset)))); } GType caja_path_bar_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_path_bar_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_container_get_type ()), g_intern_static_string ("CajaPathBar"
), sizeof (CajaPathBarClass), (GClassInitFunc)(void (*)(void)
) caja_path_bar_class_intern_init, sizeof (CajaPathBar), (GInstanceInitFunc
)(void (*)(void)) caja_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
93 caja_path_bar,static void caja_path_bar_init (CajaPathBar *self); static void
caja_path_bar_class_init (CajaPathBarClass *klass); static GType
caja_path_bar_get_type_once (void); static gpointer caja_path_bar_parent_class
= ((void*)0); static gint CajaPathBar_private_offset; static
void caja_path_bar_class_intern_init (gpointer klass) { caja_path_bar_parent_class
= g_type_class_peek_parent (klass); if (CajaPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaPathBar_private_offset
); caja_path_bar_class_init ((CajaPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer caja_path_bar_get_instance_private
(CajaPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CajaPathBar_private_offset)))); } GType caja_path_bar_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_path_bar_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_container_get_type ()), g_intern_static_string ("CajaPathBar"
), sizeof (CajaPathBarClass), (GClassInitFunc)(void (*)(void)
) caja_path_bar_class_intern_init, sizeof (CajaPathBar), (GInstanceInitFunc
)(void (*)(void)) caja_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
94 GTK_TYPE_CONTAINER)static void caja_path_bar_init (CajaPathBar *self); static void
caja_path_bar_class_init (CajaPathBarClass *klass); static GType
caja_path_bar_get_type_once (void); static gpointer caja_path_bar_parent_class
= ((void*)0); static gint CajaPathBar_private_offset; static
void caja_path_bar_class_intern_init (gpointer klass) { caja_path_bar_parent_class
= g_type_class_peek_parent (klass); if (CajaPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CajaPathBar_private_offset
); caja_path_bar_class_init ((CajaPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer caja_path_bar_get_instance_private
(CajaPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (CajaPathBar_private_offset)))); } GType caja_path_bar_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_path_bar_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType caja_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_container_get_type ()), g_intern_static_string ("CajaPathBar"
), sizeof (CajaPathBarClass), (GClassInitFunc)(void (*)(void)
) caja_path_bar_class_intern_init, sizeof (CajaPathBar), (GInstanceInitFunc
)(void (*)(void)) caja_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
;
95
96static void caja_path_bar_finalize (GObject *object);
97static void caja_path_bar_dispose (GObject *object);
98
99static void caja_path_bar_get_preferred_width (GtkWidget *widget,
100 gint *minimum,
101 gint *natural);
102static void caja_path_bar_get_preferred_height (GtkWidget *widget,
103 gint *minimum,
104 gint *natural);
105
106static void caja_path_bar_unmap (GtkWidget *widget);
107static void caja_path_bar_size_allocate (GtkWidget *widget,
108 GtkAllocation *allocation);
109static void caja_path_bar_add (GtkContainer *container,
110 GtkWidget *widget);
111static void caja_path_bar_remove (GtkContainer *container,
112 GtkWidget *widget);
113static void caja_path_bar_forall (GtkContainer *container,
114 gboolean include_internals,
115 GtkCallback callback,
116 gpointer callback_data);
117static void caja_path_bar_scroll_up (CajaPathBar *path_bar);
118static void caja_path_bar_scroll_down (CajaPathBar *path_bar);
119static gboolean caja_path_bar_scroll (GtkWidget *path_bar,
120 GdkEventScroll *scroll);
121static void caja_path_bar_stop_scrolling (CajaPathBar *path_bar);
122static gboolean caja_path_bar_slider_button_press (GtkWidget *widget,
123 GdkEventButton *event,
124 CajaPathBar *path_bar);
125static gboolean caja_path_bar_slider_button_release (GtkWidget *widget,
126 GdkEventButton *event,
127 CajaPathBar *path_bar);
128static void caja_path_bar_grab_notify (GtkWidget *widget,
129 gboolean was_grabbed);
130static void caja_path_bar_state_flags_changed (GtkWidget *widget,
131 GtkStateFlags previous_state);
132
133static void caja_path_bar_style_updated (GtkWidget *widget);
134
135static void caja_path_bar_screen_changed (GtkWidget *widget,
136 GdkScreen *previous_screen);
137static void caja_path_bar_check_icon_theme (CajaPathBar *path_bar);
138static void caja_path_bar_update_button_appearance (ButtonData *button_data);
139static void caja_path_bar_update_button_state (ButtonData *button_data,
140 gboolean current_dir);
141static gboolean caja_path_bar_update_path (CajaPathBar *path_bar,
142 GFile *file_path,
143 gboolean emit_signal);
144
145
146static GtkWidget *
147get_slider_button (CajaPathBar *path_bar,
148 const gchar *arrow_type)
149{
150 GtkWidget *button;
151
152 button = gtk_button_new ();
153 gtk_widget_set_focus_on_click (button, FALSE(0));
154 gtk_widget_add_events (button, GDK_SCROLL_MASK);
155 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))),
156 gtk_image_new_from_icon_name (arrow_type, GTK_ICON_SIZE_MENU));
157 gtk_container_add (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))), button);
158 gtk_widget_show_all (button);
159
160 return button;
161}
162
163static void
164update_button_types (CajaPathBar *path_bar)
165{
166 GList *list;
167 GFile *path = NULL((void*)0);
168
169 for (list = path_bar->button_list; list; list = list->next)
170 {
171 ButtonData *button_data;
172 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
173 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_data->button)((((GtkToggleButton*) (void *) ((button_data->button)))))))
174 {
175 /*Increase the reference count on path so it does not get cleared
176 *by caja_path_bar_clear_buttons during caja_path_bar_update_path
177 */
178 path = g_object_ref (button_data->path)((__typeof__ (button_data->path)) (g_object_ref) (button_data
->path))
;
179 break;
180 }
181 }
182 if (path != NULL((void*)0))
183 {
184 caja_path_bar_update_path (path_bar, path, TRUE(!(0)));
185 g_object_unref (path);
186 }
187}
188
189
190static void
191desktop_location_changed_callback (gpointer user_data)
192{
193 CajaPathBar *path_bar;
194
195 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
196
197 g_object_unref (path_bar->desktop_path);
198 g_object_unref (path_bar->home_path);
199 path_bar->desktop_path = caja_get_desktop_location ();
200 path_bar->home_path = g_file_new_for_path (g_get_home_dir ());
201 desktop_is_home = g_file_equal (path_bar->home_path, path_bar->desktop_path);
202
203 update_button_types (path_bar);
204}
205
206static void
207trash_state_changed_cb (CajaTrashMonitor *monitor,
208 gboolean state,
209 CajaPathBar *path_bar)
210{
211 GFile *file;
212 GList *list;
213 gint scale;
214
215 file = g_file_new_for_uri ("trash:///");
216 scale = gtk_widget_get_scale_factor (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
217 for (list = path_bar->button_list; list; list = list->next)
218 {
219 ButtonData *button_data;
220 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
221 if (g_file_equal (file, button_data->path))
222 {
223 GIcon *icon;
224 CajaIconInfo *icon_info;
225 cairo_surface_t *surface;
226
227 icon = caja_trash_monitor_get_icon ();
228 icon_info = caja_icon_info_lookup (icon, CAJA_PATH_BAR_ICON_SIZE16, scale);
229 surface = caja_icon_info_get_surface_at_size (icon_info, CAJA_PATH_BAR_ICON_SIZE16);
230 gtk_image_set_from_surface (GTK_IMAGE (button_data->image)((((GtkImage*) (void *) ((button_data->image))))), surface);
231 }
232 }
233 g_object_unref (file);
234}
235
236static gboolean
237slider_timeout (gpointer user_data)
238{
239 CajaPathBar *path_bar;
240
241 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
242
243 path_bar->drag_slider_timeout = 0;
244
245 if (gtk_widget_get_visible (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar)))))))
246 {
247 if (path_bar->drag_slider_timeout_for_up_button)
248 {
249 caja_path_bar_scroll_up (path_bar);
250 }
251 else
252 {
253 caja_path_bar_scroll_down (path_bar);
254 }
255 }
256
257 return FALSE(0);
258}
259
260static void
261caja_path_bar_slider_drag_motion (GtkWidget *widget,
262 GdkDragContext *context,
263 int x,
264 int y,
265 unsigned int time,
266 gpointer user_data)
267{
268 CajaPathBar *path_bar;
269 unsigned int timeout;
270
271 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
272
273 if (path_bar->drag_slider_timeout == 0)
274 {
275 GtkSettings *settings;
276
277 settings = gtk_widget_get_settings (widget);
278
279 g_object_get (settings, "gtk-timeout-expand", &timeout, NULL((void*)0));
280 path_bar->drag_slider_timeout =
281 g_timeout_add (timeout,
282 slider_timeout,
283 path_bar);
284
285 path_bar->drag_slider_timeout_for_up_button =
286 widget == path_bar->up_slider_button;
287 }
288}
289
290static void
291caja_path_bar_slider_drag_leave (GtkWidget *widget,
292 GdkDragContext *context,
293 unsigned int time,
294 gpointer user_data)
295{
296 CajaPathBar *path_bar;
297
298 path_bar = CAJA_PATH_BAR (user_data)((((CajaPathBar*) (void *) ((user_data)))));
299
300 if (path_bar->drag_slider_timeout != 0)
301 {
302 g_source_remove (path_bar->drag_slider_timeout);
303 path_bar->drag_slider_timeout = 0;
304 }
305}
306
307static void
308caja_path_bar_init (CajaPathBar *path_bar)
309{
310 char *p;
311 GtkStyleContext *context;
312
313 context = gtk_widget_get_style_context (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
314 gtk_style_context_add_class (context, "caja-pathbar");
315
316 gtk_widget_set_has_window (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))), FALSE(0));
317 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))), FALSE(0));
318
319 path_bar->spacing = 3;
320 path_bar->up_slider_button = get_slider_button (path_bar, "pan-start-symbolic");
321 path_bar->down_slider_button = get_slider_button (path_bar, "pan-end-symbolic");
322 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button)))))),
323 "slider-button");
324 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (path_bar->down_slider_button)((((GtkWidget*) (void *) ((path_bar->down_slider_button)))
))
),
325 "slider-button");
326
327 path_bar->icon_size = CAJA_PATH_BAR_ICON_SIZE16;
328
329 p = caja_get_desktop_directory ();
330 path_bar->desktop_path = g_file_new_for_path (p);
331 g_free (p);
332 path_bar->home_path = g_file_new_for_path (g_get_home_dir ());
333 path_bar->root_path = g_file_new_for_path ("/");
334 path_bar->current_path = NULL((void*)0);
335 path_bar->current_button_data = NULL((void*)0);
336
337 desktop_is_home = g_file_equal (path_bar->home_path, path_bar->desktop_path);
338
339 g_signal_connect_swapped (caja_preferences, "changed::" CAJA_PREFERENCES_DESKTOP_IS_HOME_DIR,g_signal_connect_data ((caja_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
340 G_CALLBACK(desktop_location_changed_callback),g_signal_connect_data ((caja_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
341 path_bar)g_signal_connect_data ((caja_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
;
342
343 g_signal_connect_swapped (path_bar->up_slider_button, "clicked", G_CALLBACK (caja_path_bar_scroll_up), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("clicked"
), (((GCallback) (caja_path_bar_scroll_up))), (path_bar), ((void
*)0), G_CONNECT_SWAPPED)
;
344 g_signal_connect_swapped (path_bar->down_slider_button, "clicked", G_CALLBACK (caja_path_bar_scroll_down), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("clicked"
), (((GCallback) (caja_path_bar_scroll_down))), (path_bar), (
(void*)0), G_CONNECT_SWAPPED)
;
345
346 g_signal_connect (path_bar->up_slider_button, "button_press_event", G_CALLBACK (caja_path_bar_slider_button_press), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("button_press_event"
), (((GCallback) (caja_path_bar_slider_button_press))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
347 g_signal_connect (path_bar->up_slider_button, "button_release_event", G_CALLBACK (caja_path_bar_slider_button_release), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("button_release_event"
), (((GCallback) (caja_path_bar_slider_button_release))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
348 g_signal_connect (path_bar->down_slider_button, "button_press_event", G_CALLBACK (caja_path_bar_slider_button_press), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("button_press_event"
), (((GCallback) (caja_path_bar_slider_button_press))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
349 g_signal_connect (path_bar->down_slider_button, "button_release_event", G_CALLBACK (caja_path_bar_slider_button_release), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("button_release_event"
), (((GCallback) (caja_path_bar_slider_button_release))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
350
351 gtk_drag_dest_set (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button))))),
352 0, NULL((void*)0), 0, 0);
353 gtk_drag_dest_set_track_motion (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button))))), TRUE(!(0)));
354 g_signal_connect (path_bar->up_slider_button,g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
355 "drag-motion",g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
356 G_CALLBACK (caja_path_bar_slider_drag_motion),g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
357 path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
358 g_signal_connect (path_bar->up_slider_button,g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
359 "drag-leave",g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
360 G_CALLBACK (caja_path_bar_slider_drag_leave),g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
361 path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
362
363 gtk_drag_dest_set (GTK_WIDGET (path_bar->down_slider_button)((((GtkWidget*) (void *) ((path_bar->down_slider_button)))
))
,
364 0, NULL((void*)0), 0, 0);
365 gtk_drag_dest_set_track_motion (GTK_WIDGET (path_bar->up_slider_button)((((GtkWidget*) (void *) ((path_bar->up_slider_button))))), TRUE(!(0)));
366 g_signal_connect (path_bar->down_slider_button,g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
367 "drag-motion",g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
368 G_CALLBACK (caja_path_bar_slider_drag_motion),g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
369 path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (caja_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
370 g_signal_connect (path_bar->down_slider_button,g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
371 "drag-leave",g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
372 G_CALLBACK (caja_path_bar_slider_drag_leave),g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
373 path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (caja_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
374
375 g_signal_connect (caja_trash_monitor_get (),g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
376 "trash_state_changed",g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
377 G_CALLBACK (trash_state_changed_cb),g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
378 path_bar)g_signal_connect_data ((caja_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
;
379}
380
381static void
382caja_path_bar_class_init (CajaPathBarClass *path_bar_class)
383{
384 GObjectClass *gobject_class;
385 GtkWidgetClass *widget_class;
386 GtkContainerClass *container_class;
387
388 gobject_class = (GObjectClass *) path_bar_class;
389 widget_class = (GtkWidgetClass *) path_bar_class;
390 container_class = (GtkContainerClass *) path_bar_class;
391
392 gobject_class->finalize = caja_path_bar_finalize;
393 gobject_class->dispose = caja_path_bar_dispose;
394
395 widget_class->get_preferred_height = caja_path_bar_get_preferred_height;
396 widget_class->get_preferred_width = caja_path_bar_get_preferred_width;
397
398 widget_class->unmap = caja_path_bar_unmap;
399 widget_class->size_allocate = caja_path_bar_size_allocate;
400 widget_class->style_updated = caja_path_bar_style_updated;
401
402 widget_class->screen_changed = caja_path_bar_screen_changed;
403 widget_class->grab_notify = caja_path_bar_grab_notify;
404 widget_class->state_flags_changed = caja_path_bar_state_flags_changed;
405 widget_class->scroll_event = caja_path_bar_scroll;
406
407 container_class->add = caja_path_bar_add;
408 container_class->forall = caja_path_bar_forall;
409 container_class->remove = caja_path_bar_remove;
410
411 path_bar_signals [PATH_CLICKED] =
412 g_signal_new ("path-clicked",
413 G_OBJECT_CLASS_TYPE (path_bar_class)((((GTypeClass*) (path_bar_class))->g_type)),
414 G_SIGNAL_RUN_FIRST,
415 G_STRUCT_OFFSET (CajaPathBarClass, path_clicked)((glong) __builtin_offsetof(CajaPathBarClass, path_clicked)),
416 NULL((void*)0), NULL((void*)0),
417 g_cclosure_marshal_VOID__OBJECT,
418 G_TYPE_NONE((GType) ((1) << (2))), 1,
419 G_TYPE_FILE(g_file_get_type ()));
420
421 path_bar_signals [PATH_EVENT] =
422 g_signal_new ("path-event",
423 G_OBJECT_CLASS_TYPE (path_bar_class)((((GTypeClass*) (path_bar_class))->g_type)),
424 G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
425 G_STRUCT_OFFSET (CajaPathBarClass, path_event)((glong) __builtin_offsetof(CajaPathBarClass, path_event)),
426 NULL((void*)0), NULL((void*)0), NULL((void*)0),
427 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
428 G_TYPE_FILE(g_file_get_type ()),
429 GDK_TYPE_EVENT(gdk_event_get_type ()));
430
431 gtk_container_class_handle_border_width (container_class);
432}
433
434
435static void
436caja_path_bar_finalize (GObject *object)
437{
438 CajaPathBar *path_bar;
439
440 path_bar = CAJA_PATH_BAR (object)((((CajaPathBar*) (void *) ((object)))));
441
442 caja_path_bar_stop_scrolling (path_bar);
443
444 if (path_bar->drag_slider_timeout != 0)
445 {
446 g_source_remove (path_bar->drag_slider_timeout);
447 path_bar->drag_slider_timeout = 0;
448 }
449
450 g_list_free (path_bar->button_list);
451 if (path_bar->root_path)
452 {
453 g_object_unref (path_bar->root_path);
454 path_bar->root_path = NULL((void*)0);
455 }
456 if (path_bar->home_path)
457 {
458 g_object_unref (path_bar->home_path);
459 path_bar->home_path = NULL((void*)0);
460 }
461 if (path_bar->desktop_path)
462 {
463 g_object_unref (path_bar->desktop_path);
464 path_bar->desktop_path = NULL((void*)0);
465 }
466
467 g_signal_handlers_disconnect_by_func (caja_trash_monitor_get (),g_signal_handlers_disconnect_matched ((caja_trash_monitor_get
()), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (trash_state_changed_cb), (path_bar))
468 trash_state_changed_cb, path_bar)g_signal_handlers_disconnect_matched ((caja_trash_monitor_get
()), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (trash_state_changed_cb), (path_bar))
;
469 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
470 desktop_location_changed_callback,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
471 path_bar)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
;
472
473 G_OBJECT_CLASS (caja_path_bar_parent_class)((((GObjectClass*) (void *) ((caja_path_bar_parent_class)))))->finalize (object);
474}
475
476/* Removes the settings signal handler. It's safe to call multiple times */
477static void
478remove_settings_signal (CajaPathBar *path_bar,
479 GdkScreen *screen)
480{
481 if (path_bar->settings_signal_id)
482 {
483 GtkSettings *settings;
484
485 settings = gtk_settings_get_for_screen (screen);
486 g_signal_handler_disconnect (settings,
487 path_bar->settings_signal_id);
488 path_bar->settings_signal_id = 0;
489 }
490}
491
492static void
493caja_path_bar_dispose (GObject *object)
494{
495 remove_settings_signal (CAJA_PATH_BAR (object)((((CajaPathBar*) (void *) ((object))))), gtk_widget_get_screen (GTK_WIDGET (object)((((GtkWidget*) (void *) ((object)))))));
496
497 G_OBJECT_CLASS (caja_path_bar_parent_class)((((GObjectClass*) (void *) ((caja_path_bar_parent_class)))))->dispose (object);
498}
499
500/* Size requisition:
501 *
502 * Ideally, our size is determined by another widget, and we are just filling
503 * available space.
504 */
505
506static void
507caja_path_bar_get_preferred_width (GtkWidget *widget,
508 gint *minimum,
509 gint *natural)
510{
511 CajaPathBar *path_bar;
512 GList *list;
513 gint child_height;
514 gint height;
515 gint child_min, child_nat;
516 gint slider_width;
517 ButtonData *button_data = NULL((void*)0);
518
519 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
520
521 *minimum = *natural = 0;
522 height = 0;
523
524 for (list = path_bar->button_list; list; list = list->next) {
525 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
526 gtk_widget_get_preferred_width (button_data->button, &child_min, &child_nat);
527 gtk_widget_get_preferred_height (button_data->button, &child_height, NULL((void*)0));
528 height = MAX (height, child_height)(((height) > (child_height)) ? (height) : (child_height));
529
530 if (button_data->type == NORMAL_BUTTON) {
531 /* Use 2*Height as button width because of ellipsized label. */
532 child_min = MAX (child_min, child_height * 2)(((child_min) > (child_height * 2)) ? (child_min) : (child_height
* 2))
;
533 child_nat = MAX (child_min, child_height * 2)(((child_min) > (child_height * 2)) ? (child_min) : (child_height
* 2))
;
534 }
535
536 *minimum = MAX (*minimum, child_min)(((*minimum) > (child_min)) ? (*minimum) : (child_min));
537 *natural = MAX (*natural, child_nat)(((*natural) > (child_nat)) ? (*natural) : (child_nat));
538 }
539
540 /* Add space for slider, if we have more than one path */
541 /* Theoretically, the slider could be bigger than the other button. But we're
542 * not going to worry about that now.
543 */
544 gtk_widget_get_preferred_width (path_bar->down_slider_button,
545 &slider_width,
546 NULL((void*)0));
547 gtk_widget_get_preferred_width (path_bar->up_slider_button,
548 &slider_width,
549 NULL((void*)0));
550
551
552 if (path_bar->button_list) {
553 *minimum += (path_bar->spacing + slider_width) * 2;
554 *natural += (path_bar->spacing + slider_width) * 2;
555 }
556 /*Let's keep the rest of this as it was */
557 path_bar->slider_width = slider_width;
558}
559
560static void
561caja_path_bar_get_preferred_height (GtkWidget *widget,
562 gint *minimum,
563 gint *natural)
564{
565 CajaPathBar *path_bar;
566 GList *list;
567 gint child_min, child_nat;
568 ButtonData *button_data = NULL((void*)0);
569
570 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
571
572 *minimum = *natural = 0;
573
574 for (list = path_bar->button_list; list; list = list->next) {
575 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
576 gtk_widget_get_preferred_height (button_data->button, &child_min, &child_nat);
577
578 *minimum = MAX (*minimum, child_min)(((*minimum) > (child_min)) ? (*minimum) : (child_min));
579 *natural = MAX (*natural, child_nat)(((*natural) > (child_nat)) ? (*natural) : (child_nat));
580 }
581}
582
583static void
584caja_path_bar_update_slider_buttons (CajaPathBar *path_bar)
585{
586 if (path_bar->button_list)
587 {
588
589 GtkWidget *button;
590
591 button = BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button;
592 if (gtk_widget_get_child_visible (button))
593 {
594 gtk_widget_set_sensitive (path_bar->down_slider_button, FALSE(0));
595 }
596 else
597 {
598 gtk_widget_set_sensitive (path_bar->down_slider_button, TRUE(!(0)));
599 }
600 button = BUTTON_DATA (g_list_last (path_bar->button_list)->data)((ButtonData *)(g_list_last (path_bar->button_list)->data
))
->button;
601 if (gtk_widget_get_child_visible (button))
602 {
603 gtk_widget_set_sensitive (path_bar->up_slider_button, FALSE(0));
604 }
605 else
606 {
607 gtk_widget_set_sensitive (path_bar->up_slider_button, TRUE(!(0)));
608 }
609 }
610}
611
612static void
613caja_path_bar_unmap (GtkWidget *widget)
614{
615 caja_path_bar_stop_scrolling (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
616
617 GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->unmap (widget);
618}
619
620/* This is a tad complicated */
621static void
622caja_path_bar_size_allocate (GtkWidget *widget,
623 GtkAllocation *allocation)
624{
625 GtkWidget *child;
626 CajaPathBar *path_bar;
627 GtkTextDirection direction;
628 GtkAllocation child_allocation;
629 GList *list, *first_button;
630 gint width;
631 gint allocation_width;
632 gboolean need_sliders;
633 gint up_slider_offset;
634 gint down_slider_offset;
635 GtkRequisition child_requisition;
636 GtkAllocation widget_allocation;
637
638 need_sliders = TRUE(!(0));
639 up_slider_offset = 0;
640 down_slider_offset = 0;
641 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
642
643 gtk_widget_set_allocation (widget, allocation);
644
645 /* No path is set so we don't have to allocate anything. */
646 if (path_bar->button_list == NULL((void*)0))
647 {
648 return;
649 }
650 direction = gtk_widget_get_direction (widget);
651
652 allocation_width = allocation->width;
653
654 /* First, we check to see if we need the scrollbars. */
655 if (path_bar->fake_root)
656 {
657 width = path_bar->spacing + path_bar->slider_width;
658 }
659 else
660 {
661 width = 0;
662 }
663
664 gtk_widget_get_preferred_size (BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button,
665 &child_requisition, NULL((void*)0));
666 width += child_requisition.width;
667
668 for (list = path_bar->button_list->next; list; list = list->next)
669 {
670 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
671 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
672 width += child_requisition.width + path_bar->spacing;
673
674 if (list == path_bar->fake_root)
675 {
676 break;
677 }
678 }
679
680 if (width <= allocation_width)
681 {
682 if (path_bar->fake_root)
683 {
684 first_button = path_bar->fake_root;
685 }
686 else
687 {
688 first_button = g_list_last (path_bar->button_list);
689 }
690 }
691 else
692 {
693 gboolean reached_end;
694 gint slider_space;
695 reached_end = FALSE(0);
696 slider_space = 2 * (path_bar->spacing + path_bar->slider_width);
697
698 if (path_bar->first_scrolled_button)
699 {
700 first_button = path_bar->first_scrolled_button;
701 }
702 else
703 {
704 first_button = path_bar->button_list;
705 }
706
707 need_sliders = TRUE(!(0));
708 /* To see how much space we have, and how many buttons we can display.
709 * We start at the first button, count forward until hit the new
710 * button, then count backwards.
711 */
712 /* Count down the path chain towards the end. */
713 gtk_widget_get_preferred_size (BUTTON_DATA (first_button->data)((ButtonData *)(first_button->data))->button,
714 &child_requisition, NULL((void*)0));
715 width = child_requisition.width;
716 list = first_button->prev;
717 while (list && !reached_end)
718 {
719 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
720 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
721
722 if (width + child_requisition.width + path_bar->spacing + slider_space > allocation_width)
723 {
724 reached_end = TRUE(!(0));
725 }
726 else
727 {
728 if (list == path_bar->fake_root)
729 {
730 break;
731 }
732 else
733 {
734 width += child_requisition.width + path_bar->spacing;
735 }
736 }
737
738 list = list->prev;
739 }
740
741 /* Finally, we walk up, seeing how many of the previous buttons we can add*/
742
743 while (first_button->next && ! reached_end)
744 {
745 child = BUTTON_DATA (first_button->next->data)((ButtonData *)(first_button->next->data))->button;
746 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
747
748 if (width + child_requisition.width + path_bar->spacing + slider_space > allocation_width)
749 {
750 reached_end = TRUE(!(0));
751 }
752 else
753 {
754 width += child_requisition.width + path_bar->spacing;
755 if (first_button == path_bar->fake_root)
756 {
757 break;
758 }
759 first_button = first_button->next;
760 }
761 }
762 }
763
764 /* Now, we allocate space to the buttons */
765 child_allocation.y = allocation->y;
766 child_allocation.height = allocation->height;
767
768 if (direction == GTK_TEXT_DIR_RTL)
769 {
770 child_allocation.x = allocation->x + allocation->width;
771
772 if (need_sliders || path_bar->fake_root)
773 {
774 child_allocation.x -= (path_bar->spacing + path_bar->slider_width);
775 up_slider_offset = allocation->width - path_bar->slider_width;
776
777 }
778 }
779 else
780 {
781 child_allocation.x = allocation->x;
782
783 if (need_sliders || path_bar->fake_root)
784 {
785 up_slider_offset = 0;
786 child_allocation.x += (path_bar->spacing + path_bar->slider_width);
787 }
788 }
789
790 for (list = first_button; list; list = list->prev)
791 {
792 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
793 gtk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
794
795 gtk_widget_get_allocation (widget, &widget_allocation);
796
797 child_allocation.width = child_requisition.width;
798 if (direction == GTK_TEXT_DIR_RTL)
799 {
800 child_allocation.x -= child_allocation.width;
801 }
802 /* Check to see if we've don't have any more space to allocate buttons */
803 if (need_sliders && direction == GTK_TEXT_DIR_RTL)
804 {
805 if (child_allocation.x - path_bar->spacing - path_bar->slider_width < widget_allocation.x)
806 {
807 break;
808 }
809 }
810 else
811 {
812 if (need_sliders && direction == GTK_TEXT_DIR_LTR)
813 {
814 if (child_allocation.x + child_allocation.width + path_bar->spacing + path_bar->slider_width > widget_allocation.x + allocation_width)
815
816 {
817 break;
818 }
819 }
820 }
821
822 gtk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, TRUE(!(0)));
823 gtk_widget_size_allocate (child, &child_allocation);
824
825 if (direction == GTK_TEXT_DIR_RTL)
826 {
827 child_allocation.x -= path_bar->spacing;
828 down_slider_offset = child_allocation.x - allocation->x - path_bar->slider_width;
829 }
830 else
831 {
832 down_slider_offset = child_allocation.x - widget_allocation.x;
833 down_slider_offset += child_allocation.width + path_bar->spacing;
834
835 child_allocation.x += child_allocation.width + path_bar->spacing;
836 }
837 }
838 /* Now we go hide all the widgets that don't fit */
839 while (list)
840 {
841 gtk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, FALSE(0));
842 list = list->prev;
843 }
844 for (list = first_button->next; list; list = list->next)
845 {
846 gtk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, FALSE(0));
847 }
848
849 if (need_sliders || path_bar->fake_root)
850 {
851 child_allocation.width = path_bar->slider_width;
852 child_allocation.x = up_slider_offset + allocation->x;
853 gtk_widget_size_allocate (path_bar->up_slider_button, &child_allocation);
854
855 gtk_widget_set_child_visible (path_bar->up_slider_button, TRUE(!(0)));
856 gtk_widget_show_all (path_bar->up_slider_button);
857 }
858 else
859 {
860 gtk_widget_set_child_visible (path_bar->up_slider_button, FALSE(0));
861 }
862
863 if (need_sliders)
864 {
865 child_allocation.width = path_bar->slider_width;
866 child_allocation.x = down_slider_offset + allocation->x;
867 gtk_widget_size_allocate (path_bar->down_slider_button, &child_allocation);
868
869 gtk_widget_set_child_visible (path_bar->down_slider_button, TRUE(!(0)));
870 gtk_widget_show_all (path_bar->down_slider_button);
871 caja_path_bar_update_slider_buttons (path_bar);
872 }
873 else
874 {
875 gtk_widget_set_child_visible (path_bar->down_slider_button, FALSE(0));
876 }
877}
878
879static void
880caja_path_bar_style_updated (GtkWidget *widget)
881{
882 if (GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->style_updated)
883 {
884 GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->style_updated (widget);
885 }
886
887 caja_path_bar_check_icon_theme (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
888}
889
890static void
891caja_path_bar_screen_changed (GtkWidget *widget,
892 GdkScreen *previous_screen)
893{
894 if (GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->screen_changed)
895 {
896 GTK_WIDGET_CLASS (caja_path_bar_parent_class)((((GtkWidgetClass*) (void *) ((caja_path_bar_parent_class)))
))
->screen_changed (widget, previous_screen);
897 }
898 /* We might nave a new settings, so we remove the old one */
899 if (previous_screen)
900 {
901 remove_settings_signal (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))), previous_screen);
902 }
903 caja_path_bar_check_icon_theme (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
904}
905
906static gboolean
907caja_path_bar_scroll (GtkWidget *widget,
908 GdkEventScroll *event)
909{
910 CajaPathBar *path_bar;
911
912 path_bar = CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget)))));
913
914 switch (event->direction)
915 {
916 case GDK_SCROLL_RIGHT:
917 case GDK_SCROLL_DOWN:
918 caja_path_bar_scroll_down (path_bar);
919 return TRUE(!(0));
920
921 case GDK_SCROLL_LEFT:
922 case GDK_SCROLL_UP:
923 caja_path_bar_scroll_up (path_bar);
924 return TRUE(!(0));
925
926 case GDK_SCROLL_SMOOTH:
927 break;
928 }
929
930 return FALSE(0);
931}
932
933
934static void
935caja_path_bar_add (GtkContainer *container,
936 GtkWidget *widget)
937{
938 gtk_widget_set_parent (widget, GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
939}
940
941static void
942caja_path_bar_remove_1 (GtkContainer *container,
943 GtkWidget *widget)
944{
945 gboolean was_visible = gtk_widget_get_visible (widget);
946 gtk_widget_unparent (widget);
947 if (was_visible)
948 {
949 gtk_widget_queue_resize (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
950 }
951}
952
953static void
954caja_path_bar_remove (GtkContainer *container,
955 GtkWidget *widget)
956{
957 CajaPathBar *path_bar;
958 GList *children;
959
960 path_bar = CAJA_PATH_BAR (container)((((CajaPathBar*) (void *) ((container)))));
961
962 if (widget == path_bar->up_slider_button)
963 {
964 caja_path_bar_remove_1 (container, widget);
965 path_bar->up_slider_button = NULL((void*)0);
966 return;
967 }
968
969 if (widget == path_bar->down_slider_button)
970 {
971 caja_path_bar_remove_1 (container, widget);
972 path_bar->down_slider_button = NULL((void*)0);
973 return;
974 }
975
976 children = path_bar->button_list;
977 while (children)
978 {
979 if (widget == BUTTON_DATA (children->data)((ButtonData *)(children->data))->button)
980 {
981 caja_path_bar_remove_1 (container, widget);
982 path_bar->button_list = g_list_remove_link (path_bar->button_list, children);
983 g_list_free_1 (children);
984 return;
985 }
986 children = children->next;
987 }
988}
989
990static void
991caja_path_bar_forall (GtkContainer *container,
992 gboolean include_internals,
993 GtkCallback callback,
994 gpointer callback_data)
995{
996 CajaPathBar *path_bar;
997 GList *children;
998
999 g_return_if_fail (callback != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if (callback != ((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__)), "callback != NULL"
); return; } } while (0)
;
1000 path_bar = CAJA_PATH_BAR (container)((((CajaPathBar*) (void *) ((container)))));
1001
1002 children = path_bar->button_list;
1003 while (children)
1004 {
1005 GtkWidget *child;
1006 child = BUTTON_DATA (children->data)((ButtonData *)(children->data))->button;
1007 children = children->next;
1008 (* callback) (child, callback_data);
1009 }
1010
1011 if (path_bar->up_slider_button)
1012 {
1013 (* callback) (path_bar->up_slider_button, callback_data);
1014 }
1015
1016 if (path_bar->down_slider_button)
1017 {
1018 (* callback) (path_bar->down_slider_button, callback_data);
1019 }
1020}
1021
1022static void
1023caja_path_bar_scroll_down (CajaPathBar *path_bar)
1024{
1025 GList *list;
1026 GList *down_button;
1027 GList *up_button;
1028 gint space_available;
1029 gint space_needed;
1030 GtkTextDirection direction;
1031 GtkAllocation allocation, button_allocation, slider_allocation;
1032
1033 down_button = NULL((void*)0);
1034 up_button = NULL((void*)0);
10
Null pointer value stored to 'up_button'
1035
1036 if (path_bar->ignore_click
10.1
Field 'ignore_click' is 0
)
11
Taking false branch
1037 {
1038 path_bar->ignore_click = FALSE(0);
1039 return;
1040 }
1041
1042 gtk_widget_queue_resize (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
1043
1044 direction = gtk_widget_get_direction (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
1045
1046 /* We find the button at the 'down' end that we have to make */
1047 /* visible */
1048 for (list = path_bar->button_list; list; list = list->next)
1049 {
1050 if (list->next && gtk_widget_get_child_visible (BUTTON_DATA (list->next->data)((ButtonData *)(list->next->data))->button))
12
Assuming field 'next' is non-null
13
Assuming the condition is true
14
Taking true branch
1051 {
1052 down_button = list;
1053 break;
1054 }
1055 }
1056
1057 if (down_button
15.1
'down_button' is not equal to NULL
== NULL((void*)0))
15
Execution continues on line 1057
16
Taking false branch
1058 {
1059 return;
1060 }
1061
1062 /* Find the last visible button on the 'up' end */
1063 for (list = g_list_last (path_bar->button_list); list; list = list->prev)
17
Loop condition is false. Execution continues on line 1072
1064 {
1065 if (gtk_widget_get_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button))
1066 {
1067 up_button = list;
1068 break;
1069 }
1070 }
1071
1072 gtk_widget_get_allocation (BUTTON_DATA (down_button->data)((ButtonData *)(down_button->data))->button, &button_allocation);
1073 gtk_widget_get_allocation (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))), &allocation);
1074 gtk_widget_get_allocation (path_bar->down_slider_button, &slider_allocation);
1075
1076 space_needed = button_allocation.width + path_bar->spacing;
1077 if (direction == GTK_TEXT_DIR_RTL)
18
Assuming 'direction' is equal to GTK_TEXT_DIR_RTL
19
Taking true branch
1078 {
1079 space_available = slider_allocation.x - allocation.x;
1080 }
1081 else
1082 {
1083 space_available = (allocation.x + allocation.width) -
1084 (slider_allocation.x + slider_allocation.width);
1085 }
1086
1087 /* We have space_available extra space that's not being used. We
1088 * need space_needed space to make the button fit. So we walk down
1089 * from the end, removing buttons until we get all the space we
1090 * need. */
1091 gtk_widget_get_allocation (BUTTON_DATA (up_button->data)((ButtonData *)(up_button->data))->button, &button_allocation);
20
Access to field 'data' results in a dereference of a null pointer (loaded from variable 'up_button')
1092 while (space_available < space_needed && up_button)
1093 {
1094 space_available += button_allocation.width + path_bar->spacing;
1095 up_button = up_button->prev;
1096 path_bar->first_scrolled_button = up_button;
1097 }
1098}
1099
1100static void
1101caja_path_bar_scroll_up (CajaPathBar *path_bar)
1102{
1103 GList *list;
1104
1105 if (path_bar->ignore_click)
1106 {
1107 path_bar->ignore_click = FALSE(0);
1108 return;
1109 }
1110
1111 gtk_widget_queue_resize (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
1112
1113 for (list = g_list_last (path_bar->button_list); list; list = list->prev)
1114 {
1115 if (list->prev && gtk_widget_get_child_visible (BUTTON_DATA (list->prev->data)((ButtonData *)(list->prev->data))->button))
1116 {
1117 if (list->prev == path_bar->fake_root)
1118 {
1119 path_bar->fake_root = NULL((void*)0);
1120 }
1121 path_bar->first_scrolled_button = list;
1122 return;
1123 }
1124 }
1125}
1126
1127static gboolean
1128caja_path_bar_scroll_timeout (CajaPathBar *path_bar)
1129{
1130 gboolean retval = FALSE(0);
1131
1132 if (path_bar->timer)
1133 {
1134 if (gtk_widget_has_focus (path_bar->up_slider_button))
1135 {
1136 caja_path_bar_scroll_up (path_bar);
1137 }
1138 else
1139 {
1140 if (gtk_widget_has_focus (path_bar->down_slider_button))
1141 {
1142 caja_path_bar_scroll_down (path_bar);
1143 }
1144 }
1145 if (path_bar->need_timer)
1146 {
1147 path_bar->need_timer = FALSE(0);
1148
1149 path_bar->timer = g_timeout_add (SCROLL_TIMEOUT150,
1150 (GSourceFunc)caja_path_bar_scroll_timeout,
1151 path_bar);
1152
1153 }
1154 else
1155 {
1156 retval = TRUE(!(0));
1157 }
1158 }
1159
1160 return retval;
1161}
1162
1163static void
1164caja_path_bar_stop_scrolling (CajaPathBar *path_bar)
1165{
1166 if (path_bar->timer)
1167 {
1168 g_source_remove (path_bar->timer);
1169 path_bar->timer = 0;
1170 path_bar->need_timer = FALSE(0);
1171 }
1172}
1173
1174static gboolean
1175caja_path_bar_slider_button_press (GtkWidget *widget,
1176 GdkEventButton *event,
1177 CajaPathBar *path_bar)
1178{
1179 if (!gtk_widget_has_focus (widget))
1
Assuming the condition is false
1180 {
1181 gtk_widget_grab_focus (widget);
1182 }
1183
1184 if (event->type != GDK_BUTTON_PRESS || event->button != 1)
2
Assuming field 'type' is equal to GDK_BUTTON_PRESS
3
Assuming field 'button' is equal to 1
4
Taking false branch
1185 {
1186 return FALSE(0);
1187 }
1188
1189 path_bar->ignore_click = FALSE(0);
1190
1191 if (widget == path_bar->up_slider_button)
5
Assuming 'widget' is not equal to field 'up_slider_button'
6
Taking false branch
1192 {
1193 caja_path_bar_scroll_up (path_bar);
1194 }
1195 else
1196 {
1197 if (widget == path_bar->down_slider_button)
7
Assuming 'widget' is equal to field 'down_slider_button'
8
Taking true branch
1198 {
1199 caja_path_bar_scroll_down (path_bar);
9
Calling 'caja_path_bar_scroll_down'
1200 }
1201 }
1202
1203 if (!path_bar->timer)
1204 {
1205 path_bar->need_timer = TRUE(!(0));
1206 path_bar->timer = g_timeout_add (INITIAL_SCROLL_TIMEOUT300,
1207 (GSourceFunc)caja_path_bar_scroll_timeout,
1208 path_bar);
1209 }
1210
1211 return FALSE(0);
1212}
1213
1214static gboolean
1215caja_path_bar_slider_button_release (GtkWidget *widget,
1216 GdkEventButton *event,
1217 CajaPathBar *path_bar)
1218{
1219 if (event->type != GDK_BUTTON_RELEASE)
1220 {
1221 return FALSE(0);
1222 }
1223
1224 path_bar->ignore_click = TRUE(!(0));
1225 caja_path_bar_stop_scrolling (path_bar);
1226
1227 return FALSE(0);
1228}
1229
1230static void
1231caja_path_bar_grab_notify (GtkWidget *widget,
1232 gboolean was_grabbed)
1233{
1234 if (!was_grabbed)
1235 {
1236 caja_path_bar_stop_scrolling (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
1237 }
1238}
1239
1240static void
1241caja_path_bar_state_flags_changed (GtkWidget *widget,
1242 GtkStateFlags previous_state)
1243{
1244 if (!gtk_widget_get_sensitive (widget))
1245 {
1246 caja_path_bar_stop_scrolling (CAJA_PATH_BAR (widget)((((CajaPathBar*) (void *) ((widget))))));
1247 }
1248}
1249
1250
1251
1252/* Changes the icons wherever it is needed */
1253static void
1254reload_icons (CajaPathBar *path_bar)
1255{
1256 GList *list;
1257
1258 for (list = path_bar->button_list; list; list = list->next)
1259 {
1260 ButtonData *button_data;
1261
1262 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
1263 if (button_data->type != NORMAL_BUTTON || button_data->is_base_dir)
1264 {
1265 caja_path_bar_update_button_appearance (button_data);
1266 }
1267
1268 }
1269}
1270
1271static void
1272change_icon_theme (CajaPathBar *path_bar)
1273{
1274 path_bar->icon_size = CAJA_PATH_BAR_ICON_SIZE16;
1275 reload_icons (path_bar);
1276}
1277
1278/* Callback used when a GtkSettings value changes */
1279static void
1280settings_notify_cb (GObject *object,
1281 GParamSpec *pspec,
1282 CajaPathBar *path_bar)
1283{
1284 const char *name;
1285
1286 name = g_param_spec_get_name (pspec);
1287
1288 if (! strcmp (name, "gtk-icon-theme-name") || ! strcmp (name, "gtk-icon-sizes"))
1289 {
1290 change_icon_theme (path_bar);
1291 }
1292}
1293
1294static void
1295caja_path_bar_check_icon_theme (CajaPathBar *path_bar)
1296{
1297 GtkSettings *settings;
1298
1299 if (path_bar->settings_signal_id)
1300 {
1301 return;
1302 }
1303
1304 settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar)))))));
1305 path_bar->settings_signal_id = g_signal_connect (settings, "notify", G_CALLBACK (settings_notify_cb), path_bar)g_signal_connect_data ((settings), ("notify"), (((GCallback) (
settings_notify_cb))), (path_bar), ((void*)0), (GConnectFlags
) 0)
;
1306
1307 change_icon_theme (path_bar);
1308}
1309
1310/* Public functions and their helpers */
1311void
1312caja_path_bar_clear_buttons (CajaPathBar *path_bar)
1313{
1314 while (path_bar->button_list != NULL((void*)0))
1315 {
1316 gtk_container_remove (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))), BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button);
1317 }
1318 path_bar->first_scrolled_button = NULL((void*)0);
1319 path_bar->fake_root = NULL((void*)0);
1320}
1321
1322static void
1323button_clicked_cb (GtkWidget *button,
1324 gpointer data)
1325{
1326 ButtonData *button_data;
1327 CajaPathBar *path_bar;
1328 GList *button_list;
1329
1330 button_data = BUTTON_DATA (data)((ButtonData *)(data));
1331 if (button_data->ignore_changes)
1332 {
1333 return;
1334 }
1335
1336 path_bar = CAJA_PATH_BAR (gtk_widget_get_parent (button))((((CajaPathBar*) (void *) ((gtk_widget_get_parent (button)))
)))
;
1337
1338 button_list = g_list_find (path_bar->button_list, button_data);
1339 g_assert (button_list != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if (button_list != ((void*)0)) _g_boolean_var_33 = 1; else _g_boolean_var_33
= 0; _g_boolean_var_33; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-pathbar.c", 1339, ((const char*) (__func__
)), "button_list != NULL"); } while (0)
;
1340
1341 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))), TRUE(!(0)));
1342
1343 g_signal_emit (path_bar, path_bar_signals [PATH_CLICKED], 0, button_data->path);
1344}
1345
1346static gboolean
1347button_event_cb (GtkWidget *button,
1348 GdkEventButton *event,
1349 gpointer data)
1350{
1351 ButtonData *button_data;
1352 CajaPathBar *path_bar;
1353 GList *button_list;
1354 gboolean retval;
1355
1356 button_data = BUTTON_DATA (data)((ButtonData *)(data));
1357 path_bar = CAJA_PATH_BAR (gtk_widget_get_parent (button))((((CajaPathBar*) (void *) ((gtk_widget_get_parent (button)))
)))
;
1358
1359 if (event->type == GDK_BUTTON_PRESS) {
1360 g_object_set_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "handle-button-release",
1361 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
1362 }
1363
1364 if (event->type == GDK_BUTTON_RELEASE &&
1365 !GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button),((guint) (gulong) (g_object_get_data (((((GObject*) (void *) (
(button))))), "handle-button-release")))
1366 "handle-button-release"))((guint) (gulong) (g_object_get_data (((((GObject*) (void *) (
(button))))), "handle-button-release")))
) {
1367 return FALSE(0);
1368 }
1369
1370 button_list = g_list_find (path_bar->button_list, button_data);
1371 g_assert (button_list != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if (button_list != ((void*)0)) _g_boolean_var_34 = 1; else _g_boolean_var_34
= 0; _g_boolean_var_34; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-pathbar.c", 1371, ((const char*) (__func__
)), "button_list != NULL"); } while (0)
;
1372
1373 g_signal_emit (path_bar, path_bar_signals [PATH_EVENT], 0, button_data->path, event, &retval);
1374
1375 return retval;
1376}
1377
1378static void
1379button_drag_begin_cb (GtkWidget *widget,
1380 GdkDragContext *drag_context,
1381 gpointer user_data)
1382{
1383 g_object_set_data (G_OBJECT (widget)((((GObject*) (void *) ((widget))))), "handle-button-release",
1384 GINT_TO_POINTER (FALSE)((gpointer) (glong) ((0))));
1385}
1386
1387
1388static CajaIconInfo *
1389get_type_icon_info (ButtonData *button_data)
1390{
1391 gint icon_scale = gtk_widget_get_scale_factor (GTK_WIDGET (button_data->button)((((GtkWidget*) (void *) ((button_data->button))))));
1392
1393 switch (button_data->type)
1394 {
1395 case ROOT_BUTTON:
1396 return caja_icon_info_lookup_from_name (CAJA_ICON_FILESYSTEM"drive-harddisk",
1397 CAJA_PATH_BAR_ICON_SIZE16,
1398 icon_scale);
1399
1400 case HOME_BUTTON:
1401 return caja_icon_info_lookup_from_name (CAJA_ICON_HOME"user-home",
1402 CAJA_PATH_BAR_ICON_SIZE16,
1403 icon_scale);
1404
1405 case DESKTOP_BUTTON:
1406 return caja_icon_info_lookup_from_name (CAJA_ICON_DESKTOP"user-desktop",
1407 CAJA_PATH_BAR_ICON_SIZE16,
1408 icon_scale);
1409
1410 case NORMAL_BUTTON:
1411 if (button_data->is_base_dir)
1412 {
1413 return caja_file_get_icon (button_data->file,
1414 CAJA_PATH_BAR_ICON_SIZE16, icon_scale,
1415 CAJA_FILE_ICON_FLAGS_NONE);
1416 }
1417
1418 default:
1419 return NULL((void*)0);
1420 }
1421
1422 return NULL((void*)0);
1423}
1424
1425static void
1426button_data_free (ButtonData *button_data)
1427{
1428 g_object_unref (button_data->path);
1429 g_free (button_data->dir_name);
1430 if (button_data->custom_icon)
1431 {
1432 cairo_surface_destroy (button_data->custom_icon);
1433 }
1434 if (button_data->file != NULL((void*)0))
1435 {
1436 g_signal_handler_disconnect (button_data->file,
1437 button_data->file_changed_signal_id);
1438 caja_file_monitor_remove (button_data->file, button_data);
1439 caja_file_unref (button_data->file);
1440 }
1441
1442 g_object_unref (button_data->drag_info.target_location);
1443 button_data->drag_info.target_location = NULL((void*)0);
1444
1445 g_free (button_data);
1446}
1447
1448static const char *
1449get_dir_name (ButtonData *button_data)
1450{
1451 if (button_data->type == DESKTOP_BUTTON)
1452 {
1453 return _("Desktop")dcgettext (((void*)0), "Desktop", 5);
1454 }
1455 else
1456 {
1457 return button_data->dir_name;
1458 }
1459}
1460
1461/* We always want to request the same size for the label, whether
1462 * or not the contents are bold
1463 */
1464static void
1465set_label_padding_size (ButtonData *button_data)
1466{
1467 const gchar *dir_name = get_dir_name (button_data);
1468 PangoLayout *layout;
1469 gint width, height, bold_width, bold_height;
1470 gint pad_left, pad_right;
1471 gchar *markup;
1472
1473 layout = gtk_widget_create_pango_layout (button_data->label, dir_name);
1474 pango_layout_get_pixel_size (layout, &width, &height);
1475
1476 markup = g_markup_printf_escaped ("<b>%s</b>", dir_name);
1477 pango_layout_set_markup (layout, markup, -1);
1478 g_free (markup);
1479
1480 pango_layout_get_pixel_size (layout, &bold_width, &bold_height);
1481
1482 pad_left = (bold_width - width) / 2;
1483 pad_right = (bold_width + 1 - width) / 2; /* this ensures rounding up - the
1484 pixel size difference between bold and normal fonts is not always even and
1485 will give an off-by-one error when dividing by 2 */
1486
1487 gtk_widget_set_margin_start (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), pad_left);
1488 gtk_widget_set_margin_end (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), pad_right);
1489
1490 g_object_unref (layout);
1491}
1492
1493static void
1494caja_path_bar_update_button_appearance (ButtonData *button_data)
1495{
1496 const gchar *dir_name = get_dir_name (button_data);
1497
1498 if (button_data->label != NULL((void*)0))
1499 {
1500 if (gtk_label_get_use_markup (GTK_LABEL (button_data->label)((((GtkLabel*) (void *) ((button_data->label)))))))
1501 {
1502 char *markup;
1503
1504 markup = g_markup_printf_escaped ("<b>%s</b>", dir_name);
1505 gtk_label_set_markup (GTK_LABEL (button_data->label)((((GtkLabel*) (void *) ((button_data->label))))), markup);
1506
1507 gtk_widget_set_margin_end (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), 0);
1508 gtk_widget_set_margin_start (GTK_WIDGET (button_data->label)((((GtkWidget*) (void *) ((button_data->label))))), 0);
1509 g_free(markup);
1510 }
1511 else
1512 {
1513 gtk_label_set_text (GTK_LABEL (button_data->label)((((GtkLabel*) (void *) ((button_data->label))))), dir_name);
1514 set_label_padding_size (button_data);
1515 }
1516 }
1517
1518 if (button_data->image != NULL((void*)0))
1519 {
1520 if (button_data->custom_icon)
1521 {
1522 gtk_image_set_from_surface (GTK_IMAGE (button_data->image)((((GtkImage*) (void *) ((button_data->image))))), button_data->custom_icon);
1523 gtk_widget_show (GTK_WIDGET (button_data->image)((((GtkWidget*) (void *) ((button_data->image))))));
1524 }
1525 else
1526 {
1527 CajaIconInfo *icon_info;
1528 cairo_surface_t *surface;
1529
1530 icon_info = get_type_icon_info (button_data);
1531 surface = NULL((void*)0);
1532
1533 if (icon_info != NULL((void*)0))
1534 {
1535 surface = caja_icon_info_get_surface_at_size (icon_info, CAJA_PATH_BAR_ICON_SIZE16);
1536 g_object_unref (icon_info);
1537 }
1538
1539 if (surface != NULL((void*)0))
1540 {
1541 gtk_image_set_from_surface (GTK_IMAGE (button_data->image)((((GtkImage*) (void *) ((button_data->image))))), surface);
1542 gtk_style_context_add_class (gtk_widget_get_style_context (button_data->button),
1543 "image-button");
1544 gtk_widget_show (GTK_WIDGET (button_data->image)((((GtkWidget*) (void *) ((button_data->image))))));
1545 cairo_surface_destroy (surface);
1546 }
1547 else
1548 {
1549 gtk_widget_hide (GTK_WIDGET (button_data->image)((((GtkWidget*) (void *) ((button_data->image))))));
1550 gtk_style_context_remove_class (gtk_widget_get_style_context (button_data->button),
1551 "image-button");
1552 }
1553 }
1554 }
1555
1556}
1557
1558static void
1559caja_path_bar_update_button_state (ButtonData *button_data,
1560 gboolean current_dir)
1561{
1562 if (button_data->label != NULL((void*)0))
1563 {
1564 g_object_set (button_data->label, "use-markup", current_dir, NULL((void*)0));
1565 }
1566
1567 caja_path_bar_update_button_appearance (button_data);
1568
1569 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button_data->button)((((GtkToggleButton*) (void *) ((button_data->button)))))) != current_dir)
1570 {
1571 button_data->ignore_changes = TRUE(!(0));
1572 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_data->button)((((GtkToggleButton*) (void *) ((button_data->button))))), current_dir);
1573 button_data->ignore_changes = FALSE(0);
1574 }
1575}
1576
1577static gboolean
1578setup_file_path_mounted_mount (GFile *location, ButtonData *button_data)
1579{
1580 GVolumeMonitor *volume_monitor;
1581 GList *mounts, *l;
1582 gboolean result;
1583 GIcon *icon;
1584 CajaIconInfo *info;
1585 GFile *root, *default_location;
1586 gint scale;
1587 GMount *mount = NULL((void*)0);
1588
1589 /* Return false if button has not been set up yet or has been destroyed*/
1590 if (!button_data->button)
1591 return FALSE(0);
1592 result = FALSE(0);
1593 volume_monitor = g_volume_monitor_get ();
1594 mounts = g_volume_monitor_get_mounts (volume_monitor);
1595
1596 scale = gtk_widget_get_scale_factor (GTK_WIDGET (button_data->button)((((GtkWidget*) (void *) ((button_data->button))))));
1597 for (l = mounts; l != NULL((void*)0); l = l->next)
1598 {
1599 mount = l->data;
1600 if (g_mount_is_shadowed (mount))
1601 {
1602 continue;
1603 }
1604 if (result)
1605 {
1606 continue;
1607 }
1608 root = g_mount_get_root (mount);
1609 if (g_file_equal (location, root))
1610 {
1611 result = TRUE(!(0));
1612 /* set mount specific details in button_data */
1613 icon = g_mount_get_icon (mount);
1614 if (icon == NULL((void*)0))
1615 {
1616 icon = g_themed_icon_new (CAJA_ICON_FOLDER"folder");
1617 }
1618 info = caja_icon_info_lookup (icon, CAJA_PATH_BAR_ICON_SIZE16, scale);
1619 g_object_unref (icon);
1620 button_data->custom_icon = caja_icon_info_get_surface_at_size (info, CAJA_PATH_BAR_ICON_SIZE16);
1621 g_object_unref (info);
1622 button_data->dir_name = g_mount_get_name (mount);
1623 button_data->type = MOUNT_BUTTON;
1624 button_data->fake_root = TRUE(!(0));
1625 g_object_unref (root);
1626 break;
1627 }
1628 default_location = g_mount_get_default_location (mount);
1629 if (!g_file_equal (default_location, root) &&
1630 g_file_equal (location, default_location))
1631 {
1632 result = TRUE(!(0));
1633 /* set mount specific details in button_data */
1634 icon = g_mount_get_icon (mount);
1635 if (icon == NULL((void*)0))
1636 {
1637 icon = g_themed_icon_new (CAJA_ICON_FOLDER"folder");
1638 }
1639 info = caja_icon_info_lookup (icon, CAJA_PATH_BAR_ICON_SIZE16, scale);
1640 g_object_unref (icon);
1641 button_data->custom_icon = caja_icon_info_get_surface_at_size (info, CAJA_PATH_BAR_ICON_SIZE16);
1642 g_object_unref (info);
1643 button_data->type = DEFAULT_LOCATION_BUTTON;
1644 button_data->fake_root = TRUE(!(0));
1645 g_object_unref (default_location);
1646 g_object_unref (root);
1647 break;
1648 }
1649 g_object_unref (default_location);
1650 g_object_unref (root);
1651 }
1652 g_list_free_full (mounts, g_object_unref);
1653 return result;
1654}
1655
1656static void
1657setup_button_type (ButtonData *button_data,
1658 CajaPathBar *path_bar,
1659 GFile *location)
1660{
1661 if (path_bar->root_path != NULL((void*)0) && g_file_equal (location, path_bar->root_path))
1662 {
1663 button_data->type = ROOT_BUTTON;
1664 }
1665 else if (path_bar->home_path != NULL((void*)0) && g_file_equal (location, path_bar->home_path))
1666 {
1667 button_data->type = HOME_BUTTON;
1668 button_data->fake_root = TRUE(!(0));
1669 }
1670 else if (path_bar->desktop_path != NULL((void*)0) && g_file_equal (location, path_bar->desktop_path))
1671 {
1672 if (!desktop_is_home)
1673 {
1674 button_data->type = DESKTOP_BUTTON;
1675 }
1676 else
1677 {
1678 button_data->type = NORMAL_BUTTON;
1679 }
1680 }
1681 else if (setup_file_path_mounted_mount (location, button_data))
1682 {
1683 /* already setup */
1684 }
1685 else
1686 {
1687 button_data->type = NORMAL_BUTTON;
1688 }
1689}
1690
1691static void
1692button_drag_data_get_cb (GtkWidget *widget,
1693 GdkDragContext *context,
1694 GtkSelectionData *selection_data,
1695 guint info,
1696 guint time_,
1697 gpointer user_data)
1698{
1699 ButtonData *button_data;
1700 char *uri_list[2];
1701
1702 button_data = user_data;
1703
1704 uri_list[0] = g_file_get_uri (button_data->path);
1705 uri_list[1] = NULL((void*)0);
1706
1707 if (info == CAJA_ICON_DND_MATE_ICON_LIST)
1708 {
1709 char *tmp;
1710
1711 tmp = g_strdup_printf ("%s\r\n", uri_list[0]);
1712 gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data),
1713 8, tmp, strlen (tmp));
1714 g_free (tmp);
1715 }
1716 else if (info == CAJA_ICON_DND_URI_LIST)
1717 {
1718 gtk_selection_data_set_uris (selection_data, uri_list);
1719 }
1720
1721 g_free (uri_list[0]);
1722}
1723
1724static void
1725setup_button_drag_source (ButtonData *button_data)
1726{
1727 GtkTargetList *target_list;
1728 const GtkTargetEntry targets[] =
1729 {
1730 { CAJA_ICON_DND_MATE_ICON_LIST_TYPE"x-special/mate-icon-list", 0, CAJA_ICON_DND_MATE_ICON_LIST }
1731 };
1732
1733 gtk_drag_source_set (button_data->button,
1734 GDK_BUTTON1_MASK |
1735 GDK_BUTTON2_MASK,
1736 NULL((void*)0), 0,
1737 GDK_ACTION_MOVE |
1738 GDK_ACTION_COPY |
1739 GDK_ACTION_LINK |
1740 GDK_ACTION_ASK);
1741
1742 target_list = gtk_target_list_new (targets, G_N_ELEMENTS (targets)(sizeof (targets) / sizeof ((targets)[0])));
1743 gtk_target_list_add_uri_targets (target_list, CAJA_ICON_DND_URI_LIST);
1744 gtk_drag_source_set_target_list (button_data->button, target_list);
1745 gtk_target_list_unref (target_list);
1746
1747 g_signal_connect (button_data->button, "drag-data-get",g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
1748 G_CALLBACK (button_drag_data_get_cb),g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
1749 button_data)g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
;
1750}
1751
1752static void
1753button_data_file_changed (CajaFile *file,
1754 ButtonData *button_data)
1755{
1756 GFile *location, *current_location;
1757 ButtonData *current_button_data;
1758 CajaPathBar *path_bar;
1759 gboolean renamed, child;
1760
1761 path_bar = (CajaPathBar *) gtk_widget_get_ancestor (button_data->button,
1762 CAJA_TYPE_PATH_BAR(caja_path_bar_get_type ()));
1763 if (path_bar == NULL((void*)0))
1764 {
1765 return;
1766 }
1767
1768 g_return_if_fail (path_bar->current_path != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if (path_bar->current_path != ((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__)), "path_bar->current_path != NULL"); return;
} } while (0)
;
1769 g_return_if_fail (path_bar->current_button_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if (path_bar->current_button_data != ((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__)), "path_bar->current_button_data != NULL"); return
; } } while (0)
;
1770
1771 current_button_data = path_bar->current_button_data;
1772
1773 location = caja_file_get_location (file);
1774 if (!g_file_equal (button_data->path, location))
1775 {
1776 GFile *parent, *button_parent;
1777
1778 parent = g_file_get_parent (location);
1779 button_parent = g_file_get_parent (button_data->path);
1780
1781 renamed = (parent != NULL((void*)0) && button_parent != NULL((void*)0)) &&
1782 g_file_equal (parent, button_parent);
1783
1784 if (parent != NULL((void*)0))
1785 {
1786 g_object_unref (parent);
1787 }
1788 if (button_parent != NULL((void*)0))
1789 {
1790 g_object_unref (button_parent);
1791 }
1792
1793 if (renamed)
1794 {
1795 button_data->path = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
1796 }
1797 else
1798 {
1799 /* the file has been moved.
1800 * If it was below the currently displayed location, remove it.
1801 * If it was not below the currently displayed location, update the path bar
1802 */
1803 child = g_file_has_prefix (button_data->path,
1804 path_bar->current_path);
1805
1806 if (child)
1807 {
1808 /* moved file inside current path hierarchy */
1809 g_object_unref (location);
1810 location = g_file_get_parent (button_data->path);
1811 current_location = g_object_ref (path_bar->current_path)((__typeof__ (path_bar->current_path)) (g_object_ref) (path_bar
->current_path))
;
1812 }
1813 else
1814 {
1815 /* moved current path, or file outside current path hierarchy.
1816 * Update path bar to new locations.
1817 */
1818 current_location = caja_file_get_location (current_button_data->file);
1819 }
1820
1821 caja_path_bar_update_path (path_bar, location, FALSE(0));
1822 caja_path_bar_set_path (path_bar, current_location);
1823 g_object_unref (location);
1824 g_object_unref (current_location);
1825 return;
1826 }
1827 }
1828 else if (caja_file_is_gone (file))
1829 {
1830 gint idx, position;
1831
1832 /* if the current or a parent location are gone, don't do anything, as the view
1833 * will get the event too and call us back.
1834 */
1835 current_location = caja_file_get_location (current_button_data->file);
1836
1837 if (g_file_has_prefix (location, current_location))
1838 {
1839 /* remove this and the following buttons */
1840 position = g_list_position (path_bar->button_list,
1841 g_list_find (path_bar->button_list, button_data));
1842
1843 if (position != -1)
1844 {
1845 for (idx = 0; idx <= position; idx++)
1846 {
1847 gtk_container_remove (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))),
1848 BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button);
1849 }
1850 }
1851 }
1852
1853 g_object_unref (current_location);
1854 g_object_unref (location);
1855 return;
1856 }
1857 g_object_unref (location);
1858
1859 /* MOUNTs use the GMount as the name, so don't update for those */
1860 if (button_data->type != MOUNT_BUTTON)
1861 {
1862 char *display_name;
1863
1864 display_name = caja_file_get_display_name (file);
1865 if (g_strcmp0 (display_name, button_data->dir_name) != 0)
1866 {
1867 g_free (button_data->dir_name);
1868 button_data->dir_name = g_strdup (display_name)g_strdup_inline (display_name);
1869 }
1870
1871 g_free (display_name);
1872 }
1873 caja_path_bar_update_button_appearance (button_data);
1874}
1875
1876static ButtonData *
1877make_directory_button (CajaPathBar *path_bar,
1878 CajaFile *file,
1879 gboolean current_dir,
1880 gboolean base_dir,
1881 gboolean file_is_hidden)
1882{
1883 GFile *path;
1884 GtkWidget *child;
1885 ButtonData *button_data;
1886
1887 path = caja_file_get_location (file);
1888
1889 child = NULL((void*)0);
1890
1891 file_is_hidden = !! file_is_hidden;
1892 /* Is it a special button? */
1893 button_data = g_new0 (ButtonData, 1)(ButtonData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (ButtonData); 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; }))
;
1894
1895 setup_button_type (button_data, path_bar, path);
1896 button_data->button = gtk_toggle_button_new ();
1897 gtk_style_context_add_class (gtk_widget_get_style_context (button_data->button),
1898 "text-button");
1899 gtk_widget_set_focus_on_click (button_data->button, FALSE(0));
1900 gtk_widget_add_events (button_data->button, GDK_SCROLL_MASK);
1901 /* TODO update button type when xdg directories change */
1902
1903 button_data->drag_info.target_location = g_object_ref (path)((__typeof__ (path)) (g_object_ref) (path));
1904
1905 button_data->image = gtk_image_new ();
1906
1907 switch (button_data->type)
1908 {
1909 case ROOT_BUTTON:
1910 /* Fall through */
1911 case HOME_BUTTON:
1912 /* Fall through */
1913 case DESKTOP_BUTTON:
1914 /* Fall through */
1915 case MOUNT_BUTTON:
1916 /* Fall through */
1917 case DEFAULT_LOCATION_BUTTON:
1918 button_data->label = gtk_label_new (NULL((void*)0));
1919 child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
1920 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->image, FALSE(0), FALSE(0), 0);
1921 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->label, FALSE(0), FALSE(0), 0);
1922
1923 break;
1924 case NORMAL_BUTTON:
1925 default:
1926 button_data->label = gtk_label_new (NULL((void*)0));
1927 child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
1928 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->image, FALSE(0), FALSE(0), 0);
1929 gtk_box_pack_start (GTK_BOX (child)((((GtkBox*) (void *) ((child))))), button_data->label, FALSE(0), FALSE(0), 0);
1930 button_data->is_base_dir = base_dir;
1931 }
1932
1933 if (button_data->path == NULL((void*)0))
1934 {
1935 button_data->path = g_object_ref (path)((__typeof__ (path)) (g_object_ref) (path));
1936 }
1937 if (button_data->dir_name == NULL((void*)0))
1938 {
1939 button_data->dir_name = caja_file_get_display_name (file);
1940 }
1941 if (button_data->file == NULL((void*)0))
1942 {
1943 button_data->file = caja_file_ref (file);
1944 caja_file_monitor_add (button_data->file, button_data,
1945 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
);
1946 button_data->file_changed_signal_id =
1947 g_signal_connect (button_data->file, "changed",g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
1948 G_CALLBACK (button_data_file_changed),g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
1949 button_data)g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
;
1950 }
1951
1952 button_data->file_is_hidden = file_is_hidden;
1953
1954 gtk_container_add (GTK_CONTAINER (button_data->button)((((GtkContainer*) (void *) ((button_data->button))))), child);
1955 gtk_widget_show_all (button_data->button);
1956
1957 caja_path_bar_update_button_state (button_data, current_dir);
1958
1959 g_signal_connect (button_data->button, "clicked", G_CALLBACK (button_clicked_cb), button_data)g_signal_connect_data ((button_data->button), ("clicked"),
(((GCallback) (button_clicked_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1960 g_signal_connect (button_data->button, "button-press-event", G_CALLBACK (button_event_cb), button_data)g_signal_connect_data ((button_data->button), ("button-press-event"
), (((GCallback) (button_event_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1961 g_signal_connect (button_data->button, "button-release-event", G_CALLBACK (button_event_cb), button_data)g_signal_connect_data ((button_data->button), ("button-release-event"
), (((GCallback) (button_event_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1962 g_signal_connect (button_data->button, "drag-begin", G_CALLBACK (button_drag_begin_cb), button_data)g_signal_connect_data ((button_data->button), ("drag-begin"
), (((GCallback) (button_drag_begin_cb))), (button_data), ((void
*)0), (GConnectFlags) 0)
;
1963 g_object_weak_ref (G_OBJECT (button_data->button)((((GObject*) (void *) ((button_data->button))))), (GWeakNotify) button_data_free, button_data);
1964
1965 setup_button_drag_source (button_data);
1966
1967 caja_drag_slot_proxy_init (button_data->button,
1968 &(button_data->drag_info));
1969
1970 g_object_unref (path);
1971
1972 return button_data;
1973}
1974
1975static gboolean
1976caja_path_bar_check_parent_path (CajaPathBar *path_bar,
1977 GFile *location,
1978 ButtonData **current_button_data)
1979{
1980 GList *list;
1981 GList *current_path;
1982 gboolean need_new_fake_root;
1983
1984 current_path = NULL((void*)0);
1985 need_new_fake_root = FALSE(0);
1986
1987 if (current_button_data)
1988 {
1989 *current_button_data = NULL((void*)0);
1990 }
1991
1992 for (list = path_bar->button_list; list; list = list->next)
1993 {
1994 ButtonData *button_data;
1995
1996 button_data = list->data;
1997 if (g_file_equal (location, button_data->path))
1998 {
1999 current_path = list;
2000
2001 if (current_button_data)
2002 {
2003 *current_button_data = button_data;
2004 }
2005 break;
2006 }
2007 if (list == path_bar->fake_root)
2008 {
2009 need_new_fake_root = TRUE(!(0));
2010 }
2011 }
2012
2013 if (current_path)
2014 {
2015
2016 if (need_new_fake_root)
2017 {
2018 path_bar->fake_root = NULL((void*)0);
2019 for (list = current_path; list; list = list->next)
2020 {
2021 ButtonData *button_data;
2022
2023 button_data = list->data;
2024 if (list->prev != NULL((void*)0) &&
2025 button_data->fake_root)
2026 {
2027 path_bar->fake_root = list;
2028 break;
2029 }
2030 }
2031 }
2032
2033 for (list = path_bar->button_list; list; list = list->next)
2034 {
2035
2036 caja_path_bar_update_button_state (BUTTON_DATA (list->data)((ButtonData *)(list->data)),
2037 (list == current_path) ? TRUE(!(0)) : FALSE(0));
2038 }
2039
2040 if (!gtk_widget_get_child_visible (BUTTON_DATA (current_path->data)((ButtonData *)(current_path->data))->button))
2041 {
2042 path_bar->first_scrolled_button = current_path;
2043 gtk_widget_queue_resize (GTK_WIDGET (path_bar)((((GtkWidget*) (void *) ((path_bar))))));
2044 }
2045 return TRUE(!(0));
2046 }
2047 return FALSE(0);
2048}
2049
2050static gboolean
2051caja_path_bar_update_path (CajaPathBar *path_bar,
2052 GFile *file_path,
2053 gboolean emit_signal)
2054{
2055 CajaFile *file, *parent_file;
2056 gboolean first_directory, last_directory;
2057 gboolean result;
2058 GList *new_buttons, *l, *fake_root;
2059 ButtonData *button_data, *current_button_data;
2060
2061 g_return_val_if_fail (CAJA_IS_PATH_BAR (path_bar), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((caja_path_bar_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_37
= 1; else _g_boolean_var_37 = 0; _g_boolean_var_37; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_PATH_BAR (path_bar)"); return ((0));
} } while (0)
;
2062 g_return_val_if_fail (file_path != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if (file_path != ((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__)), "file_path != NULL"
); return ((0)); } } while (0)
;
2063
2064 fake_root = NULL((void*)0);
2065 result = TRUE(!(0));
2066 first_directory = TRUE(!(0));
2067 new_buttons = NULL((void*)0);
2068 current_button_data = NULL((void*)0);
2069
2070 file = caja_file_get (file_path);
2071
2072 while (file != NULL((void*)0))
2073 {
2074 parent_file = caja_file_get_parent (file);
2075 last_directory = !parent_file;
2076 button_data = make_directory_button (path_bar, file, first_directory, last_directory, FALSE(0));
2077 caja_file_unref (file);
2078
2079 if (first_directory)
2080 {
2081 current_button_data = button_data;
2082 }
2083
2084 new_buttons = g_list_prepend (new_buttons, button_data);
2085
2086 if (parent_file != NULL((void*)0) &&
2087 button_data->fake_root)
2088 {
2089 fake_root = new_buttons;
2090 }
2091
2092 file = parent_file;
2093 first_directory = FALSE(0);
2094 }
2095
2096 caja_path_bar_clear_buttons (path_bar);
2097 path_bar->button_list = g_list_reverse (new_buttons);
2098 path_bar->fake_root = fake_root;
2099
2100 for (l = path_bar->button_list; l; l = l->next)
2101 {
2102 GtkWidget *button;
2103 button = BUTTON_DATA (l->data)((ButtonData *)(l->data))->button;
2104 gtk_container_add (GTK_CONTAINER (path_bar)((((GtkContainer*) (void *) ((path_bar))))), button);
2105 }
2106
2107 if (path_bar->current_path != NULL((void*)0))
2108 {
2109 g_object_unref (path_bar->current_path);
2110 }
2111
2112 path_bar->current_path = g_object_ref (file_path)((__typeof__ (file_path)) (g_object_ref) (file_path));
2113
2114 path_bar->current_button_data = current_button_data;
2115
2116 return result;
2117}
2118
2119gboolean
2120caja_path_bar_set_path (CajaPathBar *path_bar, GFile *file_path)
2121{
2122 ButtonData *button_data;
2123
2124 g_return_val_if_fail (CAJA_IS_PATH_BAR (path_bar), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((caja_path_bar_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_39
= 1; else _g_boolean_var_39 = 0; _g_boolean_var_39; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_PATH_BAR (path_bar)"); return ((0));
} } while (0)
;
2125 g_return_val_if_fail (file_path != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_40
; if (file_path != ((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__)), "file_path != NULL"
); return ((0)); } } while (0)
;
2126
2127 /* Check whether the new path is already present in the pathbar as buttons.
2128 * This could be a parent directory or a previous selected subdirectory. */
2129 if (caja_path_bar_check_parent_path (path_bar, file_path, &button_data))
2130 {
2131 if (path_bar->current_path != NULL((void*)0))
2132 {
2133 g_object_unref (path_bar->current_path);
2134 }
2135
2136 path_bar->current_path = g_object_ref (file_path)((__typeof__ (file_path)) (g_object_ref) (file_path));
2137 path_bar->current_button_data = button_data;
2138
2139 return TRUE(!(0));
2140 }
2141
2142 return caja_path_bar_update_path (path_bar, file_path, TRUE(!(0)));
2143}
2144
2145GFile *
2146caja_path_bar_get_path_for_button (CajaPathBar *path_bar,
2147 GtkWidget *button)
2148{
2149 GList *list;
2150
2151 g_return_val_if_fail (CAJA_IS_PATH_BAR (path_bar), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_41
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((caja_path_bar_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_41
= 1; else _g_boolean_var_41 = 0; _g_boolean_var_41; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "CAJA_IS_PATH_BAR (path_bar)"); return (((void
*)0)); } } while (0)
;
2152 g_return_val_if_fail (GTK_IS_BUTTON (button), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_42
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); 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; }))))) _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__)), "GTK_IS_BUTTON (button)"); return (((void*)0)
); } } while (0)
;
2153
2154 for (list = path_bar->button_list; list; list = list->next)
2155 {
2156 ButtonData *button_data;
2157 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
2158 if (button_data->button == button)
2159 {
2160 return g_object_ref (button_data->path)((__typeof__ (button_data->path)) (g_object_ref) (button_data
->path))
;
2161 }
2162 }
2163
2164 return NULL((void*)0);
2165}
2166
2167GtkWidget *
2168caja_path_bar_get_button_from_button_list_entry (gpointer entry)
2169{
2170 return BUTTON_DATA(entry)((ButtonData *)(entry))->button;
2171}
diff --git a/2024-07-29-023715-6438-1/report-cf3974.html b/2024-07-29-023715-6438-1/report-cf3974.html new file mode 100644 index 000000000..8030b756c --- /dev/null +++ b/2024-07-29-023715-6438-1/report-cf3974.html @@ -0,0 +1,2089 @@ + + + +eggsmclient-xsmp.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File: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 -fdebug-compilation-dir=/rootdir/mate-submodules/libegg -fcoverage-compilation-dir=/rootdir/mate-submodules/libegg -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I ../.. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/freetype2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/uuid -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -D WITH_GZFILEOP -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/gio-unix-2.0 -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/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/freetype2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/uuid -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -D WITH_GZFILEOP -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/gio-unix-2.0 -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-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 GType 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_pointer (
&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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (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/2024-07-29-023715-6438-1/report-d3c816.html b/2024-07-29-023715-6438-1/report-d3c816.html new file mode 100644 index 000000000..fbbd42c58 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-d3c816.html @@ -0,0 +1,7490 @@ + + + +caja-file-operations.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-file-operations.c
Warning:line 5830, column 32
This statement is never executed
+ +

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 caja-file-operations.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-file-operations.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* caja-file-operations.c - Caja file operations.
4
5 Copyright (C) 1999, 2000 Free Software Foundation
6 Copyright (C) 2000, 2001 Eazel, Inc.
7 Copyright (C) 2007 Red Hat, Inc.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (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 GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public
20 License along with this program; if not, write to the
21 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23
24 Authors: Alexander Larsson <alexl@redhat.com>
25 Ettore Perazzoli <ettore@gnu.org>
26 Pavel Cisler <pavel@eazel.com>
27 */
28
29#include <config.h>
30#include <string.h>
31#include <stdio.h>
32#include <stdarg.h>
33#include <locale.h>
34#include <math.h>
35#include <unistd.h>
36#include <sys/types.h>
37#include <stdlib.h>
38#include <glib/gi18n.h>
39#include <glib/gstdio.h>
40#include <gdk/gdk.h>
41#include <gdk/gdkx.h>
42#include <gtk/gtk.h>
43#include <gio/gio.h>
44#include <glib.h>
45#include <libnotify/notify.h>
46
47#include <eel/eel-glib-extensions.h>
48#include <eel/eel-gtk-extensions.h>
49#include <eel/eel-stock-dialogs.h>
50#include <eel/eel-vfs-extensions.h>
51
52#include "caja-file-operations.h"
53#include "caja-debug-log.h"
54#include "caja-file-changes-queue.h"
55#include "caja-lib-self-check-functions.h"
56#include "caja-progress-info.h"
57#include "caja-file-changes-queue.h"
58#include "caja-file-private.h"
59#include "caja-desktop-icon-file.h"
60#include "caja-desktop-link-monitor.h"
61#include "caja-global-preferences.h"
62#include "caja-link.h"
63#include "caja-autorun.h"
64#include "caja-trash-monitor.h"
65#include "caja-file-utilities.h"
66#include "caja-file-conflict-dialog.h"
67#include "caja-undostack-manager.h"
68#include "caja-metadata.h"
69
70/* TODO: TESTING!!! */
71
72typedef struct {
73 GIOSchedulerJob *io_job;
74 GTimer *time;
75 GtkWindow *parent_window;
76 int screen_num;
77 int inhibit_cookie;
78 CajaProgressInfo *progress;
79 GCancellable *cancellable;
80 GHashTable *skip_files;
81 GHashTable *skip_readdir_error;
82 gboolean skip_all_error;
83 gboolean skip_all_conflict;
84 gboolean merge_all;
85 gboolean replace_all;
86 gboolean delete_all;
87 CajaUndoStackActionData* undo_redo_data;
88} CommonJob;
89
90typedef struct {
91 CommonJob common;
92 gboolean is_move;
93 GList *files;
94 GFile *destination;
95 GFile *desktop_location;
96 GdkPoint *icon_positions;
97 int n_icon_positions;
98 GHashTable *debuting_files;
99 CajaCopyCallback done_callback;
100 gpointer done_callback_data;
101} CopyMoveJob;
102
103typedef struct {
104 CommonJob common;
105 GList *files;
106 gboolean try_trash;
107 gboolean user_cancel;
108 CajaDeleteCallback done_callback;
109 gpointer done_callback_data;
110} DeleteJob;
111
112typedef struct {
113 CommonJob common;
114 GFile *dest_dir;
115 char *filename;
116 gboolean make_dir;
117 GFile *src;
118 char *src_data;
119 int length;
120 GdkPoint position;
121 gboolean has_position;
122 GFile *created_file;
123 CajaCreateCallback done_callback;
124 gpointer done_callback_data;
125} CreateJob;
126
127
128typedef struct {
129 CommonJob common;
130 GList *trash_dirs;
131 gboolean should_confirm;
132 CajaOpCallback done_callback;
133 gpointer done_callback_data;
134} EmptyTrashJob;
135
136typedef struct {
137 CommonJob common;
138 GFile *file;
139 gboolean interactive;
140 CajaOpCallback done_callback;
141 gpointer done_callback_data;
142} MarkTrustedJob;
143
144typedef struct {
145 CommonJob common;
146 GFile *file;
147 CajaOpCallback done_callback;
148 gpointer done_callback_data;
149 guint32 file_permissions;
150 guint32 file_mask;
151 guint32 dir_permissions;
152 guint32 dir_mask;
153} SetPermissionsJob;
154
155typedef enum {
156 OP_KIND_COPY,
157 OP_KIND_MOVE,
158 OP_KIND_DELETE,
159 OP_KIND_TRASH
160} OpKind;
161
162typedef struct {
163 int num_files;
164 goffset num_bytes;
165 int num_files_since_progress;
166 OpKind op;
167} SourceInfo;
168
169typedef struct {
170 int num_files;
171 goffset num_bytes;
172 OpKind op;
173 guint64 last_report_time;
174 int last_reported_files_left;
175} TransferInfo;
176
177#define SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15 15
178#define NSEC_PER_MICROSEC1000 1000
179
180#define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50 50
181
182#define IS_IO_ERROR(__error, KIND)(((__error)->domain == g_io_error_quark() && (__error
)->code == G_IO_ERROR_KIND))
(((__error)->domain == G_IO_ERRORg_io_error_quark() && (__error)->code == G_IO_ERROR_ ## KIND))
183
184#define CANCELdcgettext (((void*)0), "_Cancel", 5) _("_Cancel")dcgettext (((void*)0), "_Cancel", 5)
185#define SKIPdcgettext (((void*)0), "_Skip", 5) _("_Skip")dcgettext (((void*)0), "_Skip", 5)
186#define SKIP_ALLdcgettext (((void*)0), "S_kip All", 5) _("S_kip All")dcgettext (((void*)0), "S_kip All", 5)
187#define RETRYdcgettext (((void*)0), "_Retry", 5) _("_Retry")dcgettext (((void*)0), "_Retry", 5)
188#define DELETEdcgettext (((void*)0), "_Delete", 5) _("_Delete")dcgettext (((void*)0), "_Delete", 5)
189#define DELETE_ALLdcgettext (((void*)0), "Delete _All", 5) _("Delete _All")dcgettext (((void*)0), "Delete _All", 5)
190#define REPLACE_ALLdcgettext (((void*)0), "Replace _All", 5) _("Replace _All")dcgettext (((void*)0), "Replace _All", 5)
191#define MERGE_ALLdcgettext (((void*)0), "Merge _All", 5) _("Merge _All")dcgettext (((void*)0), "Merge _All", 5)
192#define COPY_FORCEdcgettext (((void*)0), "Copy _Anyway", 5) _("Copy _Anyway")dcgettext (((void*)0), "Copy _Anyway", 5)
193
194NotifyNotification *unmount_notify;
195
196void
197caja_application_notify_unmount_show (const gchar *message)
198{
199 gchar **strings;
200 strings = g_strsplit (message, "\n", 0);
201
202 if (!g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_NOTIFICATIONS"show-notifications")) return;
203
204 if (unmount_notify == NULL((void*)0)) {
205 unmount_notify =
206 notify_notification_new (strings[0], strings[1],
207 "media-removable");
208
209 notify_notification_set_hint (unmount_notify,
210 "transient", g_variant_new_boolean (TRUE(!(0))));
211 notify_notification_set_urgency (unmount_notify,
212 NOTIFY_URGENCY_CRITICAL);
213 } else {
214 notify_notification_update (unmount_notify,
215 strings[0], strings[1],
216 "media-removable");
217 }
218
219 notify_notification_show (unmount_notify, NULL((void*)0));
220 g_strfreev (strings);
221}
222
223static void
224mark_desktop_file_trusted (CommonJob *common,
225 GCancellable *cancellable,
226 GFile *file,
227 gboolean interactive);
228
229static gboolean
230is_all_button_text (const char *button_text)
231{
232 g_assert (button_text != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_70
; if (button_text != ((void*)0)) _g_boolean_var_70 = 1; else _g_boolean_var_70
= 0; _g_boolean_var_70; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 232, ((const char*)
(__func__)), "button_text != NULL"); } while (0)
;
233
234 return !strcmp (button_text, SKIP_ALLdcgettext (((void*)0), "S_kip All", 5)) ||
235 !strcmp (button_text, REPLACE_ALLdcgettext (((void*)0), "Replace _All", 5)) ||
236 !strcmp (button_text, DELETE_ALLdcgettext (((void*)0), "Delete _All", 5)) ||
237 !strcmp (button_text, MERGE_ALLdcgettext (((void*)0), "Merge _All", 5));
238}
239
240static void scan_sources (GList *files,
241 SourceInfo *source_info,
242 CommonJob *job,
243 OpKind kind);
244
245
246static gboolean empty_trash_job (GIOSchedulerJob *io_job,
247 GCancellable *cancellable,
248 gpointer user_data);
249
250static char * query_fs_type (GFile *file,
251 GCancellable *cancellable);
252
253/* keep in time with format_time()
254 *
255 * This counts and outputs the number of “time units”
256 * formatted and displayed by format_time().
257 * For instance, if format_time outputs “3 hours, 4 minutes”
258 * it yields 7.
259 */
260static int
261seconds_count_format_time_units (int seconds)
262{
263 int minutes;
264 int hours;
265
266 if (seconds < 0) {
267 /* Just to make sure... */
268 seconds = 0;
269 }
270
271 if (seconds < 60) {
272 /* seconds */
273 return seconds;
274 }
275
276 if (seconds < 60*60) {
277 /* minutes */
278 minutes = seconds / 60;
279 return minutes;
280 }
281
282 hours = seconds / (60*60);
283
284 if (seconds < 60*60*4) {
285 /* minutes + hours */
286 minutes = (seconds - hours * 60 * 60) / 60;
287 return minutes + hours;
288 }
289
290 return hours;
291}
292
293static char *
294format_time (int seconds)
295{
296 int minutes;
297 int hours;
298
299 if (seconds < 0) {
300 /* Just to make sure... */
301 seconds = 0;
302 }
303
304 if (seconds < 60) {
305 return g_strdup_printf (ngettext ("%'d second","%'d seconds", (int) seconds)dcngettext (((void*)0), "%'d second", "%'d seconds", (int) seconds
, 5)
, (int) seconds);
306 }
307
308 if (seconds < 60*60) {
309 minutes = seconds / 60;
310 return g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes)dcngettext (((void*)0), "%'d minute", "%'d minutes", minutes,
5)
, minutes);
311 }
312
313 hours = seconds / (60*60);
314
315 if (seconds < 60*60*4) {
316 char *h, *m;
317 char *res;
318
319 minutes = (seconds - hours * 60 * 60) / 60;
320
321 h = g_strdup_printf (ngettext ("%'d hour", "%'d hours", hours)dcngettext (((void*)0), "%'d hour", "%'d hours", hours, 5), hours);
322 m = g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes)dcngettext (((void*)0), "%'d minute", "%'d minutes", minutes,
5)
, minutes);
323 res = g_strconcat (h, ", ", m, NULL((void*)0));
324 g_free (h);
325 g_free (m);
326 return res;
327 }
328
329 return g_strdup_printf (ngettext ("approximately %'d hour",dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
330 "approximately %'d hours",dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
331 hours)dcngettext (((void*)0), "approximately %'d hour", "approximately %'d hours"
, hours, 5)
, hours);
332}
333
334static char *
335shorten_utf8_string (const char *base, int reduce_by_num_bytes)
336{
337 int len;
338 char *ret;
339 const char *p;
340
341 len = strlen (base);
342 len -= reduce_by_num_bytes;
343
344 if (len <= 0) {
345 return NULL((void*)0);
346 }
347
348 ret = g_new (char, len + 1)(char *) (__extension__ ({ gsize __n = (gsize) (len + 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;
}))
;
349
350 p = base;
351 while (len) {
352 char *next;
353 next = g_utf8_next_char (p)(char *)((p) + g_utf8_skip[*(const guchar *)(p)]);
354 if (next - p > len || *next == '\0') {
355 break;
356 }
357
358 len -= next - p;
359 p = next;
360 }
361
362 if (p - base == 0) {
363 g_free (ret);
364 return NULL((void*)0);
365 } else {
366 memcpy (ret, base, p - base);
367 ret[p - base] = '\0';
368 return ret;
369 }
370}
371
372/* Note that we have these two separate functions with separate format
373 * strings for ease of localization.
374 */
375
376static char *
377get_link_name (const char *name, int count, int max_length)
378{
379 const char *format;
380 char *result;
381 int unshortened_length;
382 gboolean use_count;
383
384 g_assert (name != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_71
; if (name != ((void*)0)) _g_boolean_var_71 = 1; else _g_boolean_var_71
= 0; _g_boolean_var_71; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 384, ((const char*)
(__func__)), "name != NULL"); } while (0)
;
385
386 if (count < 0) {
387 g_warning ("bad count in get_link_name");
388 count = 0;
389 }
390
391 if (count <= 2) {
392 /* Handle special cases for low numbers.
393 * Perhaps for some locales we will need to add more.
394 */
395 switch (count) {
396 default:
397 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 397, ((const char*) (__func__)), ((void*)0)); } while (0)
;
398 /* fall through */
399 case 0:
400 /* duplicate original file name */
401 format = "%s";
402 break;
403 case 1:
404 /* appended to new link file */
405 format = _("Link to %s")dcgettext (((void*)0), "Link to %s", 5);
406 break;
407 case 2:
408 /* appended to new link file */
409 format = _("Another link to %s")dcgettext (((void*)0), "Another link to %s", 5);
410 break;
411 }
412
413 use_count = FALSE(0);
414 } else {
415 /* Handle special cases for the first few numbers of each ten.
416 * For locales where getting this exactly right is difficult,
417 * these can just be made all the same as the general case below.
418 */
419 switch (count % 10) {
420 case 1:
421 /* Translators: Feel free to leave out the "st" suffix
422 * if there's no way to do that nicely for a
423 * particular language.
424 */
425 format = _("%'dst link to %s")dcgettext (((void*)0), "%'dst link to %s", 5);
426 break;
427 case 2:
428 /* appended to new link file */
429 format = _("%'dnd link to %s")dcgettext (((void*)0), "%'dnd link to %s", 5);
430 break;
431 case 3:
432 /* appended to new link file */
433 format = _("%'drd link to %s")dcgettext (((void*)0), "%'drd link to %s", 5);
434 break;
435 default:
436 /* appended to new link file */
437 format = _("%'dth link to %s")dcgettext (((void*)0), "%'dth link to %s", 5);
438 break;
439 }
440
441 use_count = TRUE(!(0));
442 }
443
444 if (use_count)
445 result = g_strdup_printf (format, count, name);
446 else
447 result = g_strdup_printf (format, name);
448
449 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
450 char *new_name;
451
452 new_name = shorten_utf8_string (name, unshortened_length - max_length);
453 if (new_name) {
454 g_free (result);
455
456 if (use_count)
457 result = g_strdup_printf (format, count, new_name);
458 else
459 result = g_strdup_printf (format, new_name);
460
461 g_assert (strlen (result) <= max_length)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_72
; if (strlen (result) <= max_length) _g_boolean_var_72 = 1
; else _g_boolean_var_72 = 0; _g_boolean_var_72; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 461, ((const char*) (__func__)), "strlen (result) <= max_length"
); } while (0)
;
462 g_free (new_name);
463 }
464 }
465
466 return result;
467}
468
469
470/* Translators:
471 * Feel free to leave out the st, nd, rd and th suffix or
472 * make some or all of them match.
473 */
474
475/* Translators: tag used to detect the first copy of a file */
476static const char untranslated_copy_duplicate_tag[] = N_(" (copy)")(" (copy)");
477/* Translators: tag used to detect the second copy of a file */
478static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)")(" (another copy)");
479
480/* Translators: tag used to detect the x11th copy of a file */
481static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
482/* Translators: tag used to detect the x12th copy of a file */
483static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
484/* Translators: tag used to detect the x13th copy of a file */
485static const char untranslated_x13th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
486
487/* Translators: tag used to detect the x1st copy of a file */
488static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)")("st copy)");
489/* Translators: tag used to detect the x2nd copy of a file */
490static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)")("nd copy)");
491/* Translators: tag used to detect the x3rd copy of a file */
492static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)")("rd copy)");
493
494/* Translators: tag used to detect the xxth copy of a file */
495static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)")("th copy)");
496
497#define COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_copy_duplicate_tag, 5) _(untranslated_copy_duplicate_tag)dcgettext (((void*)0), untranslated_copy_duplicate_tag, 5)
498#define ANOTHER_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
_(untranslated_another_copy_duplicate_tag)dcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
499#define X11TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
_(untranslated_x11th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
500#define X12TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
_(untranslated_x12th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
501#define X13TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
_(untranslated_x13th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
502
503#define ST_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5) _(untranslated_st_copy_duplicate_tag)dcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5)
504#define ND_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5) _(untranslated_nd_copy_duplicate_tag)dcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5)
505#define RD_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5) _(untranslated_rd_copy_duplicate_tag)dcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5)
506#define TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5) _(untranslated_th_copy_duplicate_tag)dcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5)
507
508/* Translators: appended to first file copy */
509static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s")("%s (copy)%s");
510/* Translators: appended to second file copy */
511static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s")("%s (another copy)%s");
512
513/* Translators: appended to x11th file copy */
514static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
515/* Translators: appended to x12th file copy */
516static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
517/* Translators: appended to x13th file copy */
518static const char untranslated_x13th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
519
520/* Translators: if in your language there's no difference between 1st, 2nd, 3rd and nth
521 * plurals, you can leave the st, nd, rd suffixes out and just make all the translated
522 * strings look like "%s (copy %'d)%s".
523 */
524
525/* Translators: appended to x1st file copy */
526static const char untranslated_st_copy_duplicate_format[] = N_("%s (%'dst copy)%s")("%s (%'dst copy)%s");
527/* Translators: appended to x2nd file copy */
528static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%'dnd copy)%s")("%s (%'dnd copy)%s");
529/* Translators: appended to x3rd file copy */
530static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%'drd copy)%s")("%s (%'drd copy)%s");
531/* Translators: appended to xxth file copy */
532static const char untranslated_th_copy_duplicate_format[] = N_("%s (%'dth copy)%s")("%s (%'dth copy)%s");
533
534#define FIRST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
_(untranslated_first_copy_duplicate_format)dcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
535#define SECOND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
_(untranslated_second_copy_duplicate_format)dcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
536#define X11TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
_(untranslated_x11th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
537#define X12TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
_(untranslated_x12th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
538#define X13TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
_(untranslated_x13th_copy_duplicate_format)dcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
539
540#define ST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
_(untranslated_st_copy_duplicate_format)dcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
541#define ND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
_(untranslated_nd_copy_duplicate_format)dcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
542#define RD_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
_(untranslated_rd_copy_duplicate_format)dcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
543#define TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
_(untranslated_th_copy_duplicate_format)dcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
544
545static char *
546extract_string_until (const char *original, const char *until_substring)
547{
548 char *result;
549
550 g_assert ((int) strlen (original) >= until_substring - original)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_73
; if ((int) strlen (original) >= until_substring - original
) _g_boolean_var_73 = 1; else _g_boolean_var_73 = 0; _g_boolean_var_73
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 550, ((const char*) (__func__)), "(int) strlen (original) >= until_substring - original"
); } while (0)
;
551 g_assert (until_substring - original >= 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_74
; if (until_substring - original >= 0) _g_boolean_var_74 =
1; else _g_boolean_var_74 = 0; _g_boolean_var_74; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 551, ((const char*) (__func__)), "until_substring - original >= 0"
); } while (0)
;
552
553 result = g_malloc (until_substring - original + 1);
554 strncpy (result, original, until_substring - original);
555 result[until_substring - original] = '\0';
556
557 return result;
558}
559
560/* Dismantle a file name, separating the base name, the file suffix and removing any
561 * (xxxcopy), etc. string. Figure out the count that corresponds to the given
562 * (xxxcopy) substring.
563 */
564static void
565parse_previous_duplicate_name (const char *name,
566 char **name_base,
567 const char **suffix,
568 int *count)
569{
570 const char *tag;
571
572 g_assert (name[0] != '\0')do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_75
; if (name[0] != '\0') _g_boolean_var_75 = 1; else _g_boolean_var_75
= 0; _g_boolean_var_75; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 572, ((const char*)
(__func__)), "name[0] != '\\0'"); } while (0)
;
573
574 *suffix = strchr (name + 1, '.');
575 if (*suffix == NULL((void*)0) || (*suffix)[1] == '\0') {
576 /* no suffix */
577 *suffix = "";
578 }
579
580 tag = strstr (name, COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_copy_duplicate_tag, 5));
581 if (tag != NULL((void*)0)) {
582 if (tag > *suffix) {
583 /* handle case "foo. (copy)" */
584 *suffix = "";
585 }
586 *name_base = extract_string_until (name, tag);
587 *count = 1;
588 return;
589 }
590
591
592 tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_another_copy_duplicate_tag
, 5)
);
593 if (tag != NULL((void*)0)) {
594 if (tag > *suffix) {
595 /* handle case "foo. (another copy)" */
596 *suffix = "";
597 }
598 *name_base = extract_string_until (name, tag);
599 *count = 2;
600 return;
601 }
602
603
604 /* Check to see if we got one of st, nd, rd, th. */
605 tag = strstr (name, X11TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x11th_copy_duplicate_tag,
5)
);
606
607 if (tag == NULL((void*)0)) {
608 tag = strstr (name, X12TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x12th_copy_duplicate_tag,
5)
);
609 }
610 if (tag == NULL((void*)0)) {
611 tag = strstr (name, X13TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_x13th_copy_duplicate_tag,
5)
);
612 }
613
614 if (tag == NULL((void*)0)) {
615 tag = strstr (name, ST_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_st_copy_duplicate_tag, 5));
616 }
617 if (tag == NULL((void*)0)) {
618 tag = strstr (name, ND_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_nd_copy_duplicate_tag, 5));
619 }
620 if (tag == NULL((void*)0)) {
621 tag = strstr (name, RD_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_rd_copy_duplicate_tag, 5));
622 }
623 if (tag == NULL((void*)0)) {
624 tag = strstr (name, TH_COPY_DUPLICATE_TAGdcgettext (((void*)0), untranslated_th_copy_duplicate_tag, 5));
625 }
626
627 /* If we got one of st, nd, rd, th, fish out the duplicate number. */
628 if (tag != NULL((void*)0)) {
629 /* Translators: opening parentheses to match the "th copy)" string */
630 tag = strstr (name, _(" (")dcgettext (((void*)0), " (", 5));
631 if (tag != NULL((void*)0)) {
632 if (tag > *suffix) {
633 /* handle case "foo. (22nd copy)" */
634 *suffix = "";
635 }
636 *name_base = extract_string_until (name, tag);
637 /* Translators: opening parentheses of the "th copy)" string */
638 if (sscanf (tag, _(" (%'d")dcgettext (((void*)0), " (%'d", 5), count) == 1) {
639 if (*count < 1 || *count > 1000000) {
640 /* keep the count within a reasonable range */
641 *count = 0;
642 }
643 return;
644 }
645 *count = 0;
646 return;
647 }
648 }
649
650
651 *count = 0;
652 if (**suffix != '\0') {
653 *name_base = extract_string_until (name, *suffix);
654 } else {
655 *name_base = g_strdup (name)g_strdup_inline (name);
656 }
657}
658
659static char *
660make_next_duplicate_name (const char *base, const char *suffix, int count, int max_length)
661{
662 const char *format;
663 char *result;
664 int unshortened_length;
665 gboolean use_count;
666
667 if (count < 1) {
668 g_warning ("bad count %d in get_duplicate_name", count);
669 count = 1;
670 }
671
672 if (count <= 2) {
673
674 /* Handle special cases for low numbers.
675 * Perhaps for some locales we will need to add more.
676 */
677 switch (count) {
678 default:
679 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 679, ((const char*) (__func__)), ((void*)0)); } while (0)
;
680 /* fall through */
681 case 1:
682 format = FIRST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_first_copy_duplicate_format
, 5)
;
683 break;
684 case 2:
685 format = SECOND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_second_copy_duplicate_format
, 5)
;
686 break;
687
688 }
689
690 use_count = FALSE(0);
691 } else {
692
693 /* Handle special cases for the first few numbers of each ten.
694 * For locales where getting this exactly right is difficult,
695 * these can just be made all the same as the general case below.
696 */
697
698 /* Handle special cases for x11th - x20th.
699 */
700 switch (count % 100) {
701 case 11:
702 format = X11TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x11th_copy_duplicate_format
, 5)
;
703 break;
704 case 12:
705 format = X12TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x12th_copy_duplicate_format
, 5)
;
706 break;
707 case 13:
708 format = X13TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_x13th_copy_duplicate_format
, 5)
;
709 break;
710 default:
711 format = NULL((void*)0);
712 break;
713 }
714
715 if (format == NULL((void*)0)) {
716 switch (count % 10) {
717 case 1:
718 format = ST_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_st_copy_duplicate_format,
5)
;
719 break;
720 case 2:
721 format = ND_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_nd_copy_duplicate_format,
5)
;
722 break;
723 case 3:
724 format = RD_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_rd_copy_duplicate_format,
5)
;
725 break;
726 default:
727 /* The general case. */
728 format = TH_COPY_DUPLICATE_FORMATdcgettext (((void*)0), untranslated_th_copy_duplicate_format,
5)
;
729 break;
730 }
731 }
732
733 use_count = TRUE(!(0));
734
735 }
736
737 if (use_count)
738 result = g_strdup_printf (format, base, count, suffix);
739 else
740 result = g_strdup_printf (format, base, suffix);
741
742 if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
743 char *new_base;
744
745 new_base = shorten_utf8_string (base, unshortened_length - max_length);
746 if (new_base) {
747 g_free (result);
748
749 if (use_count)
750 result = g_strdup_printf (format, new_base, count, suffix);
751 else
752 result = g_strdup_printf (format, new_base, suffix);
753
754 g_assert (strlen (result) <= max_length)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_76
; if (strlen (result) <= max_length) _g_boolean_var_76 = 1
; else _g_boolean_var_76 = 0; _g_boolean_var_76; }), 1)) ; else
g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 754, ((const char*) (__func__)), "strlen (result) <= max_length"
); } while (0)
;
755 g_free (new_base);
756 }
757 }
758
759 return result;
760}
761
762static char *
763get_duplicate_name (const char *name, int count_increment, int max_length)
764{
765 char *result;
766 char *name_base;
767 const char *suffix;
768 int count;
769
770 parse_previous_duplicate_name (name, &name_base, &suffix, &count);
771 result = make_next_duplicate_name (name_base, suffix, count + count_increment, max_length);
772
773 g_free (name_base);
774
775 return result;
776}
777
778static gboolean
779has_invalid_xml_char (char *str)
780{
781 gunichar c;
782
783 while (*str != 0) {
784 c = g_utf8_get_char (str);
785 /* characters XML permits */
786 if (!(c == 0x9 ||
787 c == 0xA ||
788 c == 0xD ||
789 (c >= 0x20 && c <= 0xD7FF) ||
790 (c >= 0xE000 && c <= 0xFFFD) ||
791 (c >= 0x10000 && c <= 0x10FFFF))) {
792 return TRUE(!(0));
793 }
794 str = g_utf8_next_char (str)(char *)((str) + g_utf8_skip[*(const guchar *)(str)]);
795 }
796 return FALSE(0);
797}
798
799
800static char *
801custom_full_name_to_string (char *format, va_list va)
802{
803 GFile *file;
804
805 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
806
807 return g_file_get_parse_name (file);
808}
809
810static void
811custom_full_name_skip (va_list *va)
812{
813 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
814}
815
816static char *
817custom_basename_to_string (char *format, va_list va)
818{
819 GFile *file;
820 GFileInfo *info;
821 char *name, *basename, *tmp;
822
823 file = va_arg (va, GFile *)__builtin_va_arg(va, GFile *);
824
825 info = g_file_query_info (file,
826 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME"standard::display-name",
827 0,
828 g_cancellable_get_current (),
829 NULL((void*)0));
830
831 name = NULL((void*)0);
832 if (info) {
833 name = g_strdup (g_file_info_get_display_name (info))g_strdup_inline (g_file_info_get_display_name (info));
834 g_object_unref (info);
835 }
836
837 if (name == NULL((void*)0)) {
838 basename = g_file_get_basename (file);
839 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
840 name = basename;
841 } else {
842 name = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
843 g_free (basename);
844 }
845 }
846
847 /* Some chars can't be put in the markup we use for the dialogs... */
848 if (has_invalid_xml_char (name)) {
849 tmp = name;
850 name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH"!$&'()*+,;=" ":@" "/", TRUE(!(0)));
851 g_free (tmp);
852 }
853
854 /* Finally, if the string is too long, truncate it. */
855 if (name != NULL((void*)0)) {
856 tmp = name;
857 name = eel_str_middle_truncate (tmp, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH50);
858 g_free (tmp);
859 }
860
861
862 return name;
863}
864
865static void
866custom_basename_skip (va_list *va)
867{
868 (void) va_arg (*va, GFile *)__builtin_va_arg(*va, GFile *);
869}
870
871
872static char *
873custom_size_to_string (char *format, va_list va)
874{
875 goffset size;
876
877 size = va_arg (va, goffset)__builtin_va_arg(va, goffset);
878
879 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units"))
880 return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
881 else
882 return g_format_size(size);
883}
884
885static void
886custom_size_skip (va_list *va)
887{
888 (void) va_arg (*va, goffset)__builtin_va_arg(*va, goffset);
889}
890
891static char *
892custom_time_to_string (char *format, va_list va)
893{
894 int secs;
895
896 secs = va_arg (va, int)__builtin_va_arg(va, int);
897 return format_time (secs);
898}
899
900static void
901custom_time_skip (va_list *va)
902{
903 (void) va_arg (*va, int)__builtin_va_arg(*va, int);
904}
905
906static char *
907custom_mount_to_string (char *format, va_list va)
908{
909 GMount *mount;
910
911 mount = va_arg (va, GMount *)__builtin_va_arg(va, GMount *);
912 return g_mount_get_name (mount);
913}
914
915static void
916custom_mount_skip (va_list *va)
917{
918 (void) va_arg (*va, GMount *)__builtin_va_arg(*va, GMount *);
919}
920
921
922static EelPrintfHandler handlers[] = {
923 { 'F', custom_full_name_to_string, custom_full_name_skip },
924 { 'B', custom_basename_to_string, custom_basename_skip },
925 { 'S', custom_size_to_string, custom_size_skip },
926 { 'T', custom_time_to_string, custom_time_skip },
927 { 'V', custom_mount_to_string, custom_mount_skip },
928 { 0 }
929};
930
931
932static char *
933f (const char *format, ...) {
934 va_list va;
935 char *res;
936
937 va_start (va, format)__builtin_va_start(va, format);
938 res = eel_strdup_vprintf_with_custom (handlers, format, va);
939 va_end (va)__builtin_va_end(va);
940
941 return res;
942}
943
944#define op_job_new(__type, parent_window, should_start, can_pause)((__type *)(init_common (sizeof(__type), parent_window, should_start
, can_pause)))
((__type *)(init_common (sizeof(__type), parent_window, should_start, can_pause)))
945
946static gpointer
947init_common (gsize job_size,
948 GtkWindow *parent_window,
949 gboolean should_start, gboolean can_pause)
950{
951 CommonJob *common;
952
953 /* expected warning with Clang static analyzer: *
954 * "Cast a region whose size is not a multiple of the destination type size" *
955 * *
956 * It is expected for job_size to be larger than sizeof(CommonJob) no matter *
957 * what Clang analyzer reports: we're allocating the whole structure for a job *
958 * (e.g. a TrashJob), but only initializing the common part of it (CommonJob) *
959 * which is a subset of all "real" job structures, structures that all start *
960 * with a CommonJob, and that thus can be used as such. */
961 common = g_malloc0 (job_size);
962
963 if (parent_window) {
964 common->parent_window = parent_window;
965 eel_add_weak_pointer (&common->parent_window);
966 }
967 common->progress = caja_progress_info_new (should_start, can_pause);
968 common->cancellable = caja_progress_info_get_cancellable (common->progress);
969 common->time = g_timer_new ();
970 common->inhibit_cookie = -1;
971 common->screen_num = 0;
972 if (parent_window) {
973 GdkScreen *screen;
974
975 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) (void *) ((parent_window))))));
976 common->screen_num = gdk_x11_screen_get_screen_number (screen);
977 }
978
979 return common;
980}
981
982static void
983finalize_common (CommonJob *common)
984{
985 caja_progress_info_finish (common->progress);
986
987 if (common->inhibit_cookie != -1) {
988 caja_uninhibit_power_manager (common->inhibit_cookie);
989 }
990
991 common->inhibit_cookie = -1;
992 g_timer_destroy (common->time);
993 eel_remove_weak_pointer (&common->parent_window);
994 if (common->skip_files) {
995 g_hash_table_destroy (common->skip_files);
996 }
997 if (common->skip_readdir_error) {
998 g_hash_table_destroy (common->skip_readdir_error);
999 }
1000 // Start UNDO-REDO
1001 caja_undostack_manager_add_action (caja_undostack_manager_instance(),
1002 common->undo_redo_data);
1003 // End UNDO-REDO
1004 g_object_unref (common->progress);
1005 g_object_unref (common->cancellable);
1006 g_free (common);
1007}
1008
1009static void
1010skip_file (CommonJob *common,
1011 GFile *file)
1012{
1013 if (common->skip_files == NULL((void*)0)) {
1014 common->skip_files =
1015 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1016 }
1017
1018 g_hash_table_insert (common->skip_files, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)), file);
1019}
1020
1021static void
1022skip_readdir_error (CommonJob *common,
1023 GFile *dir)
1024{
1025 if (common->skip_readdir_error == NULL((void*)0)) {
1026 common->skip_readdir_error =
1027 g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1028 }
1029
1030 g_hash_table_insert (common->skip_readdir_error, g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir)), dir);
1031}
1032
1033static gboolean
1034should_skip_file (CommonJob *common,
1035 GFile *file)
1036{
1037 if (common->skip_files != NULL((void*)0)) {
1038 return g_hash_table_lookup (common->skip_files, file) != NULL((void*)0);
1039 }
1040
1041 return FALSE(0);
1042}
1043
1044static gboolean
1045should_skip_readdir_error (CommonJob *common,
1046 GFile *dir)
1047{
1048 if (common->skip_readdir_error != NULL((void*)0)) {
1049 return g_hash_table_lookup (common->skip_readdir_error, dir) != NULL((void*)0);
1050 }
1051 return FALSE(0);
1052}
1053
1054static gboolean
1055can_delete_without_confirm (GFile *file)
1056{
1057 if (g_file_has_uri_scheme (file, "burn") ||
1058 g_file_has_uri_scheme (file, "x-caja-desktop")) {
1059 return TRUE(!(0));
1060 }
1061
1062 return FALSE(0);
1063}
1064
1065static gboolean
1066can_delete_files_without_confirm (GList *files)
1067{
1068 g_assert (files != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_77
; if (files != ((void*)0)) _g_boolean_var_77 = 1; else _g_boolean_var_77
= 0; _g_boolean_var_77; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1068, ((const char*
) (__func__)), "files != NULL"); } while (0)
;
1069
1070 while (files != NULL((void*)0)) {
1071 if (!can_delete_without_confirm (files->data)) {
1072 return FALSE(0);
1073 }
1074
1075 files = files->next;
1076 }
1077
1078 return TRUE(!(0));
1079}
1080
1081typedef struct {
1082 GtkWindow **parent_window;
1083 gboolean ignore_close_box;
1084 GtkMessageType message_type;
1085 const char *primary_text;
1086 const char *secondary_text;
1087 const char *details_text;
1088 const char **button_titles;
1089 gboolean show_all;
1090
1091 int result;
1092} RunSimpleDialogData;
1093
1094static gboolean
1095do_run_simple_dialog (gpointer _data)
1096{
1097 RunSimpleDialogData *data = _data;
1098 GtkWidget *dialog;
1099 int result;
1100 int response_id;
1101
1102 /* Create the dialog. */
1103 dialog = gtk_message_dialog_new (*data->parent_window,
1104 0,
1105 data->message_type,
1106 GTK_BUTTONS_NONE,
1107 NULL((void*)0));
1108
1109 g_object_set (dialog,
1110 "text", data->primary_text,
1111 "secondary-text", data->secondary_text,
1112 NULL((void*)0));
1113
1114 for (response_id = 0;
1115 data->button_titles[response_id] != NULL((void*)0);
1116 response_id++) {
1117 const char *button_title;
1118
1119 button_title = data->button_titles[response_id];
1120 if (!data->show_all && is_all_button_text (button_title)) {
1121 continue;
1122 }
1123
1124 if (g_strcmp0 (button_title, CANCELdcgettext (((void*)0), "_Cancel", 5)) == 0)
1125 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, "process-stop", response_id);
1126 else if (g_strcmp0 (button_title, DELETEdcgettext (((void*)0), "_Delete", 5)) == 0)
1127 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, "edit-delete", response_id);
1128 else
1129 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), button_title, response_id);
1130
1131 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), response_id);
1132 }
1133
1134 if (data->details_text) {
1135 eel_gtk_message_dialog_set_details_label (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
1136 data->details_text);
1137 }
1138
1139 /* Run it. */
1140 gtk_widget_show (dialog);
1141 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
1142
1143 while ((result == GTK_RESPONSE_NONE || result == GTK_RESPONSE_DELETE_EVENT) && data->ignore_close_box) {
1144 gtk_widget_show (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
1145 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
1146 }
1147
1148 gtk_widget_destroy (dialog);
1149
1150 data->result = result;
1151
1152 return FALSE(0);
1153}
1154
1155/* NOTE: This frees the primary / secondary strings, in order to
1156 avoid doing that everywhere. So, make sure they are strduped */
1157
1158static int
1159run_simple_dialog_va (CommonJob *job,
1160 gboolean ignore_close_box,
1161 GtkMessageType message_type,
1162 char *primary_text,
1163 char *secondary_text,
1164 const char *details_text,
1165 gboolean show_all,
1166 va_list varargs)
1167{
1168 RunSimpleDialogData *data;
1169 int res;
1170 const char *button_title;
1171 GPtrArray *ptr_array;
1172
1173 g_timer_stop (job->time);
1174
1175 data = g_new0 (RunSimpleDialogData, 1)(RunSimpleDialogData *) (__extension__ ({ gsize __n = (gsize)
(1); gsize __s = sizeof (RunSimpleDialogData); 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; }))
;
1176 data->parent_window = &job->parent_window;
1177 data->ignore_close_box = ignore_close_box;
1178 data->message_type = message_type;
1179 data->primary_text = primary_text;
1180 data->secondary_text = secondary_text;
1181 data->details_text = details_text;
1182 data->show_all = show_all;
1183
1184 ptr_array = g_ptr_array_new ();
1185 while ((button_title = va_arg (varargs, const char *)__builtin_va_arg(varargs, const char *)) != NULL((void*)0)) {
1186 g_ptr_array_add (ptr_array, (char *)button_title);
1187 }
1188 g_ptr_array_add (ptr_array, NULL((void*)0));
1189 data->button_titles = (const char **)g_ptr_array_free (ptr_array, FALSE(0));
1190
1191 caja_progress_info_pause (job->progress);
1192 g_io_scheduler_job_send_to_mainloop (job->io_job,
1193 do_run_simple_dialog,
1194 data,
1195 NULL((void*)0));
1196 caja_progress_info_resume (job->progress);
1197 res = data->result;
1198
1199 g_free (data->button_titles);
1200 g_free (data);
1201
1202 g_timer_continue (job->time);
1203
1204 g_free (primary_text);
1205 g_free (secondary_text);
1206
1207 return res;
1208}
1209
1210#if 0 /* Not used at the moment */
1211static int
1212run_simple_dialog (CommonJob *job,
1213 gboolean ignore_close_box,
1214 GtkMessageType message_type,
1215 char *primary_text,
1216 char *secondary_text,
1217 const char *details_text,
1218 ...)
1219{
1220 va_list varargs;
1221 int res;
1222
1223 va_start (varargs, details_text)__builtin_va_start(varargs, details_text);
1224 res = run_simple_dialog_va (job,
1225 ignore_close_box,
1226 message_type,
1227 primary_text,
1228 secondary_text,
1229 details_text,
1230 varargs);
1231 va_end (varargs)__builtin_va_end(varargs);
1232 return res;
1233}
1234#endif
1235
1236static int
1237run_error (CommonJob *job,
1238 char *primary_text,
1239 char *secondary_text,
1240 const char *details_text,
1241 gboolean show_all,
1242 ...)
1243{
1244 va_list varargs;
1245 int res;
1246
1247 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1248 res = run_simple_dialog_va (job,
1249 FALSE(0),
1250 GTK_MESSAGE_ERROR,
1251 primary_text,
1252 secondary_text,
1253 details_text,
1254 show_all,
1255 varargs);
1256 va_end (varargs)__builtin_va_end(varargs);
1257 return res;
1258}
1259
1260static int
1261run_warning (CommonJob *job,
1262 char *primary_text,
1263 char *secondary_text,
1264 const char *details_text,
1265 gboolean show_all,
1266 ...)
1267{
1268 va_list varargs;
1269 int res;
1270
1271 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1272 res = run_simple_dialog_va (job,
1273 FALSE(0),
1274 GTK_MESSAGE_WARNING,
1275 primary_text,
1276 secondary_text,
1277 details_text,
1278 show_all,
1279 varargs);
1280 va_end (varargs)__builtin_va_end(varargs);
1281 return res;
1282}
1283
1284static int
1285run_question (CommonJob *job,
1286 char *primary_text,
1287 char *secondary_text,
1288 const char *details_text,
1289 gboolean show_all,
1290 ...)
1291{
1292 va_list varargs;
1293 int res;
1294
1295 va_start (varargs, show_all)__builtin_va_start(varargs, show_all);
1296 res = run_simple_dialog_va (job,
1297 FALSE(0),
1298 GTK_MESSAGE_QUESTION,
1299 primary_text,
1300 secondary_text,
1301 details_text,
1302 show_all,
1303 varargs);
1304 va_end (varargs)__builtin_va_end(varargs);
1305 return res;
1306}
1307
1308static void
1309inhibit_power_manager (CommonJob *job, const char *message)
1310{
1311 job->inhibit_cookie = caja_inhibit_power_manager (message);
1312}
1313
1314static void
1315abort_job (CommonJob *job)
1316{
1317 g_cancellable_cancel (job->cancellable);
1318
1319}
1320
1321/* Since this happens on a thread we can't use the global prefs object */
1322static gboolean
1323should_confirm_trash (void)
1324{
1325 GSettings *prefs;
1326 gboolean confirm_trash;
1327
1328 prefs = g_settings_new ("org.mate.caja.preferences");
1329 confirm_trash = g_settings_get_boolean (prefs, CAJA_PREFERENCES_CONFIRM_TRASH"confirm-trash");
1330 g_object_unref (prefs);
1331 return confirm_trash;
1332}
1333
1334static gboolean
1335should_confirm_move_to_trash (void)
1336{
1337 GSettings *prefs;
1338 gboolean confirm_trash;
1339
1340 prefs = g_settings_new ("org.mate.caja.preferences");
1341 confirm_trash = g_settings_get_boolean (prefs, CAJA_PREFERENCES_CONFIRM_MOVE_TO_TRASH"confirm-move-to-trash");
1342 g_object_unref (prefs);
1343 return confirm_trash;
1344}
1345
1346static gboolean
1347job_aborted (CommonJob *job)
1348{
1349 return g_cancellable_is_cancelled (job->cancellable);
1350}
1351
1352static gboolean
1353confirm_delete_from_trash (CommonJob *job,
1354 GList *files)
1355{
1356 char *prompt;
1357 int file_count;
1358 int response;
1359
1360 /* Just Say Yes if the preference says not to confirm. */
1361 if (!should_confirm_trash ()) {
1362 return TRUE(!(0));
1363 }
1364
1365 file_count = g_list_length (files);
1366 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_78
; if (file_count > 0) _g_boolean_var_78 = 1; else _g_boolean_var_78
= 0; _g_boolean_var_78; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1366, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1367
1368 if (file_count == 1) {
1369 prompt = f (_("Are you sure you want to permanently delete \"%B\" "dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\" "
"from the trash?", 5)
1370 "from the trash?")dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\" "
"from the trash?", 5)
, files->data);
1371 } else {
1372 prompt = f (ngettext("Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1373 "the %'d selected item from the trash?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1374 "Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1375 "the %'d selected items from the trash?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
1376 file_count)dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item from the trash?", "Are you sure you want to permanently delete "
"the %'d selected items from the trash?", file_count, 5)
,
1377 file_count);
1378 }
1379
1380 response = run_warning (job,
1381 prompt,
1382 f (_("If you delete an item, it will be permanently lost.")dcgettext (((void*)0), "If you delete an item, it will be permanently lost."
, 5)
),
1383 NULL((void*)0),
1384 FALSE(0),
1385 CANCELdcgettext (((void*)0), "_Cancel", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1386 NULL((void*)0));
1387
1388 return (response == 1);
1389}
1390
1391static gboolean
1392confirm_empty_trash (CommonJob *job)
1393{
1394 char *prompt;
1395 int response;
1396
1397 /* Just Say Yes if the preference says not to confirm. */
1398 if (!should_confirm_trash ()) {
1399 return TRUE(!(0));
1400 }
1401
1402 prompt = f (_("Empty all items from Trash?")dcgettext (((void*)0), "Empty all items from Trash?", 5));
1403
1404 response = run_warning (job,
1405 prompt,
1406 f(_("All items in the Trash will be permanently deleted.")dcgettext (((void*)0), "All items in the Trash will be permanently deleted."
, 5)
),
1407 NULL((void*)0),
1408 FALSE(0),
1409 CANCELdcgettext (((void*)0), "_Cancel", 5), _("Empty _Trash")dcgettext (((void*)0), "Empty _Trash", 5),
1410 NULL((void*)0));
1411
1412 return (response == 1);
1413}
1414
1415static gboolean
1416confirm_delete_directly (CommonJob *job,
1417 GList *files)
1418{
1419 char *prompt;
1420 int file_count;
1421 int response;
1422
1423 /* Just Say Yes if the preference says not to confirm. */
1424 if (!should_confirm_trash ()) {
1425 return TRUE(!(0));
1426 }
1427
1428 file_count = g_list_length (files);
1429 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_79
; if (file_count > 0) _g_boolean_var_79 = 1; else _g_boolean_var_79
= 0; _g_boolean_var_79; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1429, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1430
1431 if (can_delete_files_without_confirm (files)) {
1432 return TRUE(!(0));
1433 }
1434
1435 if (file_count == 1) {
1436 prompt = f (_("Are you sure you want to permanently delete \"%B\"?")dcgettext (((void*)0), "Are you sure you want to permanently delete \"%B\"?"
, 5)
,
1437 files->data);
1438 } else {
1439 prompt = f (ngettext("Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1440 "the %'d selected item?",dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1441 "Are you sure you want to permanently delete "dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
1442 "the %'d selected items?", file_count)dcngettext (((void*)0), "Are you sure you want to permanently delete "
"the %'d selected item?", "Are you sure you want to permanently delete "
"the %'d selected items?", file_count, 5)
,
1443 file_count);
1444 }
1445
1446 response = run_warning (job,
1447 prompt,
1448 f (_("If you delete an item, it will be permanently lost.")dcgettext (((void*)0), "If you delete an item, it will be permanently lost."
, 5)
),
1449 NULL((void*)0),
1450 FALSE(0),
1451 CANCELdcgettext (((void*)0), "_Cancel", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1452 NULL((void*)0));
1453
1454 return response == 1;
1455}
1456
1457static gboolean
1458confirm_trash (CommonJob *job,
1459 GList *files)
1460{
1461 char *prompt;
1462 int file_count;
1463 int response;
1464
1465 /* Just Say Yes if the preference says not to confirm. */
1466 if (!should_confirm_move_to_trash ()) {
1467 return TRUE(!(0));
1468 }
1469
1470 file_count = g_list_length (files);
1471 g_assert (file_count > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_80
; if (file_count > 0) _g_boolean_var_80 = 1; else _g_boolean_var_80
= 0; _g_boolean_var_80; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 1471, ((const char*
) (__func__)), "file_count > 0"); } while (0)
;
1472
1473 if (can_delete_files_without_confirm (files)) {
1474 return TRUE(!(0));
1475 }
1476
1477 if (file_count == 1) {
1478 prompt = f (_("Are you sure you want to trash \"%B\"?")dcgettext (((void*)0), "Are you sure you want to trash \"%B\"?"
, 5)
,
1479 files->data);
1480 } else {
1481 prompt = f (ngettext("Are you sure you want to trash "dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1482 "the %'d selected item?",dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1483 "Are you sure you want to trash "dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
1484 "the %'d selected items?", file_count)dcngettext (((void*)0), "Are you sure you want to trash " "the %'d selected item?"
, "Are you sure you want to trash " "the %'d selected items?"
, file_count, 5)
,
1485 file_count);
1486 }
1487
1488 response = run_warning (job,
1489 prompt,
1490 f (_("Items moved to the trash may be recovered until the trash is emptied.")dcgettext (((void*)0), "Items moved to the trash may be recovered until the trash is emptied."
, 5)
),
1491 NULL((void*)0),
1492 FALSE(0),
1493 CANCELdcgettext (((void*)0), "_Cancel", 5), _("Move to _Trash")dcgettext (((void*)0), "Move to _Trash", 5),
1494 NULL((void*)0));
1495
1496 return response == 1;
1497}
1498
1499static void
1500report_delete_progress (CommonJob *job,
1501 SourceInfo *source_info,
1502 TransferInfo *transfer_info)
1503{
1504 int files_left;
1505 double elapsed;
1506 gint64 now;
1507 char *files_left_s;
1508
1509 now = g_get_monotonic_time ();
1510 if (transfer_info->last_report_time != 0 &&
1511 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
1512 return;
1513 }
1514 transfer_info->last_report_time = now;
1515
1516 files_left = source_info->num_files - transfer_info->num_files;
1517
1518 /* Races and whatnot could cause this to be negative... */
1519 if (files_left < 0) {
1520 files_left = 1;
1521 }
1522
1523 files_left_s = f (ngettext ("%'d file left to delete",dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
1524 "%'d files left to delete",dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
1525 files_left)dcngettext (((void*)0), "%'d file left to delete", "%'d files left to delete"
, files_left, 5)
,
1526 files_left);
1527
1528 caja_progress_info_take_status (job->progress,
1529 f (_("Deleting files")dcgettext (((void*)0), "Deleting files", 5)));
1530
1531 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
1532 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15) {
1533
1534 caja_progress_info_set_details (job->progress, files_left_s);
1535 } else {
1536 char *details, *time_left_s;
1537 int remaining_time;
1538 double transfer_rate;
1539
1540 transfer_rate = transfer_info->num_files / elapsed;
1541 remaining_time = files_left / transfer_rate;
1542
1543 /* Translators: %T will expand to a time like "2 minutes".
1544 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
1545 */
1546 time_left_s = f (ngettext ("%T left",dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
1547 "%T left",dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
1548 seconds_count_format_time_units (remaining_time))dcngettext (((void*)0), "%T left", "%T left", seconds_count_format_time_units
(remaining_time), 5)
,
1549 remaining_time);
1550
1551 details = g_strconcat (files_left_s, "\xE2\x80\x94", time_left_s, NULL((void*)0));
1552 caja_progress_info_take_details (job->progress, details);
1553
1554 g_free (time_left_s);
1555 }
1556
1557 g_free (files_left_s);
1558
1559 if (source_info->num_files != 0) {
1560 caja_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files);
1561 }
1562}
1563
1564static void delete_file (CommonJob *job, GFile *file,
1565 gboolean *skipped_file,
1566 SourceInfo *source_info,
1567 TransferInfo *transfer_info,
1568 gboolean toplevel);
1569
1570static void
1571delete_dir (CommonJob *job, GFile *dir,
1572 gboolean *skipped_file,
1573 SourceInfo *source_info,
1574 TransferInfo *transfer_info,
1575 gboolean toplevel)
1576{
1577 GFileInfo *info;
1578 GError *error;
1579 GFile *file;
1580 GFileEnumerator *enumerator;
1581 char *primary, *secondary, *details;
1582 int response;
1583 gboolean skip_error;
1584 gboolean local_skipped_file;
1585
1586 local_skipped_file = FALSE(0);
1587
1588 skip_error = should_skip_readdir_error (job, dir);
1589 retry:
1590 error = NULL((void*)0);
1591 enumerator = g_file_enumerate_children (dir,
1592 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
1593 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1594 job->cancellable,
1595 &error);
1596 if (enumerator) {
1597 error = NULL((void*)0);
1598
1599 while (!job_aborted (job) &&
1600 (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error)) != NULL((void*)0)) {
1601 file = g_file_get_child (dir,
1602 g_file_info_get_name (info));
1603 delete_file (job, file, &local_skipped_file, source_info, transfer_info, FALSE(0));
1604 g_object_unref (file);
1605 g_object_unref (info);
1606 }
1607 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
1608 g_object_unref (enumerator);
1609
1610 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1611 g_error_free (error);
1612 } else if (error) {
1613 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1614 details = NULL((void*)0);
1615
1616 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1617 secondary = f (_("Files in the folder \"%B\" cannot be deleted because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be deleted because you do "
"not have permissions to see them.", 5)
1618 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be deleted because you do "
"not have permissions to see them.", 5)
, dir);
1619 } else {
1620 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, dir);
1621 details = error->message;
1622 }
1623
1624 response = run_warning (job,
1625 primary,
1626 secondary,
1627 details,
1628 FALSE(0),
1629 CANCELdcgettext (((void*)0), "_Cancel", 5), _("_Skip files")dcgettext (((void*)0), "_Skip files", 5),
1630 NULL((void*)0));
1631
1632 g_error_free (error);
1633
1634 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1635 abort_job (job);
1636 } else if (response == 1) {
1637 /* Skip: Do Nothing */
1638 local_skipped_file = TRUE(!(0));
1639 } else {
1640 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1640, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1641 }
1642 }
1643
1644 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1645 g_error_free (error);
1646 } else {
1647 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1648 details = NULL((void*)0);
1649 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
1650 secondary = f (_("The folder \"%B\" cannot be deleted because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be deleted because you do not have "
"permissions to read it.", 5)
1651 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be deleted because you do not have "
"permissions to read it.", 5)
, dir);
1652 } else {
1653 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, dir);
1654 details = error->message;
1655 }
1656
1657 response = run_warning (job,
1658 primary,
1659 secondary,
1660 details,
1661 FALSE(0),
1662 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
1663 NULL((void*)0));
1664
1665 g_error_free (error);
1666
1667 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1668 abort_job (job);
1669 } else if (response == 1) {
1670 /* Skip: Do Nothing */
1671 local_skipped_file = TRUE(!(0));
1672 } else if (response == 2) {
1673 goto retry;
1674 } else {
1675 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1675, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1676 }
1677 }
1678
1679 if (!job_aborted (job) &&
1680 /* Don't delete dir if there was a skipped file */
1681 !local_skipped_file) {
1682 if (!g_file_delete (dir, job->cancellable, &error)) {
1683 if (job->skip_all_error) {
1684 goto skip;
1685 }
1686 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1687 secondary = f (_("Could not remove the folder %B.")dcgettext (((void*)0), "Could not remove the folder %B.", 5), dir);
1688 details = error->message;
1689
1690 response = run_warning (job,
1691 primary,
1692 secondary,
1693 details,
1694 (source_info->num_files - transfer_info->num_files) > 1,
1695 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
1696 NULL((void*)0));
1697
1698 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1699 abort_job (job);
1700 } else if (response == 1) { /* skip all */
1701 job->skip_all_error = TRUE(!(0));
1702 local_skipped_file = TRUE(!(0));
1703 } else if (response == 2) { /* skip */
1704 local_skipped_file = TRUE(!(0));
1705 } else {
1706 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1706, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1707 }
1708
1709 skip:
1710 g_error_free (error);
1711 } else {
1712 caja_file_changes_queue_file_removed (dir);
1713 transfer_info->num_files ++;
1714 report_delete_progress (job, source_info, transfer_info);
1715 return;
1716 }
1717 }
1718
1719 if (local_skipped_file) {
1720 *skipped_file = TRUE(!(0));
1721 }
1722}
1723
1724static void
1725delete_file (CommonJob *job, GFile *file,
1726 gboolean *skipped_file,
1727 SourceInfo *source_info,
1728 TransferInfo *transfer_info,
1729 gboolean toplevel)
1730{
1731 GError *error;
1732 char *primary, *secondary, *details;
1733 int response;
1734
1735 if (should_skip_file (job, file)) {
1736 *skipped_file = TRUE(!(0));
1737 return;
1738 }
1739
1740 error = NULL((void*)0);
1741 if (g_file_delete (file, job->cancellable, &error)) {
1742 caja_file_changes_queue_file_removed (file);
1743 transfer_info->num_files ++;
1744 report_delete_progress (job, source_info, transfer_info);
1745 return;
1746 }
1747
1748 if (IS_IO_ERROR (error, NOT_EMPTY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_EMPTY))
) {
1749 g_error_free (error);
1750 delete_dir (job, file,
1751 skipped_file,
1752 source_info, transfer_info,
1753 toplevel);
1754 return;
1755
1756 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
1757 g_error_free (error);
1758
1759 } else {
1760 if (job->skip_all_error) {
1761 goto skip;
1762 }
1763 primary = f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
1764 secondary = f (_("There was an error deleting %B.")dcgettext (((void*)0), "There was an error deleting %B.", 5), file);
1765 details = error->message;
1766
1767 response = run_warning (job,
1768 primary,
1769 secondary,
1770 details,
1771 (source_info->num_files - transfer_info->num_files) > 1,
1772 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
1773 NULL((void*)0));
1774
1775 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1776 abort_job (job);
1777 } else if (response == 1) { /* skip all */
1778 job->skip_all_error = TRUE(!(0));
1779 } else if (response == 2) { /* skip */
1780 /* do nothing */
1781 } else {
1782 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 1782, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1783 }
1784 skip:
1785 g_error_free (error);
1786 }
1787
1788 *skipped_file = TRUE(!(0));
1789}
1790
1791static void
1792delete_files (CommonJob *job, GList *files, int *files_skipped)
1793{
1794 GList *l;
1795 SourceInfo source_info;
1796 TransferInfo transfer_info;
1797 gboolean skipped_file;
1798 GFile *file = NULL((void*)0);
1799
1800 if (job_aborted (job)) {
1801 return;
1802 }
1803
1804 scan_sources (files,
1805 &source_info,
1806 job,
1807 OP_KIND_DELETE);
1808 if (job_aborted (job)) {
1809 return;
1810 }
1811
1812 g_timer_start (job->time);
1813
1814 memset (&transfer_info, 0, sizeof (transfer_info));
1815 report_delete_progress (job, &source_info, &transfer_info);
1816
1817 for (l = files;
1818 l != NULL((void*)0) && !job_aborted (job);
1819 l = l->next) {
1820 file = l->data;
1821
1822 skipped_file = FALSE(0);
1823 delete_file (job, file,
1824 &skipped_file,
1825 &source_info, &transfer_info,
1826 TRUE(!(0)));
1827 if (skipped_file) {
1828 (*files_skipped)++;
1829 }
1830 }
1831}
1832
1833static void
1834report_trash_progress (CommonJob *job,
1835 int files_trashed,
1836 int total_files)
1837{
1838 int files_left;
1839 char *s;
1840
1841 files_left = total_files - files_trashed;
1842
1843 caja_progress_info_take_status (job->progress,
1844 f (_("Moving files to trash")dcgettext (((void*)0), "Moving files to trash", 5)));
1845
1846 s = f (ngettext ("%'d file left to trash",dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
1847 "%'d files left to trash",dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
1848 files_left)dcngettext (((void*)0), "%'d file left to trash", "%'d files left to trash"
, files_left, 5)
,
1849 files_left);
1850 caja_progress_info_take_details (job->progress, s);
1851
1852 if (total_files != 0) {
1853 caja_progress_info_set_progress (job->progress, files_trashed, total_files);
1854 }
1855}
1856
1857
1858static void
1859trash_files (CommonJob *job, GList *files, int *files_skipped)
1860{
1861 GList *l;
1862 GFile *file;
1863 GList *to_delete;
1864 GError *error;
1865 int total_files, files_trashed;
1866 char *primary, *secondary, *details;
1867 int response;
1868
1869 guint64 mtime;
1870
1871 if (job_aborted (job)) {
1872 return;
1873 }
1874
1875 total_files = g_list_length (files);
1876 files_trashed = 0;
1877
1878 report_trash_progress (job, files_trashed, total_files);
1879
1880 to_delete = NULL((void*)0);
1881 for (l = files;
1882 l != NULL((void*)0) && !job_aborted (job);
1883 l = l->next) {
1884 caja_progress_info_get_ready (job->progress);
1885
1886 file = l->data;
1887
1888 error = NULL((void*)0);
1889
1890 mtime = caja_undostack_manager_get_file_modification_time (file);
1891
1892 if (!g_file_trash (file, job->cancellable, &error)) {
1893 if (job->skip_all_error) {
1894 (*files_skipped)++;
1895 goto skip;
1896 }
1897
1898 if (job->delete_all) {
1899 to_delete = g_list_prepend (to_delete, file);
1900 goto skip;
1901 }
1902
1903 primary = f (_("Cannot move file to trash, do you want to delete immediately?")dcgettext (((void*)0), "Cannot move file to trash, do you want to delete immediately?"
, 5)
);
1904 secondary = f (_("The file \"%B\" cannot be moved to the trash.")dcgettext (((void*)0), "The file \"%B\" cannot be moved to the trash."
, 5)
, file);
1905 details = NULL((void*)0);
1906 if (!IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
1907 details = error->message;
1908 }
1909
1910 response = run_question (job,
1911 primary,
1912 secondary,
1913 details,
1914 (total_files - files_trashed) > 1,
1915 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), DELETE_ALLdcgettext (((void*)0), "Delete _All", 5), DELETEdcgettext (((void*)0), "_Delete", 5),
1916 NULL((void*)0));
1917
1918 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
1919 ((DeleteJob *) job)->user_cancel = TRUE(!(0));
1920 abort_job (job);
1921 } else if (response == 1) { /* skip all */
1922 (*files_skipped)++;
1923 job->skip_all_error = TRUE(!(0));
1924 } else if (response == 2) { /* skip */
1925 (*files_skipped)++;
1926 } else if (response == 3) { /* delete all */
1927 to_delete = g_list_prepend (to_delete, file);
1928 job->delete_all = TRUE(!(0));
1929 } else if (response == 4) { /* delete */
1930 to_delete = g_list_prepend (to_delete, file);
1931 }
1932
1933 skip:
1934 g_error_free (error);
1935 total_files--;
1936 } else {
1937 caja_file_changes_queue_file_removed (file);
1938
1939 // Start UNDO-REDO
1940 caja_undostack_manager_data_add_trashed_file (job->undo_redo_data, file, mtime);
1941 // End UNDO-REDO
1942
1943 files_trashed++;
1944 report_trash_progress (job, files_trashed, total_files);
1945 }
1946 }
1947
1948 if (to_delete) {
1949 to_delete = g_list_reverse (to_delete);
1950 delete_files (job, to_delete, files_skipped);
1951 g_list_free (to_delete);
1952 }
1953}
1954
1955static gboolean
1956delete_job_done (gpointer user_data)
1957{
1958 DeleteJob *job;
1959
1960 job = user_data;
1961
1962 g_list_free_full (job->files, g_object_unref);
1963
1964 if (job->done_callback) {
1965 GHashTable *debuting_uris;
1966
1967 debuting_uris = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
1968 job->done_callback (debuting_uris, job->user_cancel, job->done_callback_data);
1969 g_hash_table_unref (debuting_uris);
1970 }
1971
1972 finalize_common ((CommonJob *)job);
1973
1974 caja_file_changes_consume_changes (TRUE(!(0)));
1975
1976 return FALSE(0);
1977}
1978
1979static gboolean
1980delete_job (GIOSchedulerJob *io_job,
1981 GCancellable *cancellable,
1982 gpointer user_data)
1983{
1984 DeleteJob *job = user_data;
1985 GList *to_trash_files;
1986 GList *to_delete_files;
1987 GList *l;
1988 gboolean confirmed;
1989 CommonJob *common;
1990 gboolean must_confirm_delete_in_trash;
1991 gboolean must_confirm_delete;
1992 gboolean must_confirm_trash;
1993 int files_skipped;
1994 GFile *file = NULL((void*)0);
1995
1996 common = (CommonJob *)job;
1997 common->io_job = io_job;
1998
1999 caja_progress_info_start (job->common.progress);
2000
2001 to_trash_files = NULL((void*)0);
2002 to_delete_files = NULL((void*)0);
2003
2004 must_confirm_delete_in_trash = FALSE(0);
2005 must_confirm_delete = FALSE(0);
2006 must_confirm_trash = FALSE(0);
2007 files_skipped = 0;
2008
2009 for (l = job->files; l != NULL((void*)0); l = l->next) {
2010 file = l->data;
2011
2012 if (job->try_trash &&
2013 g_file_has_uri_scheme (file, "trash")) {
2014 must_confirm_delete_in_trash = TRUE(!(0));
2015 to_delete_files = g_list_prepend (to_delete_files, file);
2016 } else if (can_delete_without_confirm (file)) {
2017 to_delete_files = g_list_prepend (to_delete_files, file);
2018 } else {
2019 if (job->try_trash) {
2020 must_confirm_trash = TRUE(!(0));
2021 to_trash_files = g_list_prepend (to_trash_files, file);
2022 } else {
2023 must_confirm_delete = TRUE(!(0));
2024 to_delete_files = g_list_prepend (to_delete_files, file);
2025 }
2026 }
2027 }
2028
2029 if (to_delete_files != NULL((void*)0)) {
2030 to_delete_files = g_list_reverse (to_delete_files);
2031 confirmed = TRUE(!(0));
2032 if (must_confirm_delete_in_trash) {
2033 confirmed = confirm_delete_from_trash (common, to_delete_files);
2034 } else if (must_confirm_delete) {
2035 confirmed = confirm_delete_directly (common, to_delete_files);
2036 }
2037 if (confirmed) {
2038 delete_files (common, to_delete_files, &files_skipped);
2039 } else {
2040 job->user_cancel = TRUE(!(0));
2041 }
2042 }
2043
2044 if (to_trash_files != NULL((void*)0)) {
2045 to_trash_files = g_list_reverse (to_trash_files);
2046
2047 if (! must_confirm_trash || confirm_trash (common, to_trash_files)) {
2048 trash_files (common, to_trash_files, &files_skipped);
2049 } else {
2050 job->user_cancel = TRUE(!(0));
2051 }
2052 }
2053
2054 g_list_free (to_trash_files);
2055 g_list_free (to_delete_files);
2056
2057 if (files_skipped == g_list_length (job->files)) {
2058 /* User has skipped all files, report user cancel */
2059 job->user_cancel = TRUE(!(0));
2060 }
2061
2062 g_io_scheduler_job_send_to_mainloop_async (io_job,
2063 delete_job_done,
2064 job,
2065 NULL((void*)0));
2066
2067 return FALSE(0);
2068}
2069
2070static void
2071trash_or_delete_internal (GList *files,
2072 GtkWindow *parent_window,
2073 gboolean try_trash,
2074 CajaDeleteCallback done_callback,
2075 gpointer done_callback_data)
2076{
2077 DeleteJob *job;
2078
2079 /* TODO: special case desktop icon link files ... */
2080
2081 job = op_job_new (DeleteJob, parent_window, TRUE, FALSE)((DeleteJob *)(init_common (sizeof(DeleteJob), parent_window,
(!(0)), (0))))
;
2082 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
2083 job->try_trash = try_trash;
2084 job->user_cancel = FALSE(0);
2085 job->done_callback = done_callback;
2086 job->done_callback_data = done_callback_data;
2087
2088 if (try_trash) {
2089 inhibit_power_manager ((CommonJob *)job, _("Trashing Files")dcgettext (((void*)0), "Trashing Files", 5));
2090 } else {
2091 inhibit_power_manager ((CommonJob *)job, _("Deleting Files")dcgettext (((void*)0), "Deleting Files", 5));
2092 }
2093 // Start UNDO-REDO
2094 // FIXME: Disabled, because of missing mechanism to restore a file from trash in a clean way
2095 // see https://www.mail-archive.com/nautilus-list@gnome.org/msg04664.html
2096 if (try_trash && !caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
2097 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_MOVETOTRASH, g_list_length(files));
2098 GFile* src_dir = g_file_get_parent (files->data);
2099 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
2100 }
2101 // End UNDO-REDO
2102
2103 g_io_scheduler_push_job (delete_job,
2104 job,
2105 NULL((void*)0),
2106 0,
2107 NULL((void*)0));
2108}
2109
2110void
2111caja_file_operations_trash_or_delete (GList *files,
2112 GtkWindow *parent_window,
2113 CajaDeleteCallback done_callback,
2114 gpointer done_callback_data)
2115{
2116 trash_or_delete_internal (files, parent_window,
2117 TRUE(!(0)),
2118 done_callback, done_callback_data);
2119}
2120
2121void
2122caja_file_operations_delete (GList *files,
2123 GtkWindow *parent_window,
2124 CajaDeleteCallback done_callback,
2125 gpointer done_callback_data)
2126{
2127 trash_or_delete_internal (files, parent_window,
2128 FALSE(0),
2129 done_callback, done_callback_data);
2130}
2131
2132
2133
2134typedef struct {
2135 gboolean eject;
2136 GMount *mount;
2137 GtkWindow *parent_window;
2138 CajaUnmountCallback callback;
2139 gpointer callback_data;
2140} UnmountData;
2141
2142static void
2143unmount_mount_callback (GObject *source_object,
2144 GAsyncResult *res,
2145 gpointer user_data)
2146{
2147 UnmountData *data = user_data;
2148 GError *error;
2149 gboolean unmounted;
2150
2151 error = NULL((void*)0);
2152 if (data->eject) {
2153 unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object)((((GMount*) (void *) ((source_object))))),
2154 res, &error);
2155 if ((!error) || (unmounted == TRUE(!(0)))){
2156 caja_application_notify_unmount_show (_("It is now safe to remove the drive")dcgettext (((void*)0), "It is now safe to remove the drive", 5
)
);
2157 }
2158
2159 } else {
2160 unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object)((((GMount*) (void *) ((source_object))))),
2161 res, &error);
2162 }
2163
2164 if (! unmounted) {
2165 if (error && error->code != G_IO_ERROR_FAILED_HANDLED) {
2166 char *primary;
2167
2168 if (data->eject) {
2169 primary = f (_("Unable to eject %V")dcgettext (((void*)0), "Unable to eject %V", 5), source_object);
2170 } else {
2171 primary = f (_("Unable to unmount %V")dcgettext (((void*)0), "Unable to unmount %V", 5), source_object);
2172 }
2173 eel_show_error_dialog (primary,
2174 error->message,
2175 data->parent_window);
2176 g_free (primary);
2177 }
2178 }
2179
2180 if (data->callback) {
2181 data->callback (data->callback_data);
2182 }
2183
2184 if (error != NULL((void*)0)) {
2185 g_error_free (error);
2186 }
2187
2188 eel_remove_weak_pointer (&data->parent_window);
2189 g_object_unref (data->mount);
2190 g_free (data);
2191}
2192
2193static void
2194do_unmount (UnmountData *data)
2195{
2196 GMountOperation *mount_op;
2197
2198 mount_op = gtk_mount_operation_new (data->parent_window);
2199 if (data->eject) {
2200 g_mount_eject_with_operation (data->mount,
2201 0,
2202 mount_op,
2203 NULL((void*)0),
2204 unmount_mount_callback,
2205 data);
2206
2207 caja_application_notify_unmount_show (_("Writing data to the drive -- do not unplug")dcgettext (((void*)0), "Writing data to the drive -- do not unplug"
, 5)
);
2208
2209 } else {
2210 g_mount_unmount_with_operation (data->mount,
2211 0,
2212 mount_op,
2213 NULL((void*)0),
2214 unmount_mount_callback,
2215 data);
2216 }
2217 g_object_unref (mount_op);
2218}
2219
2220static gboolean
2221dir_has_files (GFile *dir)
2222{
2223 GFileEnumerator *enumerator;
2224 gboolean res;
2225
2226 res = FALSE(0);
2227
2228 enumerator = g_file_enumerate_children (dir,
2229 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
2230 0,
2231 NULL((void*)0), NULL((void*)0));
2232 if (enumerator) {
2233 GFileInfo *file_info;
2234
2235 file_info = g_file_enumerator_next_file (enumerator, NULL((void*)0), NULL((void*)0));
2236 if (file_info != NULL((void*)0)) {
2237 res = TRUE(!(0));
2238 g_object_unref (file_info);
2239 }
2240
2241 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2242 g_object_unref (enumerator);
2243 }
2244
2245
2246 return res;
2247}
2248
2249static GList *
2250get_trash_dirs_for_mount (GMount *mount)
2251{
2252 GFile *root;
2253 GList *list;
2254
2255 root = g_mount_get_root (mount);
2256 if (root == NULL((void*)0)) {
2257 return NULL((void*)0);
2258 }
2259
2260 list = NULL((void*)0);
2261
2262 if (g_file_is_native (root)) {
2263 GFile *trash;
2264 char *relpath;
2265
2266 relpath = g_strdup_printf (".Trash/%d", getuid ());
2267 trash = g_file_resolve_relative_path (root, relpath);
2268 g_free (relpath);
2269
2270 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2271 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2272
2273 g_object_unref (trash);
2274
2275 relpath = g_strdup_printf (".Trash-%d", getuid ());
2276 trash = g_file_get_child (root, relpath);
2277 g_free (relpath);
2278
2279 list = g_list_prepend (list, g_file_get_child (trash, "files"));
2280 list = g_list_prepend (list, g_file_get_child (trash, "info"));
2281
2282 g_object_unref (trash);
2283 }
2284
2285 g_object_unref (root);
2286
2287 return list;
2288}
2289
2290static gboolean
2291has_trash_files (GMount *mount)
2292{
2293 gboolean res;
2294 GList *dirs, *l;
2295 GFile *dir = NULL((void*)0);
2296
2297 dirs = get_trash_dirs_for_mount (mount);
2298
2299 res = FALSE(0);
2300
2301 for (l = dirs; l != NULL((void*)0); l = l->next) {
2302 dir = l->data;
2303
2304 if (dir_has_files (dir)) {
2305 res = TRUE(!(0));
2306 break;
2307 }
2308 }
2309
2310 g_list_free_full (dirs, g_object_unref);
2311
2312 return res;
2313}
2314
2315
2316static gint
2317prompt_empty_trash (GtkWindow *parent_window)
2318{
2319 gint result;
2320 GtkWidget *dialog;
2321 GdkScreen *screen;
2322
2323 screen = NULL((void*)0);
2324 if (parent_window != NULL((void*)0)) {
2325 screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)((((GtkWidget*) (void *) ((parent_window))))));
2326 }
2327
2328 /* Do we need to be modal ? */
2329 dialog = gtk_message_dialog_new (NULL((void*)0), GTK_DIALOG_MODAL,
2330 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
2331 _("Do you want to empty the trash before you unmount?")dcgettext (((void*)0), "Do you want to empty the trash before you unmount?"
, 5)
);
2332 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog)((((GtkMessageDialog*) (void *) ((dialog))))),
2333 _("In order to regain the "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2334 "free space on this volume "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2335 "the trash must be emptied. "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2336 "All trashed items on the volume "dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
2337 "will be permanently lost.")dcgettext (((void*)0), "In order to regain the " "free space on this volume "
"the trash must be emptied. " "All trashed items on the volume "
"will be permanently lost.", 5)
);
2338
2339 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2340 _("Do _not Empty Trash")dcgettext (((void*)0), "Do _not Empty Trash", 5), GTK_RESPONSE_REJECT);
2341
2342 eel_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2343 CANCELdcgettext (((void*)0), "_Cancel", 5), "process-stop", GTK_RESPONSE_CANCEL);
2344
2345 gtk_dialog_add_button (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))),
2346 _("Empty _Trash")dcgettext (((void*)0), "Empty _Trash", 5), GTK_RESPONSE_ACCEPT);
2347
2348 gtk_dialog_set_default_response (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_ACCEPT);
2349 gtk_window_set_title (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), ""); /* as per HIG */
2350 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
2351 if (screen) {
2352 gtk_window_set_screen (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), screen);
2353 }
2354 atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT);
2355
2356 /* Make transient for the window group */
2357 gtk_widget_realize (dialog);
2358 if (screen != NULL((void*)0)) {
2359 gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog)))))),
2360 gdk_screen_get_root_window (screen));
2361 }
2362
2363 result = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
2364 gtk_widget_destroy (dialog);
2365 return result;
2366}
2367
2368void
2369caja_file_operations_unmount_mount_full (GtkWindow *parent_window,
2370 GMount *mount,
2371 gboolean eject,
2372 gboolean check_trash,
2373 CajaUnmountCallback callback,
2374 gpointer callback_data)
2375{
2376 UnmountData *data;
2377
2378 data = g_new0 (UnmountData, 1)(UnmountData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (UnmountData); 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; }))
;
2379 data->callback = callback;
2380 data->callback_data = callback_data;
2381 if (parent_window) {
2382 data->parent_window = parent_window;
2383 eel_add_weak_pointer (&data->parent_window);
2384
2385 }
2386 data->eject = eject;
2387 data->mount = g_object_ref (mount)((__typeof__ (mount)) (g_object_ref) (mount));
2388
2389 if (check_trash && has_trash_files (mount)) {
2390 int response;
2391
2392 response = prompt_empty_trash (parent_window);
2393
2394 if (response == GTK_RESPONSE_ACCEPT) {
2395 EmptyTrashJob *job;
2396
2397 job = op_job_new (EmptyTrashJob, parent_window, TRUE, FALSE)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
, (!(0)), (0))))
;
2398 job->should_confirm = FALSE(0);
2399 job->trash_dirs = get_trash_dirs_for_mount (mount);
2400 job->done_callback = (CajaOpCallback)do_unmount;
2401 job->done_callback_data = data;
2402 g_io_scheduler_push_job (empty_trash_job,
2403 job,
2404 NULL((void*)0),
2405 0,
2406 NULL((void*)0));
2407 return;
2408 } else if (response == GTK_RESPONSE_CANCEL) {
2409 if (callback) {
2410 callback (callback_data);
2411 }
2412 eel_remove_weak_pointer (&data->parent_window);
2413 g_object_unref (data->mount);
2414 g_free (data);
2415 return;
2416 }
2417 }
2418
2419 do_unmount (data);
2420}
2421
2422void
2423caja_file_operations_unmount_mount (GtkWindow *parent_window,
2424 GMount *mount,
2425 gboolean eject,
2426 gboolean check_trash)
2427{
2428 caja_file_operations_unmount_mount_full (parent_window, mount, eject,
2429 check_trash, NULL((void*)0), NULL((void*)0));
2430}
2431
2432static void
2433mount_callback_data_notify (gpointer data,
2434 GObject *object)
2435{
2436 GMountOperation *mount_op;
2437
2438 mount_op = G_MOUNT_OPERATION (data)((((GMountOperation*) (void *) ((data)))));
2439 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback", NULL((void*)0));
2440 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback-data", NULL((void*)0));
2441}
2442
2443static void
2444volume_mount_cb (GObject *source_object,
2445 GAsyncResult *res,
2446 gpointer user_data)
2447{
2448 CajaMountCallback mount_callback;
2449 GObject *mount_callback_data_object;
2450 GMountOperation *mount_op = user_data;
2451 GError *error;
2452
2453 error = NULL((void*)0);
2454 caja_allow_autorun_for_volume_finish (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))));
2455 if (!g_volume_mount_finish (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))), res, &error)) {
2456 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2457 char *name;
2458 char *primary;
2459
2460 name = g_volume_get_name (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))));
2461 primary = g_strdup_printf (_("Unable to mount %s")dcgettext (((void*)0), "Unable to mount %s", 5), name);
2462 g_free (name);
2463 eel_show_error_dialog (primary,
2464 error->message,
2465 NULL((void*)0));
2466 g_free (primary);
2467 }
2468 g_error_free (error);
2469 }
2470
2471 mount_callback = (CajaMountCallback)
2472 g_object_get_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback");
2473 mount_callback_data_object =
2474 g_object_get_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))), "mount-callback-data");
2475
2476 if (mount_callback != NULL((void*)0)) {
2477 (* mount_callback) (G_VOLUME (source_object)((((GVolume*) (void *) ((source_object))))),
2478 mount_callback_data_object);
2479
2480 if (mount_callback_data_object != NULL((void*)0)) {
2481 g_object_weak_unref (mount_callback_data_object,
2482 mount_callback_data_notify,
2483 mount_op);
2484 }
2485 }
2486
2487 g_object_unref (mount_op);
2488}
2489
2490
2491void
2492caja_file_operations_mount_volume (GtkWindow *parent_window,
2493 GVolume *volume,
2494 gboolean allow_autorun)
2495{
2496 caja_file_operations_mount_volume_full (parent_window, volume,
2497 allow_autorun, NULL((void*)0), NULL((void*)0));
2498}
2499
2500void
2501caja_file_operations_mount_volume_full (GtkWindow *parent_window,
2502 GVolume *volume,
2503 gboolean allow_autorun,
2504 CajaMountCallback mount_callback,
2505 GObject *mount_callback_data_object)
2506{
2507 GMountOperation *mount_op;
2508
2509 mount_op = gtk_mount_operation_new (parent_window);
2510 g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
2511 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))),
2512 "mount-callback",
2513 mount_callback);
2514
2515 if (mount_callback != NULL((void*)0) &&
2516 mount_callback_data_object != NULL((void*)0)) {
2517 g_object_weak_ref (mount_callback_data_object,
2518 mount_callback_data_notify,
2519 mount_op);
2520 }
2521 g_object_set_data (G_OBJECT (mount_op)((((GObject*) (void *) ((mount_op))))),
2522 "mount-callback-data",
2523 mount_callback_data_object);
2524
2525 if (allow_autorun)
2526 caja_allow_autorun_for_volume (volume);
2527 g_volume_mount (volume, 0, mount_op, NULL((void*)0), volume_mount_cb, mount_op);
2528}
2529
2530static void
2531report_count_progress (CommonJob *job,
2532 SourceInfo *source_info)
2533{
2534 char *s;
2535
2536 switch (source_info->op) {
2537 default:
2538 case OP_KIND_COPY:
2539 s = f (ngettext("Preparing to copy %'d file (%S)",dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
2540 "Preparing to copy %'d files (%S)",dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
2541 source_info->num_files)dcngettext (((void*)0), "Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)"
, source_info->num_files, 5)
,
2542 source_info->num_files, source_info->num_bytes);
2543 break;
2544 case OP_KIND_MOVE:
2545 s = f (ngettext("Preparing to move %'d file (%S)",dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
2546 "Preparing to move %'d files (%S)",dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
2547 source_info->num_files)dcngettext (((void*)0), "Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)"
, source_info->num_files, 5)
,
2548 source_info->num_files, source_info->num_bytes);
2549 break;
2550 case OP_KIND_DELETE:
2551 s = f (ngettext("Preparing to delete %'d file (%S)",dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
2552 "Preparing to delete %'d files (%S)",dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
2553 source_info->num_files)dcngettext (((void*)0), "Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)"
, source_info->num_files, 5)
,
2554 source_info->num_files, source_info->num_bytes);
2555 break;
2556 case OP_KIND_TRASH:
2557 s = f (ngettext("Preparing to trash %'d file",dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
2558 "Preparing to trash %'d files",dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
2559 source_info->num_files)dcngettext (((void*)0), "Preparing to trash %'d file", "Preparing to trash %'d files"
, source_info->num_files, 5)
,
2560 source_info->num_files);
2561 break;
2562 }
2563
2564 caja_progress_info_take_details (job->progress, s);
2565 caja_progress_info_pulse_progress (job->progress);
2566}
2567
2568static void
2569count_file (GFileInfo *info,
2570 CommonJob *job,
2571 SourceInfo *source_info)
2572{
2573 source_info->num_files += 1;
2574 source_info->num_bytes += g_file_info_get_size (info);
2575
2576 if (source_info->num_files_since_progress++ > 100) {
2577 report_count_progress (job, source_info);
2578 source_info->num_files_since_progress = 0;
2579 }
2580}
2581
2582static char *
2583get_scan_primary (OpKind kind)
2584{
2585 switch (kind) {
2586 default:
2587 case OP_KIND_COPY:
2588 return f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
2589 case OP_KIND_MOVE:
2590 return f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
2591 case OP_KIND_DELETE:
2592 return f (_("Error while deleting.")dcgettext (((void*)0), "Error while deleting.", 5));
2593 case OP_KIND_TRASH:
2594 return f (_("Error while moving files to trash.")dcgettext (((void*)0), "Error while moving files to trash.", 5
)
);
2595 }
2596}
2597
2598static void
2599scan_dir (GFile *dir,
2600 SourceInfo *source_info,
2601 CommonJob *job,
2602 GQueue *dirs)
2603{
2604 GFileInfo *info;
2605 GError *error;
2606 GFile *subdir;
2607 GFileEnumerator *enumerator;
2608 char *primary, *secondary, *details;
2609 int response;
2610 SourceInfo saved_info;
2611
2612 saved_info = *source_info;
2613
2614 retry:
2615 error = NULL((void*)0);
2616 enumerator = g_file_enumerate_children (dir,
2617 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
2618 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2619 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size"","
2620 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size",
2621 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2622 job->cancellable,
2623 &error);
2624 if (enumerator) {
2625 error = NULL((void*)0);
2626 while ((info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
2627 count_file (info, job, source_info);
2628
2629 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2630 subdir = g_file_get_child (dir,
2631 g_file_info_get_name (info));
2632
2633 /* Push to head, since we want depth-first */
2634 g_queue_push_head (dirs, subdir);
2635 }
2636
2637 g_object_unref (info);
2638 }
2639 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
2640 g_object_unref (enumerator);
2641
2642 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2643 g_error_free (error);
2644 } else if (error) {
2645 primary = get_scan_primary (source_info->op);
2646 details = NULL((void*)0);
2647
2648 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2649 secondary = f (_("Files in the folder \"%B\" cannot be handled because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be handled because you do "
"not have permissions to see them.", 5)
2650 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be handled because you do "
"not have permissions to see them.", 5)
, dir);
2651 } else {
2652 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, dir);
2653 details = error->message;
2654 }
2655
2656 response = run_warning (job,
2657 primary,
2658 secondary,
2659 details,
2660 FALSE(0),
2661 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
2662 NULL((void*)0));
2663
2664 g_error_free (error);
2665
2666 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2667 abort_job (job);
2668 } else if (response == 1) {
2669 *source_info = saved_info;
2670 goto retry;
2671 } else if (response == 2) {
2672 skip_readdir_error (job, dir);
2673 } else {
2674 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2674, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2675 }
2676 }
2677
2678 } else if (job->skip_all_error) {
2679 g_error_free (error);
2680 skip_file (job, dir);
2681 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2682 g_error_free (error);
2683 } else {
2684 primary = get_scan_primary (source_info->op);
2685 details = NULL((void*)0);
2686
2687 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2688 secondary = f (_("The folder \"%B\" cannot be handled because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
2689 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
, dir);
2690 } else {
2691 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, dir);
2692 details = error->message;
2693 }
2694 /* set show_all to TRUE here, as we don't know how many
2695 * files we'll end up processing yet.
2696 */
2697 response = run_warning (job,
2698 primary,
2699 secondary,
2700 details,
2701 TRUE(!(0)),
2702 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2703 NULL((void*)0));
2704
2705 g_error_free (error);
2706
2707 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2708 abort_job (job);
2709 } else if (response == 1 || response == 2) {
2710 if (response == 1) {
2711 job->skip_all_error = TRUE(!(0));
2712 }
2713 skip_file (job, dir);
2714 } else if (response == 3) {
2715 goto retry;
2716 } else {
2717 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2717, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2718 }
2719 }
2720}
2721
2722static void
2723scan_file (GFile *file,
2724 SourceInfo *source_info,
2725 CommonJob *job)
2726{
2727 GFileInfo *info;
2728 GError *error;
2729 GQueue *dirs;
2730 GFile *dir;
2731 char *primary;
2732 char *secondary;
2733 char *details;
2734 int response;
2735
2736 dirs = g_queue_new ();
2737
2738 retry:
2739 error = NULL((void*)0);
2740 info = g_file_query_info (file,
2741 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2742 G_FILE_ATTRIBUTE_STANDARD_SIZE"standard::size"","
2743 G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE"standard::allocated-size",
2744 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
2745 job->cancellable,
2746 &error);
2747
2748 if (info) {
2749 count_file (info, job, source_info);
2750
2751 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2752 g_queue_push_head (dirs, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)));
2753 }
2754
2755 g_object_unref (info);
2756 } else if (job->skip_all_error) {
2757 g_error_free (error);
2758 skip_file (job, file);
2759 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2760 g_error_free (error);
2761 } else {
2762 primary = get_scan_primary (source_info->op);
2763 details = NULL((void*)0);
2764
2765 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2766 secondary = f (_("The file \"%B\" cannot be handled because you do not have "dcgettext (((void*)0), "The file \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
2767 "permissions to read it.")dcgettext (((void*)0), "The file \"%B\" cannot be handled because you do not have "
"permissions to read it.", 5)
, file);
2768 } else {
2769 secondary = f (_("There was an error getting information about \"%B\".")dcgettext (((void*)0), "There was an error getting information about \"%B\"."
, 5)
, file);
2770 details = error->message;
2771 }
2772 /* set show_all to TRUE here, as we don't know how many
2773 * files we'll end up processing yet.
2774 */
2775 response = run_warning (job,
2776 primary,
2777 secondary,
2778 details,
2779 TRUE(!(0)),
2780 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2781 NULL((void*)0));
2782
2783 g_error_free (error);
2784
2785 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2786 abort_job (job);
2787 } else if (response == 1 || response == 2) {
2788 if (response == 1) {
2789 job->skip_all_error = TRUE(!(0));
2790 }
2791 skip_file (job, file);
2792 } else if (response == 3) {
2793 goto retry;
2794 } else {
2795 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2795, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2796 }
2797 }
2798
2799 while (!job_aborted (job) &&
2800 (dir = g_queue_pop_head (dirs)) != NULL((void*)0)) {
2801 scan_dir (dir, source_info, job, dirs);
2802 g_object_unref (dir);
2803 }
2804
2805 /* Free all from queue if we exited early */
2806 g_queue_foreach (dirs, (GFunc)g_object_unref, NULL((void*)0));
2807 g_queue_free (dirs);
2808}
2809
2810static void
2811scan_sources (GList *files,
2812 SourceInfo *source_info,
2813 CommonJob *job,
2814 OpKind kind)
2815{
2816 GList *l;
2817 GFile *file = NULL((void*)0);
2818
2819 memset (source_info, 0, sizeof (SourceInfo));
2820 source_info->op = kind;
2821
2822 report_count_progress (job, source_info);
2823
2824 for (l = files; l != NULL((void*)0) && !job_aborted (job); l = l->next) {
2825 file = l->data;
2826
2827 scan_file (file,
2828 source_info,
2829 job);
2830 }
2831
2832 /* Make sure we report the final count */
2833 report_count_progress (job, source_info);
2834}
2835
2836static void
2837verify_destination (CommonJob *job,
2838 GFile *dest,
2839 char **dest_fs_id,
2840 goffset required_size)
2841{
2842 GFileInfo *info, *fsinfo;
2843 GError *error;
2844 guint64 free_size;
2845 char *primary, *secondary, *details;
2846 int response;
2847 GFileType file_type;
2848
2849 if (dest_fs_id) {
2850 *dest_fs_id = NULL((void*)0);
2851 }
2852
2853 retry:
2854
2855 error = NULL((void*)0);
2856 info = g_file_query_info (dest,
2857 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
2858 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
2859 0,
2860 job->cancellable,
2861 &error);
2862
2863 if (info == NULL((void*)0)) {
2864 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
2865 g_error_free (error);
2866 return;
2867 }
2868
2869 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2870 details = NULL((void*)0);
2871
2872 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
2873 secondary = f (_("You do not have permissions to access the destination folder.")dcgettext (((void*)0), "You do not have permissions to access the destination folder."
, 5)
);
2874 } else {
2875 secondary = f (_("There was an error getting information about the destination.")dcgettext (((void*)0), "There was an error getting information about the destination."
, 5)
);
2876 details = error->message;
2877 }
2878
2879 response = run_error (job,
2880 primary,
2881 secondary,
2882 details,
2883 FALSE(0),
2884 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
2885 NULL((void*)0));
2886
2887 g_error_free (error);
2888
2889 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2890 abort_job (job);
2891 } else if (response == 1) {
2892 goto retry;
2893 } else {
2894 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2894, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2895 }
2896
2897 return;
2898 }
2899
2900 file_type = g_file_info_get_file_type (info);
2901
2902 if (dest_fs_id) {
2903 *dest_fs_id =
2904 g_strdup (g_file_info_get_attribute_string (info,g_strdup_inline (g_file_info_get_attribute_string (info, "id::filesystem"
))
2905 G_FILE_ATTRIBUTE_ID_FILESYSTEM))g_strdup_inline (g_file_info_get_attribute_string (info, "id::filesystem"
))
;
2906 }
2907
2908 g_object_unref (info);
2909
2910 if (file_type != G_FILE_TYPE_DIRECTORY) {
2911 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2912 secondary = f (_("The destination is not a folder.")dcgettext (((void*)0), "The destination is not a folder.", 5));
2913
2914 response = run_error (job,
2915 primary,
2916 secondary,
2917 NULL((void*)0),
2918 FALSE(0),
2919 CANCELdcgettext (((void*)0), "_Cancel", 5),
2920 NULL((void*)0));
2921
2922 abort_job (job);
2923 return;
2924 }
2925
2926 fsinfo = g_file_query_filesystem_info (dest,
2927 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free"","
2928 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly",
2929 job->cancellable,
2930 NULL((void*)0));
2931 if (fsinfo == NULL((void*)0)) {
2932 /* All sorts of things can go wrong getting the fs info (like not supported)
2933 * only check these things if the fs returns them
2934 */
2935 return;
2936 }
2937
2938 if (required_size > 0 &&
2939 g_file_info_has_attribute (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free")) {
2940 free_size = g_file_info_get_attribute_uint64 (fsinfo,
2941 G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
2942
2943 if (free_size < required_size) {
2944 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2945 secondary = f(_("There is not enough space on the destination. Try to remove files to make space.")dcgettext (((void*)0), "There is not enough space on the destination. Try to remove files to make space."
, 5)
);
2946
2947 details = f (_("There is %S available, but %S is required.")dcgettext (((void*)0), "There is %S available, but %S is required."
, 5)
, free_size, required_size);
2948
2949 response = run_warning (job,
2950 primary,
2951 secondary,
2952 details,
2953 FALSE(0),
2954 CANCELdcgettext (((void*)0), "_Cancel", 5),
2955 COPY_FORCEdcgettext (((void*)0), "Copy _Anyway", 5),
2956 RETRYdcgettext (((void*)0), "_Retry", 5),
2957 NULL((void*)0));
2958
2959 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
2960 abort_job (job);
2961 } else if (response == 2) {
2962 goto retry;
2963 } else if (response == 1) {
2964 /* We are forced to copy - just fall through ... */
2965 } else {
2966 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 2966, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2967 }
2968 }
2969 }
2970
2971 if (!job_aborted (job) &&
2972 g_file_info_get_attribute_boolean (fsinfo,
2973 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY"filesystem::readonly")) {
2974 primary = f (_("Error while copying to \"%B\".")dcgettext (((void*)0), "Error while copying to \"%B\".", 5), dest);
2975 secondary = f (_("The destination is read-only.")dcgettext (((void*)0), "The destination is read-only.", 5));
2976
2977 response = run_error (job,
2978 primary,
2979 secondary,
2980 NULL((void*)0),
2981 FALSE(0),
2982 CANCELdcgettext (((void*)0), "_Cancel", 5),
2983 NULL((void*)0));
2984
2985 g_error_free (error);
2986
2987 abort_job (job);
2988 }
2989
2990 g_object_unref (fsinfo);
2991}
2992
2993static void
2994report_copy_progress (CopyMoveJob *copy_job,
2995 SourceInfo *source_info,
2996 TransferInfo *transfer_info)
2997{
2998 int files_left;
2999 goffset total_size;
3000 double elapsed, transfer_rate;
3001 guint64 now;
3002 CommonJob *job;
3003 gboolean is_move;
3004
3005 job = (CommonJob *)copy_job;
3006
3007 is_move = copy_job->is_move;
3008
3009 now = g_get_monotonic_time ();
3010
3011 if (transfer_info->last_report_time != 0 &&
3012 ABS ((gint64)(transfer_info->last_report_time - now))((((gint64)(transfer_info->last_report_time - now)) < 0
) ? -((gint64)(transfer_info->last_report_time - now)) : (
(gint64)(transfer_info->last_report_time - now)))
< 100 * NSEC_PER_MICROSEC1000) {
3013 return;
3014 }
3015 transfer_info->last_report_time = now;
3016
3017 files_left = source_info->num_files - transfer_info->num_files;
3018
3019 /* Races and whatnot could cause this to be negative... */
3020 if (files_left < 0) {
3021 files_left = 1;
3022 }
3023
3024 if (files_left != transfer_info->last_reported_files_left ||
3025 transfer_info->last_reported_files_left == 0) {
3026 /* Avoid changing this unless files_left changed since last time */
3027 transfer_info->last_reported_files_left = files_left;
3028
3029 if (source_info->num_files == 1) {
3030 if (copy_job->destination != NULL((void*)0)) {
3031 caja_progress_info_take_status (job->progress,
3032 f (is_move ?
3033 _("Moving \"%B\" to \"%B\"")dcgettext (((void*)0), "Moving \"%B\" to \"%B\"", 5):
3034 _("Copying \"%B\" to \"%B\"")dcgettext (((void*)0), "Copying \"%B\" to \"%B\"", 5),
3035 (GFile *)copy_job->files->data,
3036 copy_job->destination));
3037 } else {
3038 caja_progress_info_take_status (job->progress,
3039 f (_("Duplicating \"%B\"")dcgettext (((void*)0), "Duplicating \"%B\"", 5),
3040 (GFile *)copy_job->files->data));
3041 }
3042 } else if (copy_job->files != NULL((void*)0) &&
3043 copy_job->files->next == NULL((void*)0)) {
3044 if (copy_job->destination != NULL((void*)0)) {
3045 caja_progress_info_take_status (job->progress,
3046 f (is_move?
3047 ngettext ("Moving %'d file (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3048 "Moving %'d files (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3049 files_left)dcngettext (((void*)0), "Moving %'d file (in \"%B\") to \"%B\""
, "Moving %'d files (in \"%B\") to \"%B\"", files_left, 5)
3050 :
3051 ngettext ("Copying %'d file (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
3052 "Copying %'d files (in \"%B\") to \"%B\"",dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
3053 files_left)dcngettext (((void*)0), "Copying %'d file (in \"%B\") to \"%B\""
, "Copying %'d files (in \"%B\") to \"%B\"", files_left, 5)
,
3054 files_left,
3055 (GFile *)copy_job->files->data,
3056 copy_job->destination));
3057 } else {
3058 caja_progress_info_take_status (job->progress,
3059 f (ngettext ("Duplicating %'d file (in \"%B\")",dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
3060 "Duplicating %'d files (in \"%B\")",dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
3061 files_left)dcngettext (((void*)0), "Duplicating %'d file (in \"%B\")", "Duplicating %'d files (in \"%B\")"
, files_left, 5)
,
3062 files_left,
3063 (GFile *)copy_job->files->data));
3064 }
3065 } else {
3066 if (copy_job->destination != NULL((void*)0)) {
3067 caja_progress_info_take_status (job->progress,
3068 f (is_move?
3069 ngettext ("Moving %'d file to \"%B\"",dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3070 "Moving %'d files to \"%B\"",dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3071 files_left)dcngettext (((void*)0), "Moving %'d file to \"%B\"", "Moving %'d files to \"%B\""
, files_left, 5)
3072 :
3073 ngettext ("Copying %'d file to \"%B\"",dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
3074 "Copying %'d files to \"%B\"",dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
3075 files_left)dcngettext (((void*)0), "Copying %'d file to \"%B\"", "Copying %'d files to \"%B\""
, files_left, 5)
,
3076 files_left, copy_job->destination));
3077 } else {
3078 caja_progress_info_take_status (job->progress,
3079 f (ngettext ("Duplicating %'d file",dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
3080 "Duplicating %'d files",dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
3081 files_left)dcngettext (((void*)0), "Duplicating %'d file", "Duplicating %'d files"
, files_left, 5)
,
3082 files_left));
3083 }
3084 }
3085 }
3086
3087 total_size = MAX (source_info->num_bytes, transfer_info->num_bytes)(((source_info->num_bytes) > (transfer_info->num_bytes
)) ? (source_info->num_bytes) : (transfer_info->num_bytes
))
;
3088
3089 elapsed = g_timer_elapsed (job->time, NULL((void*)0));
3090 transfer_rate = 0;
3091 if (elapsed > 0) {
3092 transfer_rate = transfer_info->num_bytes / elapsed;
3093 }
3094
3095 if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE15 &&
3096 transfer_rate > 0) {
3097 char *s;
3098 /* Translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */
3099 s = f (_("%S of %S")dcgettext (((void*)0), "%S of %S", 5), transfer_info->num_bytes, total_size);
3100 caja_progress_info_take_details (job->progress, s);
3101 } else {
3102 int remaining_time;
3103 char *s;
3104
3105 remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate;
3106
3107 /* Translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like
3108 * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)"
3109 *
3110 * The singular/plural form will be used depending on the remaining time (i.e. the %T argument).
3111 */
3112 s = f (ngettext ("%S of %S \xE2\x80\x94 %T left (%S/sec)",dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
3113 "%S of %S \xE2\x80\x94 %T left (%S/sec)",dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
3114 seconds_count_format_time_units (remaining_time))dcngettext (((void*)0), "%S of %S \xE2\x80\x94 %T left (%S/sec)"
, "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units
(remaining_time), 5)
,
3115 transfer_info->num_bytes, total_size,
3116 remaining_time,
3117 (goffset)transfer_rate);
3118 caja_progress_info_take_details (job->progress, s);
3119 }
3120
3121 caja_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size);
3122}
3123
3124static int
3125get_max_name_length (GFile *file_dir)
3126{
3127 int max_length;
3128 char *dir;
3129 long max_path;
3130 long max_name;
3131
3132 max_length = -1;
3133
3134 if (!g_file_has_uri_scheme (file_dir, "file"))
3135 return max_length;
3136
3137 dir = g_file_get_path (file_dir);
3138 if (!dir)
3139 return max_length;
3140
3141 max_path = pathconf (dir, _PC_PATH_MAX_PC_PATH_MAX);
3142 max_name = pathconf (dir, _PC_NAME_MAX_PC_NAME_MAX);
3143
3144 if (max_name == -1 && max_path == -1) {
3145 max_length = -1;
3146 } else if (max_name == -1 && max_path != -1) {
3147 max_length = max_path - (strlen (dir) + 1);
3148 } else if (max_name != -1 && max_path == -1) {
3149 max_length = max_name;
3150 } else {
3151 int leftover;
3152
3153 leftover = max_path - (strlen (dir) + 1);
3154
3155 max_length = MIN (leftover, max_name)(((leftover) < (max_name)) ? (leftover) : (max_name));
3156 }
3157
3158 g_free (dir);
3159
3160 return max_length;
3161}
3162
3163#define FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>" "/:;*?\"<>"
3164
3165static gboolean
3166str_replace (char *str,
3167 const char *chars_to_replace,
3168 char replacement)
3169{
3170 gboolean success;
3171 int i;
3172
3173 success = FALSE(0);
3174 for (i = 0; str[i] != '\0'; i++) {
3175 if (strchr (chars_to_replace, str[i])) {
3176 success = TRUE(!(0));
3177 str[i] = replacement;
3178 }
3179 }
3180
3181 return success;
3182}
3183
3184static gboolean
3185make_file_name_valid_for_dest_fs (char *filename,
3186 const char *dest_fs_type)
3187{
3188 if (dest_fs_type != NULL((void*)0) && filename != NULL((void*)0)) {
3189 if (!strcmp (dest_fs_type, "fat") ||
3190 !strcmp (dest_fs_type, "vfat") ||
3191 !strcmp (dest_fs_type, "msdos") ||
3192 !strcmp (dest_fs_type, "msdosfs")) {
3193 gboolean ret;
3194 int i, old_len;
3195
3196 ret = str_replace (filename, FAT_FORBIDDEN_CHARACTERS"/:;*?\"<>", '_');
3197
3198 old_len = strlen (filename);
3199 for (i = 0; i < old_len; i++) {
3200 if (filename[i] != ' ') {
3201 g_strchomp (filename);
3202 ret |= (old_len != strlen (filename));
3203 break;
3204 }
3205 }
3206
3207 return ret;
3208 }
3209 }
3210
3211 return FALSE(0);
3212}
3213
3214static GFile *
3215get_unique_target_file (GFile *src,
3216 GFile *dest_dir,
3217 gboolean same_fs,
3218 const char *dest_fs_type,
3219 int count)
3220{
3221 char *new_name;
3222 GFileInfo *info;
3223 GFile *dest;
3224 int max_length;
3225
3226 max_length = get_max_name_length (dest_dir);
3227
3228 dest = NULL((void*)0);
3229 info = g_file_query_info (src,
3230 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3231 0, NULL((void*)0), NULL((void*)0));
3232 if (info != NULL((void*)0)) {
3233 const char *editname;
3234
3235 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3236
3237 if (editname != NULL((void*)0)) {
3238 new_name = get_duplicate_name (editname, count, max_length);
3239 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3240 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3241 g_free (new_name);
3242 }
3243
3244 g_object_unref (info);
3245 }
3246
3247 if (dest == NULL((void*)0)) {
3248 char *basename;
3249
3250 basename = g_file_get_basename (src);
3251
3252 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3253 new_name = get_duplicate_name (basename, count, max_length);
3254 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3255 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3256 g_free (new_name);
3257 }
3258
3259 if (dest == NULL((void*)0)) {
3260 const char *end;
3261
3262 end = strrchr (basename, '.');
3263 if (end != NULL((void*)0)) {
3264 count += atoi (end + 1);
3265 }
3266 new_name = g_strdup_printf ("%s.%d", basename, count);
3267 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3268 dest = g_file_get_child (dest_dir, new_name);
3269 g_free (new_name);
3270 }
3271
3272 g_free (basename);
3273 }
3274
3275 return dest;
3276}
3277
3278static GFile *
3279get_target_file_for_link (GFile *src,
3280 GFile *dest_dir,
3281 const char *dest_fs_type,
3282 int count)
3283{
3284 char *new_name;
3285 GFileInfo *info;
3286 GFile *dest;
3287 int max_length;
3288
3289 max_length = get_max_name_length (dest_dir);
3290
3291 dest = NULL((void*)0);
3292 info = g_file_query_info (src,
3293 G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name",
3294 0, NULL((void*)0), NULL((void*)0));
3295 if (info != NULL((void*)0)) {
3296 const char *editname;
3297
3298 editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME"standard::edit-name");
3299
3300 if (editname != NULL((void*)0)) {
3301 new_name = get_link_name (editname, count, max_length);
3302 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3303 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3304 g_free (new_name);
3305 }
3306
3307 g_object_unref (info);
3308 }
3309
3310 if (dest == NULL((void*)0)) {
3311 char *basename;
3312
3313 basename = g_file_get_basename (src);
3314 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3315
3316 if (g_utf8_validate (basename, -1, NULL((void*)0))) {
3317 new_name = get_link_name (basename, count, max_length);
3318 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3319 dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL((void*)0));
3320 g_free (new_name);
3321 }
3322
3323 if (dest == NULL((void*)0)) {
3324 if (count == 1) {
3325 new_name = g_strdup_printf ("%s.lnk", basename);
3326 } else {
3327 new_name = g_strdup_printf ("%s.lnk%d", basename, count);
3328 }
3329 make_file_name_valid_for_dest_fs (new_name, dest_fs_type);
3330 dest = g_file_get_child (dest_dir, new_name);
3331 g_free (new_name);
3332 }
3333
3334 g_free (basename);
3335 }
3336
3337 return dest;
3338}
3339
3340static GFile *
3341get_target_file (GFile *src,
3342 GFile *dest_dir,
3343 const char *dest_fs_type,
3344 gboolean same_fs)
3345{
3346 GFile *dest;
3347
3348 dest = NULL((void*)0);
3349 if (!same_fs) {
3350 GFileInfo *info;
3351
3352 info = g_file_query_info (src,
3353 G_FILE_ATTRIBUTE_STANDARD_COPY_NAME"standard::copy-name",
3354 0, NULL((void*)0), NULL((void*)0));
3355
3356 if (info) {
3357 char *copyname;
3358
3359 copyname = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME))g_strdup_inline (g_file_info_get_attribute_string (info, "standard::copy-name"
))
;
3360
3361 if (copyname) {
3362 make_file_name_valid_for_dest_fs (copyname, dest_fs_type);
3363 dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL((void*)0));
3364 g_free (copyname);
3365 }
3366
3367 g_object_unref (info);
3368 }
3369 }
3370
3371 if (dest == NULL((void*)0)) {
3372 char *basename;
3373
3374 basename = g_file_get_basename (src);
3375 make_file_name_valid_for_dest_fs (basename, dest_fs_type);
3376 dest = g_file_get_child (dest_dir, basename);
3377 g_free (basename);
3378 }
3379
3380 return dest;
3381}
3382
3383static gboolean
3384has_fs_id (GFile *file, const char *fs_id)
3385{
3386 GFileInfo *info;
3387 gboolean res;
3388
3389 res = FALSE(0);
3390 info = g_file_query_info (file,
3391 G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem",
3392 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3393 NULL((void*)0), NULL((void*)0));
3394
3395 if (info) {
3396 const char *id;
3397
3398 id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM"id::filesystem");
3399
3400 if (id && strcmp (id, fs_id) == 0) {
3401 res = TRUE(!(0));
3402 }
3403
3404 g_object_unref (info);
3405 }
3406
3407 return res;
3408}
3409
3410static gboolean
3411is_dir (GFile *file)
3412{
3413 GFileInfo *info;
3414 gboolean res;
3415
3416 res = FALSE(0);
3417 info = g_file_query_info (file,
3418 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
3419 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3420 NULL((void*)0), NULL((void*)0));
3421 if (info) {
3422 res = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
3423 g_object_unref (info);
3424 }
3425
3426 return res;
3427}
3428
3429static void copy_move_file (CopyMoveJob *job,
3430 GFile *src,
3431 GFile *dest_dir,
3432 gboolean same_fs,
3433 gboolean unique_names,
3434 char **dest_fs_type,
3435 SourceInfo *source_info,
3436 TransferInfo *transfer_info,
3437 GHashTable *debuting_files,
3438 GdkPoint *point,
3439 gboolean overwrite,
3440 gboolean *skipped_file,
3441 gboolean readonly_source_fs,
3442 gboolean last_item);
3443
3444typedef enum {
3445 CREATE_DEST_DIR_RETRY,
3446 CREATE_DEST_DIR_FAILED,
3447 CREATE_DEST_DIR_SUCCESS
3448} CreateDestDirResult;
3449
3450static CreateDestDirResult
3451create_dest_dir (CommonJob *job,
3452 GFile *src,
3453 GFile **dest,
3454 gboolean same_fs,
3455 char **dest_fs_type)
3456{
3457 GError *error;
3458 GFile *new_dest, *dest_dir;
3459 char *primary, *secondary, *details;
3460 int response;
3461 gboolean handled_invalid_filename;
3462
3463 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
3464
3465 retry:
3466 /* First create the directory, then copy stuff to it before
3467 copying the attributes, because we need to be sure we can write to it */
3468
3469 error = NULL((void*)0);
3470 if (!g_file_make_directory (*dest, job->cancellable, &error)) {
3471 if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3472 g_error_free (error);
3473 return CREATE_DEST_DIR_FAILED;
3474 } else if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
3475 !handled_invalid_filename) {
3476 handled_invalid_filename = TRUE(!(0));
3477
3478 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_81 = 1; else
_g_boolean_var_81 = 0; _g_boolean_var_81; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 3478, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
3479
3480 dest_dir = g_file_get_parent (*dest);
3481
3482 if (dest_dir != NULL((void*)0)) {
3483 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
3484
3485 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
3486 g_object_unref (dest_dir);
3487
3488 if (!g_file_equal (*dest, new_dest)) {
3489 g_object_unref (*dest);
3490 *dest = new_dest;
3491 g_error_free (error);
3492 return CREATE_DEST_DIR_RETRY;
3493 } else {
3494 g_object_unref (new_dest);
3495 }
3496 }
3497 }
3498
3499 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3500 details = NULL((void*)0);
3501
3502 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3503 secondary = f (_("The folder \"%B\" cannot be copied because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to create it in the destination.", 5)
3504 "permissions to create it in the destination.")dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to create it in the destination.", 5)
, src);
3505 } else {
3506 secondary = f (_("There was an error creating the folder \"%B\".")dcgettext (((void*)0), "There was an error creating the folder \"%B\"."
, 5)
, src);
3507 details = error->message;
3508 }
3509
3510 response = run_warning (job,
3511 primary,
3512 secondary,
3513 details,
3514 FALSE(0),
3515 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
3516 NULL((void*)0));
3517
3518 g_error_free (error);
3519
3520 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3521 abort_job (job);
3522 } else if (response == 1) {
3523 /* Skip: Do Nothing */
3524 } else if (response == 2) {
3525 goto retry;
3526 } else {
3527 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3527, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3528 }
3529 return CREATE_DEST_DIR_FAILED;
3530 }
3531 // Start UNDO-REDO
3532 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, *dest);
3533 // End UNDO-REDO
3534 caja_file_changes_queue_file_added (*dest);
3535 return CREATE_DEST_DIR_SUCCESS;
3536}
3537
3538/* a return value of FALSE means retry, i.e.
3539 * the destination has changed and the source
3540 * is expected to re-try the preceeding
3541 * g_file_move() or g_file_copy() call with
3542 * the new destination.
3543 */
3544static gboolean
3545copy_move_directory (CopyMoveJob *copy_job,
3546 GFile *src,
3547 GFile **dest,
3548 gboolean same_fs,
3549 gboolean create_dest,
3550 char **parent_dest_fs_type,
3551 SourceInfo *source_info,
3552 TransferInfo *transfer_info,
3553 GHashTable *debuting_files,
3554 gboolean *skipped_file,
3555 gboolean readonly_source_fs,
3556 gboolean last_item_above)
3557{
3558 GFileInfo *info, *nextinfo;
3559 GError *error;
3560 GFile *src_file;
3561 GFileEnumerator *enumerator;
3562 char *primary, *secondary, *details;
3563 char *dest_fs_type;
3564 int response;
3565 gboolean skip_error;
3566 gboolean local_skipped_file;
3567 CommonJob *job;
3568 GFileCopyFlags flags;
3569 gboolean last_item;
3570
3571 job = (CommonJob *)copy_job;
3572
3573 if (create_dest) {
3574 switch (create_dest_dir (job, src, dest, same_fs, parent_dest_fs_type)) {
3575 case CREATE_DEST_DIR_RETRY:
3576 /* next time copy_move_directory() is called,
3577 * create_dest will be FALSE if a directory already
3578 * exists under the new name (i.e. WOULD_RECURSE)
3579 */
3580 return FALSE(0);
3581
3582 case CREATE_DEST_DIR_FAILED:
3583 *skipped_file = TRUE(!(0));
3584 return TRUE(!(0));
3585
3586 case CREATE_DEST_DIR_SUCCESS:
3587 default:
3588 break;
3589 }
3590
3591 if (debuting_files) {
3592 g_hash_table_replace (debuting_files, g_object_ref (*dest)((__typeof__ (*dest)) (g_object_ref) (*dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
3593 }
3594
3595 }
3596
3597 local_skipped_file = FALSE(0);
3598 dest_fs_type = NULL((void*)0);
3599
3600 skip_error = should_skip_readdir_error (job, src);
3601 retry:
3602 error = NULL((void*)0);
3603 enumerator = g_file_enumerate_children (src,
3604 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3605 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3606 job->cancellable,
3607 &error);
3608 if (enumerator) {
3609 error = NULL((void*)0);
3610
3611 nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error);
3612 while (!job_aborted (job) &&
3613 (info = nextinfo) != NULL((void*)0)) {
3614 caja_progress_info_get_ready (job->progress);
3615
3616 nextinfo = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL((void*)0):&error);
3617 src_file = g_file_get_child (src,
3618 g_file_info_get_name (info));
3619
3620 last_item = (last_item_above) && (!nextinfo);
3621 copy_move_file (copy_job, src_file, *dest, same_fs, FALSE(0), &dest_fs_type,
3622 source_info, transfer_info, NULL((void*)0), NULL((void*)0), FALSE(0), &local_skipped_file,
3623 readonly_source_fs, last_item);
3624 g_object_unref (src_file);
3625 g_object_unref (info);
3626 }
3627 if (nextinfo)
3628 g_object_unref (nextinfo);
3629
3630 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3631 g_object_unref (enumerator);
3632
3633 if (error && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3634 g_error_free (error);
3635 } else if (error) {
3636 if (copy_job->is_move) {
3637 primary = f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
3638 } else {
3639 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3640 }
3641 details = NULL((void*)0);
3642
3643 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3644 secondary = f (_("Files in the folder \"%B\" cannot be copied because you do "dcgettext (((void*)0), "Files in the folder \"%B\" cannot be copied because you do "
"not have permissions to see them.", 5)
3645 "not have permissions to see them.")dcgettext (((void*)0), "Files in the folder \"%B\" cannot be copied because you do "
"not have permissions to see them.", 5)
, src);
3646 } else {
3647 secondary = f (_("There was an error getting information about the files in the folder \"%B\".")dcgettext (((void*)0), "There was an error getting information about the files in the folder \"%B\"."
, 5)
, src);
3648 details = error->message;
3649 }
3650
3651 response = run_warning (job,
3652 primary,
3653 secondary,
3654 details,
3655 FALSE(0),
3656 CANCELdcgettext (((void*)0), "_Cancel", 5), _("_Skip files")dcgettext (((void*)0), "_Skip files", 5),
3657 NULL((void*)0));
3658
3659 g_error_free (error);
3660
3661 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3662 abort_job (job);
3663 } else if (response == 1) {
3664 /* Skip: Do Nothing */
3665 local_skipped_file = TRUE(!(0));
3666 } else {
3667 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3667, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3668 }
3669 }
3670
3671 /* Count the copied directory as a file */
3672 transfer_info->num_files ++;
3673 report_copy_progress (copy_job, source_info, transfer_info);
3674
3675 if (debuting_files) {
3676 g_hash_table_replace (debuting_files, g_object_ref (*dest)((__typeof__ (*dest)) (g_object_ref) (*dest)), GINT_TO_POINTER (create_dest)((gpointer) (glong) (create_dest)));
3677 }
3678 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3679 g_error_free (error);
3680 } else {
3681 if (copy_job->is_move) {
3682 primary = f (_("Error while moving.")dcgettext (((void*)0), "Error while moving.", 5));
3683 } else {
3684 primary = f (_("Error while copying.")dcgettext (((void*)0), "Error while copying.", 5));
3685 }
3686 details = NULL((void*)0);
3687
3688 if (IS_IO_ERROR (error, PERMISSION_DENIED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_PERMISSION_DENIED))
) {
3689 secondary = f (_("The folder \"%B\" cannot be copied because you do not have "dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to read it.", 5)
3690 "permissions to read it.")dcgettext (((void*)0), "The folder \"%B\" cannot be copied because you do not have "
"permissions to read it.", 5)
, src);
3691 } else {
3692 secondary = f (_("There was an error reading the folder \"%B\".")dcgettext (((void*)0), "There was an error reading the folder \"%B\"."
, 5)
, src);
3693 details = error->message;
3694 }
3695
3696 response = run_warning (job,
3697 primary,
3698 secondary,
3699 details,
3700 FALSE(0),
3701 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
3702 NULL((void*)0));
3703
3704 g_error_free (error);
3705
3706 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3707 abort_job (job);
3708 } else if (response == 1) {
3709 /* Skip: Do Nothing */
3710 local_skipped_file = TRUE(!(0));
3711 } else if (response == 2) {
3712 goto retry;
3713 } else {
3714 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3714, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3715 }
3716 }
3717
3718 if (create_dest) {
3719 flags = (readonly_source_fs) ? G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_PERMS
3720 : G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA;
3721 /* Ignore errors here. Failure to copy metadata is not a hard error */
3722 g_file_copy_attributes (src, *dest,
3723 flags,
3724 job->cancellable, NULL((void*)0));
3725 }
3726
3727 if (!job_aborted (job) && copy_job->is_move &&
3728 /* Don't delete source if there was a skipped file */
3729 !local_skipped_file) {
3730 if (!g_file_delete (src, job->cancellable, &error)) {
3731 if (job->skip_all_error) {
3732 goto skip;
3733 }
3734 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
3735 secondary = f (_("Could not remove the source folder.")dcgettext (((void*)0), "Could not remove the source folder.",
5)
);
3736 details = error->message;
3737
3738 response = run_warning (job,
3739 primary,
3740 secondary,
3741 details,
3742 (source_info->num_files - transfer_info->num_files) > 1,
3743 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3744 NULL((void*)0));
3745
3746 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3747 abort_job (job);
3748 } else if (response == 1) { /* skip all */
3749 job->skip_all_error = TRUE(!(0));
3750 local_skipped_file = TRUE(!(0));
3751 } else if (response == 2) { /* skip */
3752 local_skipped_file = TRUE(!(0));
3753 } else {
3754 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3754, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3755 }
3756
3757 skip:
3758 g_error_free (error);
3759 }
3760 }
3761
3762 if (local_skipped_file) {
3763 *skipped_file = TRUE(!(0));
3764 }
3765
3766 g_free (dest_fs_type);
3767 return TRUE(!(0));
3768}
3769
3770static gboolean
3771remove_target_recursively (CommonJob *job,
3772 GFile *src,
3773 GFile *toplevel_dest,
3774 GFile *file)
3775{
3776 GFileEnumerator *enumerator;
3777 GError *error;
3778 GFile *child;
3779 gboolean stop;
3780 char *primary, *secondary, *details;
3781 int response;
3782 GFileInfo *info;
3783
3784 stop = FALSE(0);
3785
3786 error = NULL((void*)0);
3787 enumerator = g_file_enumerate_children (file,
3788 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name",
3789 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3790 job->cancellable,
3791 &error);
3792 if (enumerator) {
3793 error = NULL((void*)0);
3794
3795 while (!job_aborted (job) &&
3796 (info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL((void*)0)) {
3797 child = g_file_get_child (file,
3798 g_file_info_get_name (info));
3799 if (!remove_target_recursively (job, src, toplevel_dest, child)) {
3800 stop = TRUE(!(0));
3801 break;
3802 }
3803 g_object_unref (child);
3804 g_object_unref (info);
3805 }
3806 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
3807 g_object_unref (enumerator);
3808
3809 } else if (IS_IO_ERROR (error, NOT_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_DIRECTORY))
) {
3810 /* Not a dir, continue */
3811 g_error_free (error);
3812
3813 } else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3814 g_error_free (error);
3815 } else {
3816 if (job->skip_all_error) {
3817 goto skip1;
3818 }
3819
3820 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
3821 secondary = f (_("Could not remove files from the already existing folder %F.")dcgettext (((void*)0), "Could not remove files from the already existing folder %F."
, 5)
, file);
3822 details = error->message;
3823
3824 /* set show_all to TRUE here, as we don't know how many
3825 * files we'll end up processing yet.
3826 */
3827 response = run_warning (job,
3828 primary,
3829 secondary,
3830 details,
3831 TRUE(!(0)),
3832 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3833 NULL((void*)0));
3834
3835 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3836 abort_job (job);
3837 } else if (response == 1) { /* skip all */
3838 job->skip_all_error = TRUE(!(0));
3839 } else if (response == 2) { /* skip */
3840 /* do nothing */
3841 } else {
3842 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3842, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3843 }
3844 skip1:
3845 g_error_free (error);
3846
3847 stop = TRUE(!(0));
3848 }
3849
3850 if (stop) {
3851 return FALSE(0);
3852 }
3853
3854 error = NULL((void*)0);
3855
3856 if (!g_file_delete (file, job->cancellable, &error)) {
3857 if (job->skip_all_error ||
3858 IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
3859 goto skip2;
3860 }
3861 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
3862 secondary = f (_("Could not remove the already existing file %F.")dcgettext (((void*)0), "Could not remove the already existing file %F."
, 5)
, file);
3863 details = error->message;
3864
3865 /* set show_all to TRUE here, as we don't know how many
3866 * files we'll end up processing yet.
3867 */
3868 response = run_warning (job,
3869 primary,
3870 secondary,
3871 details,
3872 TRUE(!(0)),
3873 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
3874 NULL((void*)0));
3875
3876 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
3877 abort_job (job);
3878 } else if (response == 1) { /* skip all */
3879 job->skip_all_error = TRUE(!(0));
3880 } else if (response == 2) { /* skip */
3881 /* do nothing */
3882 } else {
3883 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 3883, ((const char*) (__func__)), ((void*)0)); } while (0)
;
3884 }
3885
3886 skip2:
3887 g_error_free (error);
3888
3889 return FALSE(0);
3890 }
3891 caja_file_changes_queue_file_removed (file);
3892
3893 return TRUE(!(0));
3894
3895}
3896
3897typedef struct {
3898 CopyMoveJob *job;
3899 goffset last_size;
3900 SourceInfo *source_info;
3901 TransferInfo *transfer_info;
3902} ProgressData;
3903
3904static void
3905copy_file_progress_callback (goffset current_num_bytes,
3906 goffset total_num_bytes,
3907 gpointer user_data)
3908{
3909 ProgressData *pdata;
3910 goffset new_size;
3911
3912 pdata = user_data;
3913
3914 new_size = current_num_bytes - pdata->last_size;
3915
3916 if (new_size > 0) {
3917 pdata->transfer_info->num_bytes += new_size;
3918 pdata->last_size = current_num_bytes;
3919 report_copy_progress (pdata->job,
3920 pdata->source_info,
3921 pdata->transfer_info);
3922 }
3923}
3924
3925static gboolean
3926test_dir_is_parent (GFile *child, GFile *root)
3927{
3928 GFile *f;
3929
3930 f = g_file_dup (child);
3931 while (f) {
3932 if (g_file_equal (f, root)) {
3933 g_object_unref (f);
3934 return TRUE(!(0));
3935 }
3936 f = g_file_get_parent (f);
3937 }
3938 if (f) {
3939 g_object_unref (f);
3940 }
3941 return FALSE(0);
3942}
3943
3944static char *
3945query_fs_type (GFile *file,
3946 GCancellable *cancellable)
3947{
3948 GFileInfo *fsinfo;
3949 char *ret;
3950
3951 ret = NULL((void*)0);
3952
3953 fsinfo = g_file_query_filesystem_info (file,
3954 G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3955 cancellable,
3956 NULL((void*)0));
3957 if (fsinfo != NULL((void*)0)) {
3958 ret = g_strdup (g_file_info_get_attribute_string (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))g_strdup_inline (g_file_info_get_attribute_string (fsinfo, "filesystem::type"
))
;
3959 g_object_unref (fsinfo);
3960 }
3961
3962 if (ret == NULL((void*)0)) {
3963 /* ensure that we don't attempt to query
3964 * the FS type for each file in a given
3965 * directory, if it can't be queried. */
3966 ret = g_strdup ("")g_strdup_inline ("");
3967 }
3968
3969 return ret;
3970}
3971
3972static gboolean
3973is_trusted_desktop_file (GFile *file,
3974 GCancellable *cancellable)
3975{
3976 char *basename;
3977 gboolean res;
3978 GFileInfo *info;
3979
3980 /* Don't trust non-local files */
3981 if (!g_file_is_native (file)) {
3982 return FALSE(0);
3983 }
3984
3985 basename = g_file_get_basename (file);
3986 if (!g_str_has_suffix (basename, ".desktop")(__builtin_constant_p (".desktop")? __extension__ ({ const char
* const __str = (basename); const char * const __suffix = (".desktop"
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_82; if (__str == ((void*)0) || __suffix
== ((void*)0)) _g_boolean_var_82 = 1; else _g_boolean_var_82
= 0; _g_boolean_var_82; }), 0)) __result = (g_str_has_suffix
) (__str, __suffix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __suffix_len = strlen (((
__suffix) + !(__suffix))); if (__str_len >= __suffix_len) __result
= memcmp (__str + __str_len - __suffix_len, ((__suffix) + !(
__suffix)), __suffix_len) == 0; } __result; }) : (g_str_has_suffix
) (basename, ".desktop") )
) {
3987 g_free (basename);
3988 return FALSE(0);
3989 }
3990 g_free (basename);
3991
3992 info = g_file_query_info (file,
3993 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" ","
3994 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute",
3995 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
3996 cancellable,
3997 NULL((void*)0));
3998
3999 if (info == NULL((void*)0)) {
4000 return FALSE(0);
4001 }
4002
4003 res = FALSE(0);
4004
4005 /* Weird file => not trusted,
4006 Already executable => no need to mark trusted */
4007 if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR &&
4008 !g_file_info_get_attribute_boolean (info,
4009 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE"access::can-execute") &&
4010 caja_is_in_system_dir (file)) {
4011 res = TRUE(!(0));
4012 }
4013 g_object_unref (info);
4014
4015 return res;
4016}
4017
4018typedef struct {
4019 int id;
4020 char *new_name;
4021 gboolean apply_to_all;
4022} ConflictResponseData;
4023
4024typedef struct {
4025 GFile *src;
4026 GFile *dest;
4027 GFile *dest_dir;
4028 GtkWindow *parent;
4029 ConflictResponseData *resp_data;
4030} ConflictDialogData;
4031
4032static gboolean
4033do_run_conflict_dialog (gpointer _data)
4034{
4035 ConflictDialogData *data = _data;
4036 GtkWidget *dialog;
4037 int response;
4038
4039 dialog = caja_file_conflict_dialog_new (data->parent,
4040 data->src,
4041 data->dest,
4042 data->dest_dir);
4043 response = gtk_dialog_run (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))));
4044
4045 if (response == CONFLICT_RESPONSE_RENAME) {
4046 data->resp_data->new_name =
4047 caja_file_conflict_dialog_get_new_name (CAJA_FILE_CONFLICT_DIALOG (dialog)((((CajaFileConflictDialog*) (void *) ((dialog))))));
4048 } else if (response != GTK_RESPONSE_CANCEL ||
4049 response != GTK_RESPONSE_NONE) {
4050 data->resp_data->apply_to_all =
4051 caja_file_conflict_dialog_get_apply_to_all
4052 (CAJA_FILE_CONFLICT_DIALOG (dialog)((((CajaFileConflictDialog*) (void *) ((dialog))))));
4053 }
4054
4055 data->resp_data->id = response;
4056
4057 gtk_widget_destroy (dialog);
4058
4059 return FALSE(0);
4060}
4061
4062static ConflictResponseData *
4063run_conflict_dialog (CommonJob *job,
4064 GFile *src,
4065 GFile *dest,
4066 GFile *dest_dir)
4067{
4068 ConflictDialogData *data;
4069 ConflictResponseData *resp_data;
4070
4071 g_timer_stop (job->time);
4072
4073 data = g_slice_new0 (ConflictDialogData)(ConflictDialogData *) (__extension__ ({ gsize __s = sizeof (
ConflictDialogData); gpointer __p; __p = g_slice_alloc (__s);
memset (__p, 0, __s); __p; }))
;
4074 data->parent = job->parent_window;
4075 data->src = src;
4076 data->dest = dest;
4077 data->dest_dir = dest_dir;
4078
4079 resp_data = g_slice_new0 (ConflictResponseData)(ConflictResponseData *) (__extension__ ({ gsize __s = sizeof
(ConflictResponseData); gpointer __p; __p = g_slice_alloc (__s
); memset (__p, 0, __s); __p; }))
;
4080 resp_data->new_name = NULL((void*)0);
4081 data->resp_data = resp_data;
4082
4083 caja_progress_info_pause (job->progress);
4084 g_io_scheduler_job_send_to_mainloop (job->io_job,
4085 do_run_conflict_dialog,
4086 data,
4087 NULL((void*)0));
4088 caja_progress_info_resume (job->progress);
4089
4090 g_slice_free (ConflictDialogData, data)do { if (1) g_slice_free1 (sizeof (ConflictDialogData), (data
)); else (void) ((ConflictDialogData*) 0 == (data)); } while (
0)
;
4091
4092 g_timer_continue (job->time);
4093
4094 return resp_data;
4095}
4096
4097static void
4098conflict_response_data_free (ConflictResponseData *data)
4099{
4100 g_free (data->new_name);
4101 g_slice_free (ConflictResponseData, data)do { if (1) g_slice_free1 (sizeof (ConflictResponseData), (data
)); else (void) ((ConflictResponseData*) 0 == (data)); } while
(0)
;
4102}
4103
4104static GFile *
4105get_target_file_for_display_name (GFile *dir,
4106 char *name)
4107{
4108 GFile *dest;
4109
4110 dest = NULL((void*)0);
4111 dest = g_file_get_child_for_display_name (dir, name, NULL((void*)0));
4112
4113 if (dest == NULL((void*)0)) {
4114 dest = g_file_get_child (dir, name);
4115 }
4116
4117 return dest;
4118}
4119
4120/* Debuting files is non-NULL only for toplevel items */
4121static void
4122copy_move_file (CopyMoveJob *copy_job,
4123 GFile *src,
4124 GFile *dest_dir,
4125 gboolean same_fs,
4126 gboolean unique_names,
4127 char **dest_fs_type,
4128 SourceInfo *source_info,
4129 TransferInfo *transfer_info,
4130 GHashTable *debuting_files,
4131 GdkPoint *position,
4132 gboolean overwrite,
4133 gboolean *skipped_file,
4134 gboolean readonly_source_fs,
4135 gboolean last_item)
4136{
4137 GFile *dest, *new_dest;
4138 GError *error;
4139 GFileCopyFlags flags;
4140 char *primary, *secondary, *details;
4141 int response;
4142 ProgressData pdata;
4143 gboolean would_recurse, is_merge;
4144 CommonJob *job;
4145 gboolean res;
4146 int unique_name_nr;
4147 gboolean handled_invalid_filename;
4148
4149 job = (CommonJob *)copy_job;
4150
4151 if (should_skip_file (job, src)) {
4152 *skipped_file = TRUE(!(0));
4153 return;
4154 }
4155
4156 unique_name_nr = 1;
4157
4158 // TODO: Here we should get the previous file name UNDO
4159
4160 /* another file in the same directory might have handled the invalid
4161 * filename condition for us
4162 */
4163 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4164
4165 if (unique_names) {
4166 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4167 } else {
4168 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4169 }
4170
4171
4172 /* Don't allow recursive move/copy into itself.
4173 * (We would get a file system error if we proceeded but it is nicer to
4174 * detect and report it at this level) */
4175 if (test_dir_is_parent (dest_dir, src)) {
4176 if (job->skip_all_error) {
4177 goto out;
4178 }
4179
4180 /* the run_warning() frees all strings passed in automatically */
4181 primary = copy_job->is_move ? g_strdup (_("You cannot move a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a folder into itself."
, 5))
4182 : g_strdup (_("You cannot copy a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a folder into itself."
, 5))
;
4183 secondary = g_strdup (_("The destination folder is inside the source folder."))g_strdup_inline (dcgettext (((void*)0), "The destination folder is inside the source folder."
, 5))
;
4184
4185 response = run_warning (job,
4186 primary,
4187 secondary,
4188 NULL((void*)0),
4189 (source_info->num_files - transfer_info->num_files) > 1,
4190 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4191 NULL((void*)0));
4192
4193 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4194 abort_job (job);
4195 } else if (response == 1) { /* skip all */
4196 job->skip_all_error = TRUE(!(0));
4197 } else if (response == 2) { /* skip */
4198 /* do nothing */
4199 } else {
4200 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4200, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4201 }
4202
4203 goto out;
4204 }
4205
4206 /* Don't allow copying over the source or one of the parents of the source.
4207 */
4208 if (test_dir_is_parent (src, dest)) {
4209 if (job->skip_all_error) {
4210 goto out;
4211 }
4212
4213 /* the run_warning() frees all strings passed in automatically */
4214 primary = copy_job->is_move ? g_strdup (_("You cannot move a file over itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a file over itself."
, 5))
4215 : g_strdup (_("You cannot copy a file over itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a file over itself."
, 5))
;
4216 secondary = g_strdup (_("The source file would be overwritten by the destination."))g_strdup_inline (dcgettext (((void*)0), "The source file would be overwritten by the destination."
, 5))
;
4217
4218 response = run_warning (job,
4219 primary,
4220 secondary,
4221 NULL((void*)0),
4222 (source_info->num_files - transfer_info->num_files) > 1,
4223 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4224 NULL((void*)0));
4225
4226 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4227 abort_job (job);
4228 } else if (response == 1) { /* skip all */
4229 job->skip_all_error = TRUE(!(0));
4230 } else if (response == 2) { /* skip */
4231 /* do nothing */
4232 } else {
4233 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4233, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4234 }
4235
4236 goto out;
4237 }
4238
4239
4240 retry:
4241 error = NULL((void*)0);
4242 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS;
4243 if (overwrite) {
4244 flags |= G_FILE_COPY_OVERWRITE;
4245 }
4246 if (readonly_source_fs) {
4247 flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS;
4248 }
4249
4250 pdata.job = copy_job;
4251 pdata.last_size = 0;
4252 pdata.source_info = source_info;
4253 pdata.transfer_info = transfer_info;
4254
4255 if (!is_dir(src) && last_item)
4256 /* this is the last file for this operation, cannot pause anymore */
4257 caja_progress_info_disable_pause (job->progress);
4258
4259 if (copy_job->is_move) {
4260 res = g_file_move (src, dest,
4261 flags,
4262 job->cancellable,
4263 copy_file_progress_callback,
4264 &pdata,
4265 &error);
4266 } else {
4267 res = g_file_copy (src, dest,
4268 flags,
4269 job->cancellable,
4270 copy_file_progress_callback,
4271 &pdata,
4272 &error);
4273 }
4274
4275 if (res) {
4276 if (!copy_job->is_move) {
4277 /* Ignore errors here. Failure to copy metadata is not a hard error */
4278 g_file_copy_attributes (src, dest,
4279 flags | G_FILE_COPY_ALL_METADATA,
4280 job->cancellable, NULL((void*)0));
4281 }
4282
4283 transfer_info->num_files ++;
4284 report_copy_progress (copy_job, source_info, transfer_info);
4285
4286 if (debuting_files) {
4287 if (position) {
4288 caja_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4289 } else {
4290 caja_file_changes_queue_schedule_position_remove (dest);
4291 }
4292
4293 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4294 }
4295 if (copy_job->is_move) {
4296 caja_file_changes_queue_file_moved (src, dest);
4297 } else {
4298 caja_file_changes_queue_file_added (dest);
4299 }
4300
4301 /* If copying a trusted desktop file to the desktop,
4302 mark it as trusted. */
4303 if (copy_job->desktop_location != NULL((void*)0) &&
4304 g_file_equal (copy_job->desktop_location, dest_dir) &&
4305 is_trusted_desktop_file (src, job->cancellable)) {
4306 mark_desktop_file_trusted (job,
4307 job->cancellable,
4308 dest,
4309 FALSE(0));
4310 }
4311
4312 // Start UNDO-REDO
4313 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, dest);
4314 // End UNDO-REDO
4315
4316 g_object_unref (dest);
4317 return;
4318 }
4319
4320 if (!handled_invalid_filename &&
4321 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
) {
4322 handled_invalid_filename = TRUE(!(0));
4323
4324 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_83
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_83 = 1; else
_g_boolean_var_83 = 0; _g_boolean_var_83; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4324, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4325 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4326
4327 if (unique_names) {
4328 new_dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr);
4329 } else {
4330 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4331 }
4332
4333 if (!g_file_equal (dest, new_dest)) {
4334 g_object_unref (dest);
4335 dest = new_dest;
4336
4337 g_error_free (error);
4338 goto retry;
4339 } else {
4340 g_object_unref (new_dest);
4341 }
4342 }
4343
4344 /* Conflict */
4345 if (!overwrite &&
4346 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4347 gboolean is_merge;
4348 ConflictResponseData *response;
4349
4350 g_error_free (error);
4351
4352 if (unique_names) {
4353 g_object_unref (dest);
4354 dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++);
4355 goto retry;
4356 }
4357
4358 is_merge = FALSE(0);
4359
4360 if (is_dir (dest) && is_dir (src)) {
4361 is_merge = TRUE(!(0));
4362 }
4363
4364 if ((is_merge && job->merge_all) ||
4365 (!is_merge && job->replace_all)) {
4366 overwrite = TRUE(!(0));
4367 goto retry;
4368 }
4369
4370 if (job->skip_all_conflict) {
4371 goto out;
4372 }
4373
4374 response = run_conflict_dialog (job, src, dest, dest_dir);
4375
4376 if (response->id == GTK_RESPONSE_CANCEL ||
4377 response->id == GTK_RESPONSE_DELETE_EVENT) {
4378 conflict_response_data_free (response);
4379 abort_job (job);
4380 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4381 if (response->apply_to_all) {
4382 job->skip_all_conflict = TRUE(!(0));
4383 }
4384 conflict_response_data_free (response);
4385 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4386 if (response->apply_to_all) {
4387 if (is_merge) {
4388 job->merge_all = TRUE(!(0));
4389 } else {
4390 job->replace_all = TRUE(!(0));
4391 }
4392 }
4393 overwrite = TRUE(!(0));
4394 conflict_response_data_free (response);
4395 goto retry;
4396 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4397 g_object_unref (dest);
4398 dest = get_target_file_for_display_name (dest_dir,
4399 response->new_name);
4400 conflict_response_data_free (response);
4401 goto retry;
4402 } else {
4403 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4403, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4404 }
4405 }
4406
4407 else if (overwrite &&
4408 IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
) {
4409
4410 g_error_free (error);
4411
4412 if (remove_target_recursively (job, src, dest, dest)) {
4413 goto retry;
4414 }
4415 }
4416
4417 /* Needs to recurse */
4418 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
4419 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
) {
4420 is_merge = error->code == G_IO_ERROR_WOULD_MERGE;
4421 would_recurse = error->code == G_IO_ERROR_WOULD_RECURSE;
4422 g_error_free (error);
4423
4424 if (overwrite && would_recurse) {
4425 error = NULL((void*)0);
4426
4427 /* Copying a dir onto file, first remove the file */
4428 if (!g_file_delete (dest, job->cancellable, &error) &&
4429 !IS_IO_ERROR (error, NOT_FOUND)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_FOUND))
) {
4430 if (job->skip_all_error) {
4431 g_error_free (error);
4432 goto out;
4433 }
4434 if (copy_job->is_move) {
4435 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
4436 } else {
4437 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
4438 }
4439 secondary = f (_("Could not remove the already existing file with the same name in %F.")dcgettext (((void*)0), "Could not remove the already existing file with the same name in %F."
, 5)
, dest_dir);
4440 details = error->message;
4441
4442 /* setting TRUE on show_all here, as we could have
4443 * another error on the same file later.
4444 */
4445 response = run_warning (job,
4446 primary,
4447 secondary,
4448 details,
4449 TRUE(!(0)),
4450 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4451 NULL((void*)0));
4452
4453 g_error_free (error);
4454
4455 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4456 abort_job (job);
4457 } else if (response == 1) { /* skip all */
4458 job->skip_all_error = TRUE(!(0));
4459 } else if (response == 2) { /* skip */
4460 /* do nothing */
4461 } else {
4462 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4462, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4463 }
4464 goto out;
4465
4466 }
4467 if (error) {
4468 g_error_free (error);
4469 error = NULL((void*)0);
4470 }
4471 caja_file_changes_queue_file_removed (dest);
4472 }
4473
4474 if (is_merge) {
4475 /* On merge we now write in the target directory, which may not
4476 be in the same directory as the source, even if the parent is
4477 (if the merged directory is a mountpoint). This could cause
4478 problems as we then don't transcode filenames.
4479 We just set same_fs to FALSE which is safe but a bit slower. */
4480 same_fs = FALSE(0);
4481 }
4482
4483 if (!copy_move_directory (copy_job, src, &dest, same_fs,
4484 would_recurse, dest_fs_type,
4485 source_info, transfer_info,
4486 debuting_files, skipped_file,
4487 readonly_source_fs,
4488 last_item)) {
4489 /* destination changed, since it was an invalid file name */
4490 g_assert (*dest_fs_type != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if (*dest_fs_type != ((void*)0)) _g_boolean_var_84 = 1; else
_g_boolean_var_84 = 0; _g_boolean_var_84; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4490, ((const char*
) (__func__)), "*dest_fs_type != NULL"); } while (0)
;
4491 handled_invalid_filename = TRUE(!(0));
4492 goto retry;
4493 }
4494
4495 g_object_unref (dest);
4496 return;
4497 }
4498
4499 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
4500 g_error_free (error);
4501 }
4502
4503 /* Other error */
4504 else {
4505 if (job->skip_all_error) {
4506 g_error_free (error);
4507 goto out;
4508 }
4509 primary = f (_("Error while copying \"%B\".")dcgettext (((void*)0), "Error while copying \"%B\".", 5), src);
4510 secondary = f (_("There was an error copying the file into %F.")dcgettext (((void*)0), "There was an error copying the file into %F."
, 5)
, dest_dir);
4511 details = error->message;
4512
4513 response = run_warning (job,
4514 primary,
4515 secondary,
4516 details,
4517 (source_info->num_files - transfer_info->num_files) > 1,
4518 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4519 NULL((void*)0));
4520
4521 g_error_free (error);
4522
4523 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4524 abort_job (job);
4525 } else if (response == 1) { /* skip all */
4526 job->skip_all_error = TRUE(!(0));
4527 } else if (response == 2) { /* skip */
4528 /* do nothing */
4529 } else {
4530 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4530, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4531 }
4532 }
4533 out:
4534 *skipped_file = TRUE(!(0)); /* Or aborted, but same-same */
4535 g_object_unref (dest);
4536}
4537
4538static void
4539copy_files (CopyMoveJob *job,
4540 const char *dest_fs_id,
4541 SourceInfo *source_info,
4542 TransferInfo *transfer_info)
4543{
4544 CommonJob *common;
4545 GList *l;
4546 gboolean same_fs;
4547 int i;
4548 GdkPoint *point;
4549 gboolean skipped_file;
4550 gboolean unique_names;
4551 GFile *dest;
4552 GFile *source_dir;
4553 char *dest_fs_type;
4554 gboolean readonly_source_fs;
4555 GFile *src = NULL((void*)0);
4556
4557 dest_fs_type = NULL((void*)0);
4558 readonly_source_fs = FALSE(0);
4559
4560 common = &job->common;
4561
4562 report_copy_progress (job, source_info, transfer_info);
4563
4564 /* Query the source dir, not the file because if its a symlink we'll follow it */
4565 source_dir = g_file_get_parent ((GFile *) job->files->data);
4566 if (source_dir) {
4567 GFileInfo *inf;
4568
4569 inf = g_file_query_filesystem_info (source_dir, "filesystem::readonly", NULL((void*)0), NULL((void*)0));
4570 if (inf != NULL((void*)0)) {
4571 readonly_source_fs = g_file_info_get_attribute_boolean (inf, "filesystem::readonly");
4572 g_object_unref (inf);
4573 }
4574 g_object_unref (source_dir);
4575 }
4576
4577 unique_names = (job->destination == NULL((void*)0));
4578 i = 0;
4579 for (l = job->files;
4580 l != NULL((void*)0) && !job_aborted (common);
4581 l = l->next) {
4582 caja_progress_info_get_ready (common->progress);
4583
4584 src = l->data;
4585
4586 if (i < job->n_icon_positions) {
4587 point = &job->icon_positions[i];
4588 } else {
4589 point = NULL((void*)0);
4590 }
4591
4592
4593 same_fs = FALSE(0);
4594 if (dest_fs_id) {
4595 same_fs = has_fs_id (src, dest_fs_id);
4596 }
4597
4598 if (job->destination) {
4599 dest = g_object_ref (job->destination)((__typeof__ (job->destination)) (g_object_ref) (job->destination
))
;
4600 } else {
4601 dest = g_file_get_parent (src);
4602
4603 }
4604 if (dest) {
4605 skipped_file = FALSE(0);
4606
4607 copy_move_file (job, src, dest,
4608 same_fs, unique_names,
4609 &dest_fs_type,
4610 source_info, transfer_info,
4611 job->debuting_files,
4612 point, FALSE(0), &skipped_file,
4613 readonly_source_fs,
4614 !l->next);
4615 g_object_unref (dest);
4616 }
4617 i++;
4618 }
4619
4620 g_free (dest_fs_type);
4621}
4622
4623static gboolean
4624copy_job_done (gpointer user_data)
4625{
4626 CopyMoveJob *job;
4627
4628 job = user_data;
4629 if (job->done_callback) {
4630 job->done_callback (job->debuting_files, job->done_callback_data);
4631 }
4632
4633 g_list_free_full (job->files, g_object_unref);
4634 if (job->destination) {
4635 g_object_unref (job->destination);
4636 }
4637 if (job->desktop_location) {
4638 g_object_unref (job->desktop_location);
4639 }
4640 g_hash_table_unref (job->debuting_files);
4641 g_free (job->icon_positions);
4642
4643 finalize_common ((CommonJob *)job);
4644
4645 caja_file_changes_consume_changes (TRUE(!(0)));
4646 return FALSE(0);
4647}
4648
4649static gboolean
4650copy_job (GIOSchedulerJob *io_job,
4651 GCancellable *cancellable,
4652 gpointer user_data)
4653{
4654 CopyMoveJob *job;
4655 CommonJob *common;
4656 SourceInfo source_info;
4657 TransferInfo transfer_info;
4658 char *dest_fs_id;
4659 GFile *dest;
4660
4661 job = user_data;
4662 common = &job->common;
4663 common->io_job = io_job;
4664
4665 dest_fs_id = NULL((void*)0);
4666
4667 caja_progress_info_start (job->common.progress);
4668
4669 scan_sources (job->files,
4670 &source_info,
4671 common,
4672 OP_KIND_COPY);
4673 if (job_aborted (common)) {
4674 goto aborted;
4675 }
4676
4677 if (job->destination) {
4678 dest = g_object_ref (job->destination)((__typeof__ (job->destination)) (g_object_ref) (job->destination
))
;
4679 } else {
4680 /* Duplication, no dest,
4681 * use source for free size, etc
4682 */
4683 dest = g_file_get_parent (job->files->data);
4684 }
4685
4686 verify_destination (&job->common,
4687 dest,
4688 &dest_fs_id,
4689 source_info.num_bytes);
4690 g_object_unref (dest);
4691 if (job_aborted (common)) {
4692 goto aborted;
4693 }
4694
4695 g_timer_start (job->common.time);
4696
4697 memset (&transfer_info, 0, sizeof (transfer_info));
4698 copy_files (job,
4699 dest_fs_id,
4700 &source_info, &transfer_info);
4701
4702 aborted:
4703
4704 g_free (dest_fs_id);
4705
4706 g_io_scheduler_job_send_to_mainloop_async (io_job,
4707 copy_job_done,
4708 job,
4709 NULL((void*)0));
4710
4711 return FALSE(0);
4712}
4713
4714static gboolean
4715contains_multiple_items (GList *files)
4716{
4717 GFile *first;
4718
4719 if (g_list_length (files) > 1) {
4720 return TRUE(!(0));
4721 } else {
4722 if (files) {
4723 first = files->data;
4724 if (is_dir (first))
4725 return TRUE(!(0));
4726 }
4727 }
4728
4729 return FALSE(0);
4730}
4731
4732void
4733caja_file_operations_copy (GList *files,
4734 GArray *relative_item_points,
4735 GFile *target_dir,
4736 GtkWindow *parent_window,
4737 CajaCopyCallback done_callback,
4738 gpointer done_callback_data)
4739{
4740 CopyMoveJob *job;
4741
4742 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
4743 job->desktop_location = caja_get_desktop_location ();
4744 job->done_callback = done_callback;
4745 job->done_callback_data = done_callback_data;
4746 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
4747 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
4748 if (relative_item_points != NULL((void*)0) &&
4749 relative_item_points->len > 0) {
4750 job->icon_positions =
4751 g_memdup (relative_item_points->data,
4752 sizeof (GdkPoint) * relative_item_points->len);
4753 job->n_icon_positions = relative_item_points->len;
4754 }
4755 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
4756
4757 inhibit_power_manager ((CommonJob *)job, _("Copying Files")dcgettext (((void*)0), "Copying Files", 5));
4758
4759 // Start UNDO-REDO
4760 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
4761 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_COPY, g_list_length(files));
4762 GFile* src_dir = g_file_get_parent (files->data);
4763 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
4764 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
4765 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
4766 }
4767 // End UNDO-REDO
4768
4769 g_io_scheduler_push_job (copy_job,
4770 job,
4771 NULL((void*)0), /* destroy notify */
4772 0,
4773 job->common.cancellable);
4774}
4775
4776static void
4777report_move_progress (CopyMoveJob *move_job, int total, int left)
4778{
4779 CommonJob *job;
4780
4781 job = (CommonJob *)move_job;
4782
4783 caja_progress_info_take_status (job->progress,
4784 f (_("Preparing to Move to \"%B\"")dcgettext (((void*)0), "Preparing to Move to \"%B\"", 5),
4785 move_job->destination));
4786
4787 caja_progress_info_take_details (job->progress,
4788 f (ngettext ("Preparing to move %'d file",dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
4789 "Preparing to move %'d files",dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
4790 left)dcngettext (((void*)0), "Preparing to move %'d file", "Preparing to move %'d files"
, left, 5)
, left));
4791
4792 caja_progress_info_pulse_progress (job->progress);
4793}
4794
4795typedef struct {
4796 GFile *file;
4797 gboolean overwrite;
4798 gboolean has_position;
4799 GdkPoint position;
4800} MoveFileCopyFallback;
4801
4802static MoveFileCopyFallback *
4803move_copy_file_callback_new (GFile *file,
4804 gboolean overwrite,
4805 GdkPoint *position)
4806{
4807 MoveFileCopyFallback *fallback;
4808
4809 fallback = g_new (MoveFileCopyFallback, 1)(MoveFileCopyFallback *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (MoveFileCopyFallback); 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; }))
;
4810 fallback->file = file;
4811 fallback->overwrite = overwrite;
4812 if (position) {
4813 fallback->has_position = TRUE(!(0));
4814 fallback->position = *position;
4815 } else {
4816 fallback->has_position = FALSE(0);
4817 }
4818
4819 return fallback;
4820}
4821
4822static GList *
4823get_files_from_fallbacks (GList *fallbacks)
4824{
4825 GList *res, *l;
4826 MoveFileCopyFallback *fallback = NULL((void*)0);
4827
4828 res = NULL((void*)0);
4829 for (l = fallbacks; l != NULL((void*)0); l = l->next) {
4830 fallback = l->data;
4831 res = g_list_prepend (res, fallback->file);
4832 }
4833 return g_list_reverse (res);
4834}
4835
4836static void
4837move_file_prepare (CopyMoveJob *move_job,
4838 GFile *src,
4839 GFile *dest_dir,
4840 gboolean same_fs,
4841 char **dest_fs_type,
4842 GHashTable *debuting_files,
4843 GdkPoint *position,
4844 GList **fallback_files,
4845 int files_left)
4846{
4847 GFile *dest, *new_dest;
4848 GError *error;
4849 CommonJob *job;
4850 gboolean overwrite;
4851 char *primary, *secondary, *details;
4852 int response;
4853 GFileCopyFlags flags;
4854 MoveFileCopyFallback *fallback;
4855 gboolean handled_invalid_filename;
4856
4857 overwrite = FALSE(0);
4858 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
4859
4860 job = (CommonJob *)move_job;
4861
4862 dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4863
4864
4865 /* Don't allow recursive move/copy into itself.
4866 * (We would get a file system error if we proceeded but it is nicer to
4867 * detect and report it at this level) */
4868 if (test_dir_is_parent (dest_dir, src)) {
4869 if (job->skip_all_error) {
4870 goto out;
4871 }
4872
4873 /* the run_warning() frees all strings passed in automatically */
4874 primary = move_job->is_move ? g_strdup (_("You cannot move a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot move a folder into itself."
, 5))
4875 : g_strdup (_("You cannot copy a folder into itself."))g_strdup_inline (dcgettext (((void*)0), "You cannot copy a folder into itself."
, 5))
;
4876 secondary = g_strdup (_("The destination folder is inside the source folder."))g_strdup_inline (dcgettext (((void*)0), "The destination folder is inside the source folder."
, 5))
;
4877
4878 response = run_warning (job,
4879 primary,
4880 secondary,
4881 NULL((void*)0),
4882 files_left > 1,
4883 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
4884 NULL((void*)0));
4885
4886 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
4887 abort_job (job);
4888 } else if (response == 1) { /* skip all */
4889 job->skip_all_error = TRUE(!(0));
4890 } else if (response == 2) { /* skip */
4891 /* do nothing */
4892 } else {
4893 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 4893, ((const char*) (__func__)), ((void*)0)); } while (0)
;
4894 }
4895
4896 goto out;
4897 }
4898
4899 retry:
4900 caja_progress_info_get_ready (job->progress);
4901
4902 flags = G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_NO_FALLBACK_FOR_MOVE;
4903 if (overwrite) {
4904 flags |= G_FILE_COPY_OVERWRITE;
4905 }
4906
4907 error = NULL((void*)0);
4908 if (g_file_move (src, dest,
4909 flags,
4910 job->cancellable,
4911 NULL((void*)0),
4912 NULL((void*)0),
4913 &error)) {
4914
4915 if (debuting_files) {
4916 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4917 }
4918
4919 caja_file_changes_queue_file_moved (src, dest);
4920
4921 if (position) {
4922 caja_file_changes_queue_schedule_position_set (dest, *position, job->screen_num);
4923 } else {
4924 caja_file_changes_queue_schedule_position_remove (dest);
4925 }
4926
4927 // Start UNDO-REDO
4928 caja_undostack_manager_data_add_origin_target_pair (job->undo_redo_data, src, dest);
4929 // End UNDO-REDO
4930
4931 return;
4932 }
4933
4934 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
4935 !handled_invalid_filename) {
4936 handled_invalid_filename = TRUE(!(0));
4937
4938 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_85
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_85 = 1; else
_g_boolean_var_85 = 0; _g_boolean_var_85; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 4938, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
4939 *dest_fs_type = query_fs_type (dest_dir, job->cancellable);
4940
4941 new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs);
4942 if (!g_file_equal (dest, new_dest)) {
4943 g_object_unref (dest);
4944 dest = new_dest;
4945 goto retry;
4946 } else {
4947 g_object_unref (new_dest);
4948 }
4949 }
4950
4951 /* Conflict */
4952 else if (!overwrite &&
4953 IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
4954 gboolean is_merge;
4955 ConflictResponseData *response;
4956
4957 g_error_free (error);
4958
4959 is_merge = FALSE(0);
4960 if (is_dir (dest) && is_dir (src)) {
4961 is_merge = TRUE(!(0));
4962 }
4963
4964 if ((is_merge && job->merge_all) ||
4965 (!is_merge && job->replace_all)) {
4966 overwrite = TRUE(!(0));
4967 goto retry;
4968 }
4969
4970 if (job->skip_all_conflict) {
4971 goto out;
4972 }
4973
4974 response = run_conflict_dialog (job, src, dest, dest_dir);
4975
4976 if (response->id == GTK_RESPONSE_CANCEL ||
4977 response->id == GTK_RESPONSE_DELETE_EVENT) {
4978 conflict_response_data_free (response);
4979 abort_job (job);
4980 } else if (response->id == CONFLICT_RESPONSE_SKIP) {
4981 if (response->apply_to_all) {
4982 job->skip_all_conflict = TRUE(!(0));
4983 }
4984 conflict_response_data_free (response);
4985 } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
4986 if (response->apply_to_all) {
4987 if (is_merge) {
4988 job->merge_all = TRUE(!(0));
4989 } else {
4990 job->replace_all = TRUE(!(0));
4991 }
4992 }
4993 overwrite = TRUE(!(0));
4994 conflict_response_data_free (response);
4995 goto retry;
4996 } else if (response->id == CONFLICT_RESPONSE_RENAME) {
4997 g_object_unref (dest);
4998 dest = get_target_file_for_display_name (dest_dir,
4999 response->new_name);
5000 conflict_response_data_free (response);
5001 goto retry;
5002 } else {
5003 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5003, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5004 }
5005 }
5006
5007 else if (IS_IO_ERROR (error, WOULD_RECURSE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_RECURSE))
||
5008 IS_IO_ERROR (error, WOULD_MERGE)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_WOULD_MERGE))
||
5009 IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
||
5010 (overwrite && IS_IO_ERROR (error, IS_DIRECTORY)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_IS_DIRECTORY))
)) {
5011 g_error_free (error);
5012
5013 fallback = move_copy_file_callback_new (src,
5014 overwrite,
5015 position);
5016 *fallback_files = g_list_prepend (*fallback_files, fallback);
5017 }
5018
5019 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
5020 g_error_free (error);
5021 }
5022
5023 /* Other error */
5024 else {
5025 if (job->skip_all_error) {
5026 goto out;
5027 }
5028 primary = f (_("Error while moving \"%B\".")dcgettext (((void*)0), "Error while moving \"%B\".", 5), src);
5029 secondary = f (_("There was an error moving the file into %F.")dcgettext (((void*)0), "There was an error moving the file into %F."
, 5)
, dest_dir);
5030 details = error->message;
5031
5032 response = run_warning (job,
5033 primary,
5034 secondary,
5035 details,
5036 files_left > 1,
5037 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
5038 NULL((void*)0));
5039
5040 g_error_free (error);
5041
5042 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5043 abort_job (job);
5044 } else if (response == 1) { /* skip all */
5045 job->skip_all_error = TRUE(!(0));
5046 } else if (response == 2) { /* skip */
5047 /* do nothing */
5048 } else {
5049 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5049, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5050 }
5051 }
5052
5053 out:
5054 g_object_unref (dest);
5055}
5056
5057static void
5058move_files_prepare (CopyMoveJob *job,
5059 const char *dest_fs_id,
5060 char **dest_fs_type,
5061 GList **fallbacks)
5062{
5063 CommonJob *common;
5064 GList *l;
5065 gboolean same_fs;
5066 gboolean last_item;
5067 int i;
5068 GdkPoint *point;
5069 int total, left;
5070 GFile *src = NULL((void*)0);
5071
5072 common = &job->common;
5073
5074 total = left = g_list_length (job->files);
5075
5076 caja_progress_info_get_ready (common->progress);
5077 report_move_progress (job, total, left);
5078
5079 i = 0;
5080 for (l = job->files;
5081 l != NULL((void*)0) && !job_aborted (common);
5082 l = l->next) {
5083 src = l->data;
5084
5085 last_item = (!l->next) && (!is_dir(src)) && (!(*fallbacks));
5086 if (last_item)
5087 /* this is the last file and there are no fallbacks to process, cannot pause anymore */
5088 caja_progress_info_disable_pause (common->progress);
5089
5090 if (i < job->n_icon_positions) {
5091 point = &job->icon_positions[i];
5092 } else {
5093 point = NULL((void*)0);
5094 }
5095
5096
5097 same_fs = FALSE(0);
5098 if (dest_fs_id) {
5099 same_fs = has_fs_id (src, dest_fs_id);
5100 }
5101
5102 move_file_prepare (job, src, job->destination,
5103 same_fs, dest_fs_type,
5104 job->debuting_files,
5105 point,
5106 fallbacks,
5107 left);
5108 report_move_progress (job, total, --left);
5109 i++;
5110 }
5111
5112 *fallbacks = g_list_reverse (*fallbacks);
5113
5114
5115}
5116
5117static void
5118move_files (CopyMoveJob *job,
5119 GList *fallbacks,
5120 const char *dest_fs_id,
5121 char **dest_fs_type,
5122 SourceInfo *source_info,
5123 TransferInfo *transfer_info)
5124{
5125 CommonJob *common;
5126 GList *l;
5127 gboolean same_fs;
5128 int i;
5129 GdkPoint *point;
5130 gboolean skipped_file;
5131 MoveFileCopyFallback *fallback;
5132 GFile *src = NULL((void*)0);
5133
5134 common = &job->common;
5135
5136 report_copy_progress (job, source_info, transfer_info);
5137
5138 i = 0;
5139 for (l = fallbacks;
5140 l != NULL((void*)0) && !job_aborted (common);
5141 l = l->next) {
5142 caja_progress_info_get_ready (common->progress);
5143
5144 fallback = l->data;
5145 src = fallback->file;
5146
5147 if (fallback->has_position) {
5148 point = &fallback->position;
5149 } else {
5150 point = NULL((void*)0);
5151 }
5152
5153 same_fs = FALSE(0);
5154 if (dest_fs_id) {
5155 same_fs = has_fs_id (src, dest_fs_id);
5156 }
5157
5158 /* Set overwrite to true, as the user has
5159 selected overwrite on all toplevel items */
5160 skipped_file = FALSE(0);
5161 copy_move_file (job, src, job->destination,
5162 same_fs, FALSE(0), dest_fs_type,
5163 source_info, transfer_info,
5164 job->debuting_files,
5165 point, fallback->overwrite, &skipped_file, FALSE(0),
5166 !l->next);
5167 i++;
5168 }
5169}
5170
5171
5172static gboolean
5173move_job_done (gpointer user_data)
5174{
5175 CopyMoveJob *job;
5176
5177 job = user_data;
5178 if (job->done_callback) {
5179 job->done_callback (job->debuting_files, job->done_callback_data);
5180 }
5181
5182 g_list_free_full (job->files, g_object_unref);
5183 g_object_unref (job->destination);
5184 g_hash_table_unref (job->debuting_files);
5185 g_free (job->icon_positions);
5186
5187 finalize_common ((CommonJob *)job);
5188
5189 caja_file_changes_consume_changes (TRUE(!(0)));
5190 return FALSE(0);
5191}
5192
5193static gboolean
5194move_job (GIOSchedulerJob *io_job,
5195 GCancellable *cancellable,
5196 gpointer user_data)
5197{
5198 CopyMoveJob *job;
5199 CommonJob *common;
5200 GList *fallbacks;
5201 SourceInfo source_info;
5202 TransferInfo transfer_info;
5203 char *dest_fs_id;
5204 char *dest_fs_type;
5205 GList *fallback_files;
5206
5207 job = user_data;
5208 common = &job->common;
5209 common->io_job = io_job;
5210
5211 dest_fs_id = NULL((void*)0);
5212 dest_fs_type = NULL((void*)0);
5213
5214 fallbacks = NULL((void*)0);
5215
5216 caja_progress_info_start (job->common.progress);
5217
5218 verify_destination (&job->common,
5219 job->destination,
5220 &dest_fs_id,
5221 -1);
5222 if (job_aborted (common)) {
5223 goto aborted;
5224 }
5225
5226 /* This moves all files that we can do without copy + delete */
5227 move_files_prepare (job, dest_fs_id, &dest_fs_type, &fallbacks);
5228 if (job_aborted (common)) {
5229 goto aborted;
5230 }
5231
5232 /* The rest we need to do deep copy + delete behind on,
5233 so scan for size */
5234
5235 fallback_files = get_files_from_fallbacks (fallbacks);
5236 scan_sources (fallback_files,
5237 &source_info,
5238 common,
5239 OP_KIND_MOVE);
5240
5241 g_list_free (fallback_files);
5242
5243 if (job_aborted (common)) {
5244 goto aborted;
5245 }
5246
5247 verify_destination (&job->common,
5248 job->destination,
5249 NULL((void*)0),
5250 source_info.num_bytes);
5251 if (job_aborted (common)) {
5252 goto aborted;
5253 }
5254
5255 memset (&transfer_info, 0, sizeof (transfer_info));
5256 move_files (job,
5257 fallbacks,
5258 dest_fs_id, &dest_fs_type,
5259 &source_info, &transfer_info);
5260
5261 aborted:
5262 g_list_free_full (fallbacks, g_free);
5263
5264 g_free (dest_fs_id);
5265 g_free (dest_fs_type);
5266
5267 g_io_scheduler_job_send_to_mainloop (io_job,
5268 move_job_done,
5269 job,
5270 NULL((void*)0));
5271
5272 return FALSE(0);
5273}
5274
5275void
5276caja_file_operations_move (GList *files,
5277 GArray *relative_item_points,
5278 GFile *target_dir,
5279 GtkWindow *parent_window,
5280 CajaCopyCallback done_callback,
5281 gpointer done_callback_data)
5282{
5283 CopyMoveJob *job;
5284
5285 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
5286 job->is_move = TRUE(!(0));
5287 job->done_callback = done_callback;
5288 job->done_callback_data = done_callback_data;
5289 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5290 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5291 if (relative_item_points != NULL((void*)0) &&
5292 relative_item_points->len > 0) {
5293 job->icon_positions =
5294 g_memdup (relative_item_points->data,
5295 sizeof (GdkPoint) * relative_item_points->len);
5296 job->n_icon_positions = relative_item_points->len;
5297 }
5298 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5299
5300 inhibit_power_manager ((CommonJob *)job, _("Moving Files")dcgettext (((void*)0), "Moving Files", 5));
5301
5302 // Start UNDO-REDO
5303 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5304 if (g_file_has_uri_scheme (g_list_first(files)->data, "trash")) {
5305 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RESTOREFROMTRASH, g_list_length(files));
5306 } else {
5307 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_MOVE, g_list_length(files));
5308 }
5309 GFile* src_dir = g_file_get_parent (files->data);
5310 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5311 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5312 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
5313 }
5314 // End UNDO-REDO
5315
5316 g_io_scheduler_push_job (move_job,
5317 job,
5318 NULL((void*)0), /* destroy notify */
5319 0,
5320 job->common.cancellable);
5321}
5322
5323static void
5324report_link_progress (CopyMoveJob *link_job, int total, int left)
5325{
5326 CommonJob *job;
5327
5328 job = (CommonJob *)link_job;
5329
5330 caja_progress_info_take_status (job->progress,
5331 f (_("Creating links in \"%B\"")dcgettext (((void*)0), "Creating links in \"%B\"", 5),
5332 link_job->destination));
5333
5334 caja_progress_info_take_details (job->progress,
5335 f (ngettext ("Making link to %'d file",dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
5336 "Making links to %'d files",dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
5337 left)dcngettext (((void*)0), "Making link to %'d file", "Making links to %'d files"
, left, 5)
, left));
5338
5339 caja_progress_info_set_progress (job->progress, left, total);
5340}
5341
5342static char *
5343get_abs_path_for_symlink (GFile *file)
5344{
5345 GFile *root, *parent;
5346 char *relative, *abs;
5347
5348 if (g_file_is_native (file)) {
5349 return g_file_get_path (file);
5350 }
5351
5352 root = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
5353 while ((parent = g_file_get_parent (root)) != NULL((void*)0)) {
5354 g_object_unref (root);
5355 root = parent;
5356 }
5357
5358 relative = g_file_get_relative_path (root, file);
5359 g_object_unref (root);
5360 abs = g_strconcat ("/", relative, NULL((void*)0));
5361 g_free (relative);
5362 return abs;
5363}
5364
5365
5366static void
5367link_file (CopyMoveJob *job,
5368 GFile *src, GFile *dest_dir,
5369 char **dest_fs_type,
5370 GHashTable *debuting_files,
5371 GdkPoint *position,
5372 int files_left)
5373{
5374 GFile *src_dir, *dest, *new_dest;
5375 int count;
5376 char *path;
5377 gboolean not_local;
5378 GError *error;
5379 CommonJob *common;
5380 char *primary, *secondary, *details;
5381 int response;
5382 gboolean handled_invalid_filename;
5383
5384 common = (CommonJob *)job;
5385
5386 count = 0;
5387
5388 src_dir = g_file_get_parent (src);
5389 if (g_file_equal (src_dir, dest_dir)) {
5390 count = 1;
5391 }
5392 g_object_unref (src_dir);
5393
5394 handled_invalid_filename = *dest_fs_type != NULL((void*)0);
5395
5396 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5397
5398 retry:
5399 error = NULL((void*)0);
5400 not_local = FALSE(0);
5401
5402 path = get_abs_path_for_symlink (src);
5403 if (path == NULL((void*)0)) {
5404 not_local = TRUE(!(0));
5405 } else if (g_file_make_symbolic_link (dest,
5406 path,
5407 common->cancellable,
5408 &error)) {
5409 // Start UNDO-REDO
5410 caja_undostack_manager_data_add_origin_target_pair (common->undo_redo_data, src, dest);
5411 // End UNDO-REDO
5412 g_free (path);
5413 if (debuting_files) {
5414 g_hash_table_replace (debuting_files, g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest)), GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
5415 }
5416
5417 caja_file_changes_queue_file_added (dest);
5418 if (position) {
5419 caja_file_changes_queue_schedule_position_set (dest, *position, common->screen_num);
5420 } else {
5421 caja_file_changes_queue_schedule_position_remove (dest);
5422 }
5423
5424 g_object_unref (dest);
5425
5426 return;
5427 }
5428 g_free (path);
5429
5430 if (error != NULL((void*)0) &&
5431 IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
5432 !handled_invalid_filename) {
5433 handled_invalid_filename = TRUE(!(0));
5434
5435 g_assert (*dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if (*dest_fs_type == ((void*)0)) _g_boolean_var_86 = 1; else
_g_boolean_var_86 = 0; _g_boolean_var_86; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 5435, ((const char*
) (__func__)), "*dest_fs_type == NULL"); } while (0)
;
5436 *dest_fs_type = query_fs_type (dest_dir, common->cancellable);
5437
5438 new_dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count);
5439
5440 if (!g_file_equal (dest, new_dest)) {
5441 g_object_unref (dest);
5442 dest = new_dest;
5443 g_error_free (error);
5444
5445 goto retry;
5446 } else {
5447 g_object_unref (new_dest);
5448 }
5449 }
5450 /* Conflict */
5451 if (error != NULL((void*)0) && IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
5452 g_object_unref (dest);
5453 dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count++);
5454 g_error_free (error);
5455 goto retry;
5456 }
5457
5458 else if (error != NULL((void*)0) && IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
5459 g_error_free (error);
5460 }
5461
5462 /* Other error */
5463 else {
5464 if (common->skip_all_error) {
5465 goto out;
5466 }
5467 primary = f (_("Error while creating link to %B.")dcgettext (((void*)0), "Error while creating link to %B.", 5), src);
5468 if (not_local) {
5469 secondary = f (_("Symbolic links only supported for local files")dcgettext (((void*)0), "Symbolic links only supported for local files"
, 5)
);
5470 details = NULL((void*)0);
5471 } else if (error != NULL((void*)0) && IS_IO_ERROR (error, NOT_SUPPORTED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_NOT_SUPPORTED))
) {
5472 secondary = f (_("The target doesn't support symbolic links.")dcgettext (((void*)0), "The target doesn't support symbolic links."
, 5)
);
5473 details = NULL((void*)0);
5474 } else {
5475 secondary = f (_("There was an error creating the symlink in %F.")dcgettext (((void*)0), "There was an error creating the symlink in %F."
, 5)
, dest_dir);
5476 details = error ? error->message : NULL((void*)0);
5477 }
5478
5479 response = run_warning (common,
5480 primary,
5481 secondary,
5482 details,
5483 files_left > 1,
5484 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIP_ALLdcgettext (((void*)0), "S_kip All", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
5485 NULL((void*)0));
5486
5487 if (error) {
5488 g_error_free (error);
5489 }
5490
5491 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
5492 abort_job (common);
5493 } else if (response == 1) { /* skip all */
5494 common->skip_all_error = TRUE(!(0));
5495 } else if (response == 2) { /* skip */
5496 /* do nothing */
5497 } else {
5498 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 5498, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5499 }
5500 }
5501
5502 out:
5503 g_object_unref (dest);
5504}
5505
5506static gboolean
5507link_job_done (gpointer user_data)
5508{
5509 CopyMoveJob *job;
5510
5511 job = user_data;
5512 if (job->done_callback) {
5513 job->done_callback (job->debuting_files, job->done_callback_data);
5514 }
5515
5516 g_list_free_full (job->files, g_object_unref);
5517 g_object_unref (job->destination);
5518 g_hash_table_unref (job->debuting_files);
5519 g_free (job->icon_positions);
5520
5521 finalize_common ((CommonJob *)job);
5522
5523 caja_file_changes_consume_changes (TRUE(!(0)));
5524 return FALSE(0);
5525}
5526
5527static gboolean
5528link_job (GIOSchedulerJob *io_job,
5529 GCancellable *cancellable,
5530 gpointer user_data)
5531{
5532 CopyMoveJob *job;
5533 CommonJob *common;
5534 GFile *src;
5535 GdkPoint *point;
5536 char *dest_fs_type;
5537 int total, left;
5538 int i;
5539 GList *l;
5540
5541 job = user_data;
5542 common = &job->common;
5543 common->io_job = io_job;
5544
5545 dest_fs_type = NULL((void*)0);
5546
5547 caja_progress_info_start (job->common.progress);
5548
5549 verify_destination (&job->common,
5550 job->destination,
5551 NULL((void*)0),
5552 -1);
5553 if (job_aborted (common)) {
5554 goto aborted;
5555 }
5556
5557 total = left = g_list_length (job->files);
5558
5559 report_link_progress (job, total, left);
5560
5561 i = 0;
5562 for (l = job->files;
5563 l != NULL((void*)0) && !job_aborted (common);
5564 l = l->next) {
5565 caja_progress_info_get_ready (common->progress);
5566
5567 src = l->data;
5568
5569 if (i < job->n_icon_positions) {
5570 point = &job->icon_positions[i];
5571 } else {
5572 point = NULL((void*)0);
5573 }
5574
5575
5576 link_file (job, src, job->destination,
5577 &dest_fs_type, job->debuting_files,
5578 point, left);
5579 report_link_progress (job, total, --left);
5580 i++;
5581
5582 }
5583
5584 aborted:
5585 g_free (dest_fs_type);
5586
5587 g_io_scheduler_job_send_to_mainloop (io_job,
5588 link_job_done,
5589 job,
5590 NULL((void*)0));
5591
5592 return FALSE(0);
5593}
5594
5595void
5596caja_file_operations_link (GList *files,
5597 GArray *relative_item_points,
5598 GFile *target_dir,
5599 GtkWindow *parent_window,
5600 CajaCopyCallback done_callback,
5601 gpointer done_callback_data)
5602{
5603 CopyMoveJob *job;
5604
5605 job = op_job_new (CopyMoveJob, parent_window, TRUE, FALSE)((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (!(0)), (0))))
;
5606 job->done_callback = done_callback;
5607 job->done_callback_data = done_callback_data;
5608 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5609 job->destination = g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5610 if (relative_item_points != NULL((void*)0) &&
5611 relative_item_points->len > 0) {
5612 job->icon_positions =
5613 g_memdup (relative_item_points->data,
5614 sizeof (GdkPoint) * relative_item_points->len);
5615 job->n_icon_positions = relative_item_points->len;
5616 }
5617 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5618
5619 // Start UNDO-REDO
5620 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5621 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATELINK, g_list_length(files));
5622 GFile* src_dir = g_file_get_parent (files->data);
5623 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5624 g_object_ref (target_dir)((__typeof__ (target_dir)) (g_object_ref) (target_dir));
5625 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, target_dir);
5626 }
5627 // End UNDO-REDO
5628
5629 g_io_scheduler_push_job (link_job,
5630 job,
5631 NULL((void*)0), /* destroy notify */
5632 0,
5633 job->common.cancellable);
5634}
5635
5636
5637void
5638caja_file_operations_duplicate (GList *files,
5639 GArray *relative_item_points,
5640 GtkWindow *parent_window,
5641 CajaCopyCallback done_callback,
5642 gpointer done_callback_data)
5643{
5644 CopyMoveJob *job;
5645
5646 job = op_job_new (CopyMoveJob, parent_window, FALSE, contains_multiple_items (files))((CopyMoveJob *)(init_common (sizeof(CopyMoveJob), parent_window
, (0), contains_multiple_items (files))))
;
5647 job->done_callback = done_callback;
5648 job->done_callback_data = done_callback_data;
5649 job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL((void*)0));
5650 job->destination = NULL((void*)0);
5651 if (relative_item_points != NULL((void*)0) &&
5652 relative_item_points->len > 0) {
5653 job->icon_positions =
5654 g_memdup (relative_item_points->data,
5655 sizeof (GdkPoint) * relative_item_points->len);
5656 job->n_icon_positions = relative_item_points->len;
5657 }
5658 job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL((void*)0));
5659
5660 // Start UNDO-REDO
5661 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5662 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_DUPLICATE, g_list_length(files));
5663 GFile* src_dir = g_file_get_parent (files->data);
5664 caja_undostack_manager_data_set_src_dir (job->common.undo_redo_data, src_dir);
5665 g_object_ref (src_dir)((__typeof__ (src_dir)) (g_object_ref) (src_dir));
5666 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, src_dir);
5667 }
5668 // End UNDO-REDO
5669
5670 g_io_scheduler_push_job (copy_job,
5671 job,
5672 NULL((void*)0), /* destroy notify */
5673 0,
5674 job->common.cancellable);
5675}
5676
5677static gboolean
5678set_permissions_job_done (gpointer user_data)
5679{
5680 SetPermissionsJob *job;
5681
5682 job = user_data;
5683
5684 g_object_unref (job->file);
5685
5686 if (job->done_callback) {
5687 job->done_callback (job->done_callback_data);
5688 }
5689
5690 finalize_common ((CommonJob *)job);
5691 return FALSE(0);
5692}
5693
5694static void
5695set_permissions_file (SetPermissionsJob *job,
5696 GFile *file,
5697 GFileInfo *info)
5698{
5699 CommonJob *common;
5700 gboolean free_info;
5701 guint32 current;
5702 guint32 value;
5703 guint32 mask;
5704
5705 common = (CommonJob *)job;
5706
5707 caja_progress_info_pulse_progress (common->progress);
5708
5709 caja_progress_info_get_ready (common->progress);
5710
5711 free_info = FALSE(0);
5712 if (info == NULL((void*)0)) {
5713 free_info = TRUE(!(0));
5714 info = g_file_query_info (file,
5715 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5716 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5717 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5718 common->cancellable,
5719 NULL((void*)0));
5720 /* Ignore errors */
5721 if (info == NULL((void*)0)) {
5722 return;
5723 }
5724 }
5725
5726 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5727 value = job->dir_permissions;
5728 mask = job->dir_mask;
5729 } else {
5730 value = job->file_permissions;
5731 mask = job->file_mask;
5732 }
5733
5734
5735 if (!job_aborted (common) &&
5736 g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
5737 current = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
5738 // Start UNDO-REDO
5739 caja_undostack_manager_data_add_file_permissions(common->undo_redo_data, file, current);
5740 // End UNDO-REDO
5741 current = (current & ~mask) | value;
5742
5743 g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5744 current, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5745 common->cancellable, NULL((void*)0));
5746 }
5747
5748 if (!job_aborted (common) && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
5749 GFileEnumerator *enumerator;
5750
5751 enumerator = g_file_enumerate_children (file,
5752 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name"","
5753 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
5754 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
5755 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
5756 common->cancellable,
5757 NULL((void*)0));
5758 if (enumerator) {
5759 GFile *child = NULL((void*)0);
5760 GFileInfo *child_info = NULL((void*)0);
5761
5762 while (!job_aborted (common) &&
5763 (child_info = g_file_enumerator_next_file (enumerator, common->cancellable, NULL((void*)0))) != NULL((void*)0)) {
5764 child = g_file_get_child (file,
5765 g_file_info_get_name (child_info));
5766 set_permissions_file (job, child, child_info);
5767 g_object_unref (child);
5768 g_object_unref (child_info);
5769 }
5770 g_file_enumerator_close (enumerator, common->cancellable, NULL((void*)0));
5771 g_object_unref (enumerator);
5772 }
5773 }
5774 if (free_info) {
5775 g_object_unref (info);
5776 }
5777}
5778
5779
5780static gboolean
5781set_permissions_job (GIOSchedulerJob *io_job,
5782 GCancellable *cancellable,
5783 gpointer user_data)
5784{
5785 SetPermissionsJob *job = user_data;
5786 CommonJob *common;
5787
5788 common = (CommonJob *)job;
5789 common->io_job = io_job;
5790
5791 caja_progress_info_set_status (common->progress,
5792 _("Setting permissions")dcgettext (((void*)0), "Setting permissions", 5));
5793
5794 caja_progress_info_start (job->common.progress);
5795
5796 set_permissions_file (job, job->file, NULL((void*)0));
5797
5798 g_io_scheduler_job_send_to_mainloop_async (io_job,
5799 set_permissions_job_done,
5800 job,
5801 NULL((void*)0));
5802
5803 return FALSE(0);
5804}
5805
5806
5807
5808void
5809caja_file_set_permissions_recursive (const char *directory,
5810 guint32 file_permissions,
5811 guint32 file_mask,
5812 guint32 dir_permissions,
5813 guint32 dir_mask,
5814 CajaOpCallback callback,
5815 gpointer callback_data)
5816{
5817 SetPermissionsJob *job;
5818
5819 job = op_job_new (SetPermissionsJob, NULL, TRUE, FALSE)((SetPermissionsJob *)(init_common (sizeof(SetPermissionsJob)
, ((void*)0), (!(0)), (0))))
;
5820 job->file = g_file_new_for_uri (directory);
5821 job->file_permissions = file_permissions;
5822 job->file_mask = file_mask;
5823 job->dir_permissions = dir_permissions;
5824 job->dir_mask = dir_mask;
5825 job->done_callback = callback;
5826 job->done_callback_data = callback_data;
5827
5828 // Start UNDO-REDO
5829 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
5830 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_RECURSIVESETPERMISSIONS, 1);
This statement is never executed
5831 g_object_ref (job->file)((__typeof__ (job->file)) (g_object_ref) (job->file));
5832 caja_undostack_manager_data_set_dest_dir (job->common.undo_redo_data, job->file);
5833 caja_undostack_manager_data_set_recursive_permissions(job->common.undo_redo_data, file_permissions, file_mask, dir_permissions, dir_mask);
5834 }
5835 // End UNDO-REDO
5836
5837 g_io_scheduler_push_job (set_permissions_job,
5838 job,
5839 NULL((void*)0),
5840 0,
5841 NULL((void*)0));
5842}
5843
5844static GList *
5845location_list_from_uri_list (const GList *uris)
5846{
5847 const GList *l;
5848 GList *files;
5849 GFile *f = NULL((void*)0);
5850
5851 files = NULL((void*)0);
5852 for (l = uris; l != NULL((void*)0); l = l->next) {
5853 f = g_file_new_for_uri (l->data);
5854 files = g_list_prepend (files, f);
5855 }
5856
5857 return g_list_reverse (files);
5858}
5859
5860typedef struct {
5861 CajaCopyCallback real_callback;
5862 gpointer real_data;
5863} MoveTrashCBData;
5864
5865static void
5866callback_for_move_to_trash (GHashTable *debuting_uris,
5867 gboolean user_cancelled,
5868 MoveTrashCBData *data)
5869{
5870 if (data->real_callback)
5871 data->real_callback (debuting_uris, data->real_data);
5872 g_slice_free (MoveTrashCBData, data)do { if (1) g_slice_free1 (sizeof (MoveTrashCBData), (data));
else (void) ((MoveTrashCBData*) 0 == (data)); } while (0)
;
5873}
5874
5875void
5876caja_file_operations_copy_move (const GList *item_uris,
5877 GArray *relative_item_points,
5878 const char *target_dir,
5879 GdkDragAction copy_action,
5880 GtkWidget *parent_view,
5881 CajaCopyCallback done_callback,
5882 gpointer done_callback_data)
5883{
5884 GList *locations;
5885 GList *p;
5886 GFile *src_dir;
5887 GFile *dest;
5888 GtkWindow *parent_window;
5889 gboolean target_is_mapping;
5890 gboolean have_nonmapping_source;
5891
5892 dest = NULL((void*)0);
5893 target_is_mapping = FALSE(0);
5894 have_nonmapping_source = FALSE(0);
5895
5896 if (target_dir) {
5897 dest = g_file_new_for_uri (target_dir);
5898 if (g_file_has_uri_scheme (dest, "burn")) {
5899 target_is_mapping = TRUE(!(0));
5900 }
5901 }
5902
5903 locations = location_list_from_uri_list (item_uris);
5904
5905 for (p = location_list_from_uri_list (item_uris); p != NULL((void*)0); p = p->next) {
5906 if (!g_file_has_uri_scheme ((GFile* )p->data, "burn")) {
5907 have_nonmapping_source = TRUE(!(0));
5908 }
5909 }
5910
5911 if (target_is_mapping && have_nonmapping_source && copy_action == GDK_ACTION_MOVE) {
5912 /* never move to "burn:///", but fall back to copy.
5913 * This is a workaround, because otherwise the source files would be removed.
5914 */
5915 copy_action = GDK_ACTION_COPY;
5916 }
5917
5918 parent_window = NULL((void*)0);
5919 if (parent_view) {
5920 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
5921 }
5922
5923 src_dir = g_file_get_parent (locations->data);
5924
5925 if (copy_action == GDK_ACTION_COPY) {
5926 if (target_dir == NULL((void*)0) ||
5927 (src_dir != NULL((void*)0) &&
5928 g_file_equal (src_dir, dest))) {
5929 caja_file_operations_duplicate (locations,
5930 relative_item_points,
5931 parent_window,
5932 done_callback, done_callback_data);
5933 } else {
5934 caja_file_operations_copy (locations,
5935 relative_item_points,
5936 dest,
5937 parent_window,
5938 done_callback, done_callback_data);
5939 }
5940 } else if (copy_action == GDK_ACTION_MOVE) {
5941 if (g_file_has_uri_scheme (dest, "trash")) {
5942 MoveTrashCBData *cb_data;
5943
5944 cb_data = g_slice_new0 (MoveTrashCBData)(MoveTrashCBData *) (__extension__ ({ gsize __s = sizeof (MoveTrashCBData
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
5945 cb_data->real_callback = done_callback;
5946 cb_data->real_data = done_callback_data;
5947 caja_file_operations_trash_or_delete (locations,
5948 parent_window,
5949 (CajaDeleteCallback) callback_for_move_to_trash,
5950 cb_data);
5951 } else if (src_dir == NULL((void*)0) || !g_file_equal (src_dir, dest)) {
5952 caja_file_operations_move (locations,
5953 relative_item_points,
5954 dest,
5955 parent_window,
5956 done_callback, done_callback_data);
5957 }
5958 } else {
5959 caja_file_operations_link (locations,
5960 relative_item_points,
5961 dest,
5962 parent_window,
5963 done_callback, done_callback_data);
5964 }
5965
5966 g_list_free_full (locations, g_object_unref);
5967 if (dest) {
5968 g_object_unref (dest);
5969 }
5970
5971 if (src_dir) {
5972 g_object_unref (src_dir);
5973 }
5974}
5975
5976static gboolean
5977create_job_done (gpointer user_data)
5978{
5979 CreateJob *job;
5980
5981 job = user_data;
5982 if (job->done_callback) {
5983 job->done_callback (job->created_file, job->done_callback_data);
5984 }
5985
5986 g_object_unref (job->dest_dir);
5987 if (job->src) {
5988 g_object_unref (job->src);
5989 }
5990 g_free (job->src_data);
5991 g_free (job->filename);
5992 if (job->created_file) {
5993 g_object_unref (job->created_file);
5994 }
5995
5996 finalize_common ((CommonJob *)job);
5997
5998 caja_file_changes_consume_changes (TRUE(!(0)));
5999 return FALSE(0);
6000}
6001
6002static gboolean
6003create_job (GIOSchedulerJob *io_job,
6004 GCancellable *cancellable,
6005 gpointer user_data)
6006{
6007 CreateJob *job;
6008 CommonJob *common;
6009 int count;
6010 GFile *dest;
6011 char *filename, *filename2, *new_filename;
6012 char *dest_fs_type;
6013 GError *error;
6014 gboolean res;
6015 gboolean filename_is_utf8;
6016 char *primary, *secondary, *details;
6017 int response;
6018 char *data;
6019 int length;
6020 GFileOutputStream *out;
6021 gboolean handled_invalid_filename;
6022 int max_length;
6023
6024 job = user_data;
6025 common = &job->common;
6026 common->io_job = io_job;
6027
6028 caja_progress_info_start (job->common.progress);
6029
6030 handled_invalid_filename = FALSE(0);
6031
6032 dest_fs_type = NULL((void*)0);
6033 filename = NULL((void*)0);
6034 dest = NULL((void*)0);
6035
6036 max_length = get_max_name_length (job->dest_dir);
6037
6038 verify_destination (common,
6039 job->dest_dir,
6040 NULL((void*)0), -1);
6041 if (job_aborted (common)) {
6042 goto aborted;
6043 }
6044
6045 filename = g_strdup (job->filename)g_strdup_inline (job->filename);
6046 filename_is_utf8 = FALSE(0);
6047 if (filename) {
6048 filename_is_utf8 = g_utf8_validate (filename, -1, NULL((void*)0));
6049 }
6050 if (filename == NULL((void*)0)) {
6051 if (job->make_dir) {
6052 /* Translators: the initial name of a new folder */
6053 filename = g_strdup (_("untitled folder"))g_strdup_inline (dcgettext (((void*)0), "untitled folder", 5)
)
;
6054 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6055 } else {
6056 if (job->src != NULL((void*)0)) {
6057 filename = g_file_get_basename (job->src);
6058 }
6059 if (filename == NULL((void*)0)) {
6060 /* Translators: the initial name of a new empty file */
6061 filename = g_strdup (_("new file"))g_strdup_inline (dcgettext (((void*)0), "new file", 5));
6062 filename_is_utf8 = TRUE(!(0)); /* Pass in utf8 */
6063 }
6064 }
6065 }
6066
6067 make_file_name_valid_for_dest_fs (filename, dest_fs_type);
6068 if (filename_is_utf8) {
6069 dest = g_file_get_child_for_display_name (job->dest_dir, filename, NULL((void*)0));
6070 }
6071 if (dest == NULL((void*)0)) {
6072 dest = g_file_get_child (job->dest_dir, filename);
6073 }
6074 count = 1;
6075
6076 retry:
6077 caja_progress_info_get_ready (common->progress);
6078
6079 error = NULL((void*)0);
6080 if (job->make_dir) {
6081 res = g_file_make_directory (dest,
6082 common->cancellable,
6083 &error);
6084 // Start UNDO-REDO
6085 if (res) {
6086 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6087 g_file_get_uri(dest),
6088 NULL((void*)0));
6089 }
6090 // End UNDO-REDO
6091 } else {
6092 if (job->src) {
6093 res = g_file_copy (job->src,
6094 dest,
6095 G_FILE_COPY_NONE,
6096 common->cancellable,
6097 NULL((void*)0), NULL((void*)0),
6098 &error);
6099 // Start UNDO-REDO
6100 if (res) {
6101 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6102 g_file_get_uri(dest),
6103 g_file_get_uri(job->src));
6104 }
6105 // End UNDO-REDO
6106 } else {
6107 data = "";
6108 length = 0;
6109 if (job->src_data) {
6110 data = job->src_data;
6111 length = job->length;
6112 }
6113
6114 out = g_file_create (dest,
6115 G_FILE_CREATE_NONE,
6116 common->cancellable,
6117 &error);
6118 if (out) {
6119 res = g_output_stream_write_all (G_OUTPUT_STREAM (out)((((GOutputStream*) (void *) ((out))))),
6120 data, length,
6121 NULL((void*)0),
6122 common->cancellable,
6123 &error);
6124 if (res) {
6125 res = g_output_stream_close (G_OUTPUT_STREAM (out)((((GOutputStream*) (void *) ((out))))),
6126 common->cancellable,
6127 &error);
6128 // Start UNDO-REDO
6129 if (res) {
6130 caja_undostack_manager_data_set_create_data(common->undo_redo_data,
6131 g_file_get_uri(dest),
6132 g_strdup(data)g_strdup_inline (data));
6133 }
6134 // End UNDO-REDO
6135 }
6136
6137 /* This will close if the write failed and we didn't close */
6138 g_object_unref (out);
6139 } else {
6140 res = FALSE(0);
6141 }
6142 }
6143 }
6144
6145 if (res) {
6146 job->created_file = g_object_ref (dest)((__typeof__ (dest)) (g_object_ref) (dest));
6147 caja_file_changes_queue_file_added (dest);
6148 if (job->has_position) {
6149 caja_file_changes_queue_schedule_position_set (dest, job->position, common->screen_num);
6150 } else {
6151 caja_file_changes_queue_schedule_position_remove (dest);
6152 }
6153 } else {
6154 g_assert (error != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (error != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 6154, ((const char*
) (__func__)), "error != NULL"); } while (0)
;
6155
6156 if (IS_IO_ERROR (error, INVALID_FILENAME)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_INVALID_FILENAME))
&&
6157 !handled_invalid_filename) {
6158 handled_invalid_filename = TRUE(!(0));
6159
6160 g_assert (dest_fs_type == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if (dest_fs_type == ((void*)0)) _g_boolean_var_88 = 1; else
_g_boolean_var_88 = 0; _g_boolean_var_88; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-file-operations.c", 6160, ((const char*
) (__func__)), "dest_fs_type == NULL"); } while (0)
;
6161 dest_fs_type = query_fs_type (job->dest_dir, common->cancellable);
6162
6163 g_object_unref (dest);
6164
6165 if (count == 1) {
6166 new_filename = g_strdup (filename)g_strdup_inline (filename);
6167 } else if (job->make_dir) {
6168 filename2 = g_strdup_printf ("%s %d", filename, count);
6169
6170 new_filename = NULL((void*)0);
6171 if (max_length > 0 && strlen (filename2) > max_length) {
6172 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6173 }
6174
6175 if (new_filename == NULL((void*)0)) {
6176 new_filename = g_strdup (filename2)g_strdup_inline (filename2);
6177 }
6178
6179 g_free (filename2);
6180 } else {
6181 new_filename = get_duplicate_name (filename, count, max_length);
6182 }
6183
6184 if (make_file_name_valid_for_dest_fs (new_filename, dest_fs_type)) {
6185 g_object_unref (dest);
6186
6187 if (filename_is_utf8) {
6188 dest = g_file_get_child_for_display_name (job->dest_dir, new_filename, NULL((void*)0));
6189 }
6190 if (dest == NULL((void*)0)) {
6191 dest = g_file_get_child (job->dest_dir, new_filename);
6192 }
6193
6194 g_free (new_filename);
6195 g_error_free (error);
6196 goto retry;
6197 }
6198 g_free (new_filename);
6199 } else if (IS_IO_ERROR (error, EXISTS)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_EXISTS))
) {
6200 g_object_unref (dest);
6201 dest = NULL((void*)0);
6202 if (job->make_dir) {
6203 filename2 = g_strdup_printf ("%s %d", filename, ++count);
6204 if (max_length > 0 && strlen (filename2) > max_length) {
6205 new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length);
6206 if (new_filename != NULL((void*)0)) {
6207 g_free (filename2);
6208 filename2 = new_filename;
6209 }
6210 }
6211 } else {
6212 filename2 = get_duplicate_name (filename, count++, max_length);
6213 }
6214 make_file_name_valid_for_dest_fs (filename2, dest_fs_type);
6215 if (filename_is_utf8) {
6216 dest = g_file_get_child_for_display_name (job->dest_dir, filename2, NULL((void*)0));
6217 }
6218 if (dest == NULL((void*)0)) {
6219 dest = g_file_get_child (job->dest_dir, filename2);
6220 }
6221 g_free (filename2);
6222 g_error_free (error);
6223 goto retry;
6224 }
6225
6226 else if (IS_IO_ERROR (error, CANCELLED)(((error)->domain == g_io_error_quark() && (error)
->code == G_IO_ERROR_CANCELLED))
) {
6227 g_error_free (error);
6228 }
6229
6230 /* Other error */
6231 else {
6232 if (job->make_dir) {
6233 primary = f (_("Error while creating directory %B.")dcgettext (((void*)0), "Error while creating directory %B.", 5
)
, dest);
6234 } else {
6235 primary = f (_("Error while creating file %B.")dcgettext (((void*)0), "Error while creating file %B.", 5), dest);
6236 }
6237 secondary = f (_("There was an error creating the directory in %F.")dcgettext (((void*)0), "There was an error creating the directory in %F."
, 5)
, job->dest_dir);
6238 details = error->message;
6239
6240 response = run_warning (common,
6241 primary,
6242 secondary,
6243 details,
6244 FALSE(0),
6245 CANCELdcgettext (((void*)0), "_Cancel", 5), SKIPdcgettext (((void*)0), "_Skip", 5),
6246 NULL((void*)0));
6247
6248 g_error_free (error);
6249
6250 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6251 abort_job (common);
6252 } else if (response == 1) { /* skip */
6253 /* do nothing */
6254 } else {
6255 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6255, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6256 }
6257 }
6258 }
6259
6260 aborted:
6261 if (dest) {
6262 g_object_unref (dest);
6263 }
6264 g_free (filename);
6265 g_free (dest_fs_type);
6266 g_io_scheduler_job_send_to_mainloop_async (io_job,
6267 create_job_done,
6268 job,
6269 NULL((void*)0));
6270
6271 return FALSE(0);
6272}
6273
6274void
6275caja_file_operations_new_folder (GtkWidget *parent_view,
6276 GdkPoint *target_point,
6277 const char *parent_dir,
6278 CajaCreateCallback done_callback,
6279 gpointer done_callback_data)
6280{
6281 CreateJob *job;
6282 GtkWindow *parent_window;
6283
6284 parent_window = NULL((void*)0);
6285 if (parent_view) {
6286 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6287 }
6288
6289 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6290 job->done_callback = done_callback;
6291 job->done_callback_data = done_callback_data;
6292 job->dest_dir = g_file_new_for_uri (parent_dir);
6293 job->make_dir = TRUE(!(0));
6294 if (target_point != NULL((void*)0)) {
6295 job->position = *target_point;
6296 job->has_position = TRUE(!(0));
6297 }
6298
6299 // Start UNDO-REDO
6300 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6301 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEFOLDER, 1);
6302 }
6303 // End UNDO-REDO
6304
6305 g_io_scheduler_push_job (create_job,
6306 job,
6307 NULL((void*)0), /* destroy notify */
6308 0,
6309 job->common.cancellable);
6310}
6311
6312void
6313caja_file_operations_new_file_from_template (GtkWidget *parent_view,
6314 GdkPoint *target_point,
6315 const char *parent_dir,
6316 const char *target_filename,
6317 const char *template_uri,
6318 CajaCreateCallback done_callback,
6319 gpointer done_callback_data)
6320{
6321 CreateJob *job;
6322 GtkWindow *parent_window;
6323
6324 parent_window = NULL((void*)0);
6325 if (parent_view) {
6326 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6327 }
6328
6329 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6330 job->done_callback = done_callback;
6331 job->done_callback_data = done_callback_data;
6332 job->dest_dir = g_file_new_for_uri (parent_dir);
6333 if (target_point != NULL((void*)0)) {
6334 job->position = *target_point;
6335 job->has_position = TRUE(!(0));
6336 }
6337 job->filename = g_strdup (target_filename)g_strdup_inline (target_filename);
6338
6339 if (template_uri) {
6340 job->src = g_file_new_for_uri (template_uri);
6341 }
6342
6343 // Start UNDO-REDO
6344 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6345 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEFILEFROMTEMPLATE, 1);
6346 }
6347 // End UNDO-REDO
6348
6349 g_io_scheduler_push_job (create_job,
6350 job,
6351 NULL((void*)0), /* destroy notify */
6352 0,
6353 job->common.cancellable);
6354}
6355
6356void
6357caja_file_operations_new_file (GtkWidget *parent_view,
6358 GdkPoint *target_point,
6359 const char *parent_dir,
6360 const char *target_filename,
6361 const char *initial_contents,
6362 int length,
6363 CajaCreateCallback done_callback,
6364 gpointer done_callback_data)
6365{
6366 CreateJob *job;
6367 GtkWindow *parent_window;
6368
6369 parent_window = NULL((void*)0);
6370 if (parent_view) {
6371 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6372 }
6373
6374 job = op_job_new (CreateJob, parent_window, TRUE, FALSE)((CreateJob *)(init_common (sizeof(CreateJob), parent_window,
(!(0)), (0))))
;
6375 job->done_callback = done_callback;
6376 job->done_callback_data = done_callback_data;
6377 job->dest_dir = g_file_new_for_uri (parent_dir);
6378 if (target_point != NULL((void*)0)) {
6379 job->position = *target_point;
6380 job->has_position = TRUE(!(0));
6381 }
6382 job->src_data = g_memdup (initial_contents, length);
6383 job->length = length;
6384 job->filename = g_strdup (target_filename)g_strdup_inline (target_filename);
6385
6386 // Start UNDO-REDO
6387 if (!caja_undostack_manager_is_undo_redo(caja_undostack_manager_instance())) {
6388 job->common.undo_redo_data = caja_undostack_manager_data_new (CAJA_UNDOSTACK_CREATEEMPTYFILE, 1);
6389 }
6390 // End UNDO-REDO
6391
6392 g_io_scheduler_push_job (create_job,
6393 job,
6394 NULL((void*)0), /* destroy notify */
6395 0,
6396 job->common.cancellable);
6397}
6398
6399
6400
6401static void
6402delete_trash_file (CommonJob *job,
6403 GFile *file,
6404 gboolean del_file,
6405 gboolean del_children)
6406{
6407 caja_progress_info_get_ready (job->progress);
6408
6409 if (job_aborted (job)) {
6410 return;
6411 }
6412
6413 if (del_children) {
6414 GFileEnumerator *enumerator;
6415
6416 enumerator = g_file_enumerate_children (file,
6417 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" ","
6418 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
6419 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6420 job->cancellable,
6421 NULL((void*)0));
6422 if (enumerator) {
6423 GFileInfo *info = NULL((void*)0);
6424 GFile *child = NULL((void*)0);
6425
6426 while (!job_aborted (job) &&
6427 (info = g_file_enumerator_next_file (enumerator, job->cancellable, NULL((void*)0))) != NULL((void*)0)) {
6428 child = g_file_get_child (file,
6429 g_file_info_get_name (info));
6430 delete_trash_file (job, child, TRUE(!(0)),
6431 g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY);
6432 g_object_unref (child);
6433 g_object_unref (info);
6434 }
6435 g_file_enumerator_close (enumerator, job->cancellable, NULL((void*)0));
6436 g_object_unref (enumerator);
6437 }
6438 }
6439
6440 if (!job_aborted (job) && del_file) {
6441 g_file_delete (file, job->cancellable, NULL((void*)0));
6442 }
6443}
6444
6445static gboolean
6446empty_trash_job_done (gpointer user_data)
6447{
6448 EmptyTrashJob *job;
6449
6450 job = user_data;
6451
6452 g_list_free_full (job->trash_dirs, g_object_unref);
6453
6454 if (job->done_callback) {
6455 job->done_callback (job->done_callback_data);
6456 }
6457
6458 caja_undostack_manager_trash_has_emptied(caja_undostack_manager_instance());
6459
6460 finalize_common ((CommonJob *)job);
6461 return FALSE(0);
6462}
6463
6464static gboolean
6465empty_trash_job (GIOSchedulerJob *io_job,
6466 GCancellable *cancellable,
6467 gpointer user_data)
6468{
6469 EmptyTrashJob *job = user_data;
6470 CommonJob *common;
6471 GList *l;
6472 gboolean confirmed;
6473
6474 common = (CommonJob *)job;
6475 common->io_job = io_job;
6476
6477 caja_progress_info_start (job->common.progress);
6478
6479 if (job->should_confirm) {
6480 confirmed = confirm_empty_trash (common);
6481 } else {
6482 confirmed = TRUE(!(0));
6483 }
6484 if (confirmed) {
6485 for (l = job->trash_dirs;
6486 l != NULL((void*)0) && !job_aborted (common);
6487 l = l->next) {
6488 delete_trash_file (common, l->data, FALSE(0), TRUE(!(0)));
6489 }
6490 }
6491
6492 g_io_scheduler_job_send_to_mainloop_async (io_job,
6493 empty_trash_job_done,
6494 job,
6495 NULL((void*)0));
6496
6497 return FALSE(0);
6498}
6499
6500void
6501caja_file_operations_empty_trash (GtkWidget *parent_view)
6502{
6503 EmptyTrashJob *job;
6504 GtkWindow *parent_window;
6505
6506 parent_window = NULL((void*)0);
6507 if (parent_view) {
6508 parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW(gtk_window_get_type ()));
6509 }
6510
6511 job = op_job_new (EmptyTrashJob, parent_window, TRUE, FALSE)((EmptyTrashJob *)(init_common (sizeof(EmptyTrashJob), parent_window
, (!(0)), (0))))
;
6512 job->trash_dirs = g_list_prepend (job->trash_dirs,
6513 g_file_new_for_uri ("trash:"));
6514 job->should_confirm = TRUE(!(0));
6515
6516 inhibit_power_manager ((CommonJob *)job, _("Emptying Trash")dcgettext (((void*)0), "Emptying Trash", 5));
6517
6518 g_io_scheduler_push_job (empty_trash_job,
6519 job,
6520 NULL((void*)0),
6521 0,
6522 NULL((void*)0));
6523}
6524
6525static gboolean
6526mark_trusted_job_done (gpointer user_data)
6527{
6528 MarkTrustedJob *job = user_data;
6529
6530 g_object_unref (job->file);
6531
6532 if (job->done_callback) {
6533 job->done_callback (job->done_callback_data);
6534 }
6535
6536 finalize_common ((CommonJob *)job);
6537 return FALSE(0);
6538}
6539
6540#define TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
6541
6542static void
6543mark_desktop_file_trusted (CommonJob *common,
6544 GCancellable *cancellable,
6545 GFile *file,
6546 gboolean interactive)
6547{
6548 char *contents, *new_contents;
6549 gsize length, new_length;
6550 GError *error;
6551 guint32 current_perms, new_perms;
6552 int response;
6553 GFileInfo *info;
6554
6555 retry:
6556 caja_progress_info_get_ready (common->progress);
6557
6558 error = NULL((void*)0);
6559 if (!g_file_load_contents (file,
6560 cancellable,
6561 &contents, &length,
6562 NULL((void*)0), &error)) {
6563 if (interactive) {
6564 response = run_error (common,
6565 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6566 error->message,
6567 NULL((void*)0),
6568 FALSE(0),
6569 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6570 NULL((void*)0));
6571 } else {
6572 response = 0;
6573 }
6574
6575
6576 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6577 abort_job (common);
6578 } else if (response == 1) {
6579 goto retry;
6580 } else {
6581 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6581, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6582 }
6583
6584 goto out;
6585 }
6586
6587 if (!g_str_has_prefix (contents, "#!")(__builtin_constant_p ("#!")? __extension__ ({ const char * const
__str = (contents); const char * const __prefix = ("#!"); gboolean
__result = (0); if (__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if (__str == ((void*)0) || __prefix == ((void*)0)) _g_boolean_var_89
= 1; else _g_boolean_var_89 = 0; _g_boolean_var_89; }), 0)) __result
= (g_str_has_prefix) (__str, __prefix); else { const size_t __str_len
= strlen (((__str) + !(__str))); const size_t __prefix_len =
strlen (((__prefix) + !(__prefix))); if (__str_len >= __prefix_len
) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix
)), __prefix_len) == 0; } __result; }) : (g_str_has_prefix) (
contents, "#!") )
) {
6588 new_length = length + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n") + 1;
6589 new_contents = g_malloc0 (new_length);
6590
6591 g_strlcpy (new_contents, TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n", new_length);
6592 memcpy (new_contents + strlen (TRUSTED_SHEBANG"#!/usr/bin/env xdg-open\n"),
6593 contents, length);
6594
6595 if (!g_file_replace_contents (file,
6596 new_contents,
6597 new_length,
6598 NULL((void*)0),
6599 FALSE(0), 0,
6600 NULL((void*)0), cancellable, &error)) {
6601 g_free (contents);
6602 g_free (new_contents);
6603
6604 if (interactive) {
6605 response = run_error (common,
6606 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6607 error->message,
6608 NULL((void*)0),
6609 FALSE(0),
6610 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6611 NULL((void*)0));
6612 } else {
6613 response = 0;
6614 }
6615
6616 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6617 abort_job (common);
6618 } else if (response == 1) {
6619 goto retry;
6620 } else {
6621 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6621, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6622 }
6623
6624 goto out;
6625 }
6626 g_free (new_contents);
6627
6628 }
6629 g_free (contents);
6630
6631 info = g_file_query_info (file,
6632 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type"","
6633 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6634 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6635 common->cancellable,
6636 &error);
6637
6638 if (info == NULL((void*)0)) {
6639 if (interactive) {
6640 response = run_error (common,
6641 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6642 error->message,
6643 NULL((void*)0),
6644 FALSE(0),
6645 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6646 NULL((void*)0));
6647 } else {
6648 response = 0;
6649 }
6650
6651 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6652 abort_job (common);
6653 } else if (response == 1) {
6654 goto retry;
6655 } else {
6656 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6656, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6657 }
6658
6659 goto out;
6660 }
6661
6662
6663 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode")) {
6664 current_perms = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
6665 new_perms = current_perms | S_IXGRP(0100 >> 3) | S_IXUSR0100 | S_IXOTH((0100 >> 3) >> 3);
6666
6667 if ((current_perms != new_perms) &&
6668 !g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
6669 new_perms, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
6670 common->cancellable, &error))
6671 {
6672 g_object_unref (info);
6673
6674 if (interactive) {
6675 response = run_error (common,
6676 g_strdup (_("Unable to mark launcher trusted (executable)"))g_strdup_inline (dcgettext (((void*)0), "Unable to mark launcher trusted (executable)"
, 5))
,
6677 error->message,
6678 NULL((void*)0),
6679 FALSE(0),
6680 CANCELdcgettext (((void*)0), "_Cancel", 5), RETRYdcgettext (((void*)0), "_Retry", 5),
6681 NULL((void*)0));
6682 } else {
6683 response = 0;
6684 }
6685
6686 if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
6687 abort_job (common);
6688 } else if (response == 1) {
6689 goto retry;
6690 } else {
6691 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "caja-file-operations.c"
, 6691, ((const char*) (__func__)), ((void*)0)); } while (0)
;
6692 }
6693
6694 goto out;
6695 }
6696 }
6697 g_object_unref (info);
6698
6699 g_file_set_attribute_string (file,
6700 "metadata::" CAJA_METADATA_KEY_TRUSTED_LAUNCHER"caja-trusted-launcher", "true",
6701 G_FILE_QUERY_INFO_NONE,
6702 cancellable,
6703 NULL((void*)0));
6704 out:
6705 ;
6706}
6707
6708static gboolean
6709mark_trusted_job (GIOSchedulerJob *io_job,
6710 GCancellable *cancellable,
6711 gpointer user_data)
6712{
6713 MarkTrustedJob *job = user_data;
6714 CommonJob *common;
6715
6716 common = (CommonJob *)job;
6717 common->io_job = io_job;
6718
6719 caja_progress_info_start (job->common.progress);
6720
6721 mark_desktop_file_trusted (common,
6722 cancellable,
6723 job->file,
6724 job->interactive);
6725
6726 g_io_scheduler_job_send_to_mainloop_async (io_job,
6727 mark_trusted_job_done,
6728 job,
6729 NULL((void*)0));
6730
6731 return FALSE(0);
6732}
6733
6734void
6735caja_file_mark_desktop_file_trusted (GFile *file,
6736 GtkWindow *parent_window,
6737 gboolean interactive,
6738 CajaOpCallback done_callback,
6739 gpointer done_callback_data)
6740{
6741 MarkTrustedJob *job;
6742
6743 job = op_job_new (MarkTrustedJob, parent_window, TRUE, FALSE)((MarkTrustedJob *)(init_common (sizeof(MarkTrustedJob), parent_window
, (!(0)), (0))))
;
6744 job->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
6745 job->interactive = interactive;
6746 job->done_callback = done_callback;
6747 job->done_callback_data = done_callback_data;
6748
6749 g_io_scheduler_push_job (mark_trusted_job,
6750 job,
6751 NULL((void*)0),
6752 0,
6753 NULL((void*)0));
6754}
6755
6756#if !defined (CAJA_OMIT_SELF_CHECK)
6757
6758void
6759caja_self_check_file_operations (void)
6760{
6761 setlocale (LC_MESSAGES5, "C");
6762
6763
6764 /* test the next duplicate name generator */
6765 EEL_CHECK_STRING_RESULT (get_duplicate_name (" (copy)", 1, -1), " (another copy)")do { eel_before_check ("get_duplicate_name (\" (copy)\", 1, -1)"
, "caja-file-operations.c", 6765); eel_check_string_result (get_duplicate_name
(" (copy)", 1, -1), " (another copy)"); } while (0)
;
6766 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo", 1, -1), "foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo\", 1, -1)",
"caja-file-operations.c", 6766); eel_check_string_result (get_duplicate_name
("foo", 1, -1), "foo (copy)"); } while (0)
;
6767 EEL_CHECK_STRING_RESULT (get_duplicate_name (".bashrc", 1, -1), ".bashrc (copy)")do { eel_before_check ("get_duplicate_name (\".bashrc\", 1, -1)"
, "caja-file-operations.c", 6767); eel_check_string_result (get_duplicate_name
(".bashrc", 1, -1), ".bashrc (copy)"); } while (0)
;
6768 EEL_CHECK_STRING_RESULT (get_duplicate_name (".foo.txt", 1, -1), ".foo (copy).txt")do { eel_before_check ("get_duplicate_name (\".foo.txt\", 1, -1)"
, "caja-file-operations.c", 6768); eel_check_string_result (get_duplicate_name
(".foo.txt", 1, -1), ".foo (copy).txt"); } while (0)
;
6769 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo", 1, -1), "foo foo (copy)")do { eel_before_check ("get_duplicate_name (\"foo foo\", 1, -1)"
, "caja-file-operations.c", 6769); eel_check_string_result (get_duplicate_name
("foo foo", 1, -1), "foo foo (copy)"); } while (0)
;
6770 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo.txt", 1, -1), "foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo.txt\", 1, -1)"
, "caja-file-operations.c", 6770); eel_check_string_result (get_duplicate_name
("foo.txt", 1, -1), "foo (copy).txt"); } while (0)
;
6771 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt\", 1, -1)"
, "caja-file-operations.c", 6771); eel_check_string_result (get_duplicate_name
("foo foo.txt", 1, -1), "foo foo (copy).txt"); } while (0)
;
6772 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt")do { eel_before_check ("get_duplicate_name (\"foo foo.txt txt\", 1, -1)"
, "caja-file-operations.c", 6772); eel_check_string_result (get_duplicate_name
("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt"); } while
(0)
;
6773 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...txt", 1, -1), "foo (copy)...txt")do { eel_before_check ("get_duplicate_name (\"foo...txt\", 1, -1)"
, "caja-file-operations.c", 6773); eel_check_string_result (get_duplicate_name
("foo...txt", 1, -1), "foo (copy)...txt"); } while (0)
;
6774 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...", 1, -1), "foo (copy)...")do { eel_before_check ("get_duplicate_name (\"foo...\", 1, -1)"
, "caja-file-operations.c", 6774); eel_check_string_result (get_duplicate_name
("foo...", 1, -1), "foo (copy)..."); } while (0)
;
6775 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo. (copy)", 1, -1), "foo. (another copy)")do { eel_before_check ("get_duplicate_name (\"foo. (copy)\", 1, -1)"
, "caja-file-operations.c", 6775); eel_check_string_result (get_duplicate_name
("foo. (copy)", 1, -1), "foo. (another copy)"); } while (0)
;
6776 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy)", 1, -1), "foo (another copy)")do { eel_before_check ("get_duplicate_name (\"foo (copy)\", 1, -1)"
, "caja-file-operations.c", 6776); eel_check_string_result (get_duplicate_name
("foo (copy)", 1, -1), "foo (another copy)"); } while (0)
;
6777 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy).txt", 1, -1), "foo (another copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (copy).txt\", 1, -1)"
, "caja-file-operations.c", 6777); eel_check_string_result (get_duplicate_name
("foo (copy).txt", 1, -1), "foo (another copy).txt"); } while
(0)
;
6778 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy)", 1, -1), "foo (3rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (another copy)\", 1, -1)"
, "caja-file-operations.c", 6778); eel_check_string_result (get_duplicate_name
("foo (another copy)", 1, -1), "foo (3rd copy)"); } while (0
)
;
6779 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy).txt", 1, -1), "foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (another copy).txt\", 1, -1)"
, "caja-file-operations.c", 6779); eel_check_string_result (get_duplicate_name
("foo (another copy).txt", 1, -1), "foo (3rd copy).txt"); } while
(0)
;
6780 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (another copy).txt\", 1, -1)"
, "caja-file-operations.c", 6780); eel_check_string_result (get_duplicate_name
("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt"
); } while (0)
;
6781 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy)", 1, -1), "foo (14th copy)")do { eel_before_check ("get_duplicate_name (\"foo (13th copy)\", 1, -1)"
, "caja-file-operations.c", 6781); eel_check_string_result (get_duplicate_name
("foo (13th copy)", 1, -1), "foo (14th copy)"); } while (0)
;
6782 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy).txt", 1, -1), "foo (14th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (13th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6782); eel_check_string_result (get_duplicate_name
("foo (13th copy).txt", 1, -1), "foo (14th copy).txt"); } while
(0)
;
6783 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy)", 1, -1), "foo (22nd copy)")do { eel_before_check ("get_duplicate_name (\"foo (21st copy)\", 1, -1)"
, "caja-file-operations.c", 6783); eel_check_string_result (get_duplicate_name
("foo (21st copy)", 1, -1), "foo (22nd copy)"); } while (0)
;
6784 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (21st copy).txt\", 1, -1)"
, "caja-file-operations.c", 6784); eel_check_string_result (get_duplicate_name
("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt"); } while
(0)
;
6785 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy)", 1, -1), "foo (23rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy)\", 1, -1)"
, "caja-file-operations.c", 6785); eel_check_string_result (get_duplicate_name
("foo (22nd copy)", 1, -1), "foo (23rd copy)"); } while (0)
;
6786 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (22nd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6786); eel_check_string_result (get_duplicate_name
("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt"); } while
(0)
;
6787 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy)", 1, -1), "foo (24th copy)")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy)\", 1, -1)"
, "caja-file-operations.c", 6787); eel_check_string_result (get_duplicate_name
("foo (23rd copy)", 1, -1), "foo (24th copy)"); } while (0)
;
6788 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (23rd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6788); eel_check_string_result (get_duplicate_name
("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt"); } while
(0)
;
6789 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy)", 1, -1), "foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo (24th copy)\", 1, -1)"
, "caja-file-operations.c", 6789); eel_check_string_result (get_duplicate_name
("foo (24th copy)", 1, -1), "foo (25th copy)"); } while (0)
;
6790 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy).txt", 1, -1), "foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (24th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6790); eel_check_string_result (get_duplicate_name
("foo (24th copy).txt", 1, -1), "foo (25th copy).txt"); } while
(0)
;
6791 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy)", 1, -1), "foo foo (25th copy)")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy)\", 1, -1)"
, "caja-file-operations.c", 6791); eel_check_string_result (get_duplicate_name
("foo foo (24th copy)", 1, -1), "foo foo (25th copy)"); } while
(0)
;
6792 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (24th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6792); eel_check_string_result (get_duplicate_name
("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt"
); } while (0)
;
6793 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt")do { eel_before_check ("get_duplicate_name (\"foo foo (100000000000000th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6793); eel_check_string_result (get_duplicate_name
("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt"
); } while (0)
;
6794 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy)", 1, -1), "foo (11th copy)")do { eel_before_check ("get_duplicate_name (\"foo (10th copy)\", 1, -1)"
, "caja-file-operations.c", 6794); eel_check_string_result (get_duplicate_name
("foo (10th copy)", 1, -1), "foo (11th copy)"); } while (0)
;
6795 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy).txt", 1, -1), "foo (11th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (10th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6795); eel_check_string_result (get_duplicate_name
("foo (10th copy).txt", 1, -1), "foo (11th copy).txt"); } while
(0)
;
6796 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy)", 1, -1), "foo (12th copy)")do { eel_before_check ("get_duplicate_name (\"foo (11th copy)\", 1, -1)"
, "caja-file-operations.c", 6796); eel_check_string_result (get_duplicate_name
("foo (11th copy)", 1, -1), "foo (12th copy)"); } while (0)
;
6797 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy).txt", 1, -1), "foo (12th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (11th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6797); eel_check_string_result (get_duplicate_name
("foo (11th copy).txt", 1, -1), "foo (12th copy).txt"); } while
(0)
;
6798 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy)", 1, -1), "foo (13th copy)")do { eel_before_check ("get_duplicate_name (\"foo (12th copy)\", 1, -1)"
, "caja-file-operations.c", 6798); eel_check_string_result (get_duplicate_name
("foo (12th copy)", 1, -1), "foo (13th copy)"); } while (0)
;
6799 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy).txt", 1, -1), "foo (13th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (12th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6799); eel_check_string_result (get_duplicate_name
("foo (12th copy).txt", 1, -1), "foo (13th copy).txt"); } while
(0)
;
6800 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy)", 1, -1), "foo (111th copy)")do { eel_before_check ("get_duplicate_name (\"foo (110th copy)\", 1, -1)"
, "caja-file-operations.c", 6800); eel_check_string_result (get_duplicate_name
("foo (110th copy)", 1, -1), "foo (111th copy)"); } while (0
)
;
6801 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy).txt", 1, -1), "foo (111th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (110th copy).txt\", 1, -1)"
, "caja-file-operations.c", 6801); eel_check_string_result (get_duplicate_name
("foo (110th copy).txt", 1, -1), "foo (111th copy).txt"); } while
(0)
;
6802 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy)", 1, -1), "foo (123rd copy)")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy)\", 1, -1)"
, "caja-file-operations.c", 6802); eel_check_string_result (get_duplicate_name
("foo (122nd copy)", 1, -1), "foo (123rd copy)"); } while (0
)
;
6803 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (122nd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6803); eel_check_string_result (get_duplicate_name
("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt"); } while
(0)
;
6804 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy)", 1, -1), "foo (124th copy)")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy)\", 1, -1)"
, "caja-file-operations.c", 6804); eel_check_string_result (get_duplicate_name
("foo (123rd copy)", 1, -1), "foo (124th copy)"); } while (0
)
;
6805 EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt")do { eel_before_check ("get_duplicate_name (\"foo (123rd copy).txt\", 1, -1)"
, "caja-file-operations.c", 6805); eel_check_string_result (get_duplicate_name
("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt"); } while
(0)
;
6806
6807 setlocale (LC_MESSAGES5, "");
6808}
6809
6810#endif
diff --git a/2024-07-29-023715-6438-1/report-d4a7f3.html b/2024-07-29-023715-6438-1/report-d4a7f3.html new file mode 100644 index 000000000..235354a68 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-d4a7f3.html @@ -0,0 +1,3086 @@ + + + +eel-labeled-image.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-labeled-image.c
Warning:line 1105, column 13
Value stored to 'x_alignment' 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 eel-labeled-image.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-labeled-image.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* eel-labeled-image.c - A labeled image.
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Ramiro Estrugo <ramiro@eazel.com>
23*/
24
25#include <config.h>
26#include "eel-labeled-image.h"
27
28#include "eel-art-extensions.h"
29#include "eel-art-gtk-extensions.h"
30#include "eel-gtk-container.h"
31#include "eel-gtk-extensions.h"
32#include "eel-accessibility.h"
33#include <gtk/gtk.h>
34#include <gtk/gtk-a11y.h>
35#include <gdk/gdkkeysyms.h>
36#include <atk/atkimage.h>
37
38#define DEFAULT_SPACING0 0
39#define DEFAULT_X_PADDING0 0
40#define DEFAULT_Y_PADDING0 0
41#define DEFAULT_X_ALIGNMENT0.5 0.5
42#define DEFAULT_Y_ALIGNMENT0.5 0.5
43
44/* Signals */
45enum
46{
47 ACTIVATE,
48 LAST_SIGNAL
49};
50
51/* Arguments */
52enum
53{
54 PROP_0,
55 PROP_FILL,
56 PROP_LABEL,
57 PROP_LABEL_POSITION,
58 PROP_PIXBUF,
59 PROP_SHOW_IMAGE,
60 PROP_SHOW_LABEL,
61 PROP_SPACING,
62 PROP_X_ALIGNMENT,
63 PROP_X_PADDING,
64 PROP_Y_ALIGNMENT,
65 PROP_Y_PADDING
66};
67
68/* Detail member struct */
69struct EelLabeledImagePrivate
70{
71 GtkWidget *image;
72 GtkWidget *label;
73 GtkPositionType label_position;
74 gboolean show_label;
75 gboolean show_image;
76 guint spacing;
77 float x_alignment;
78 float y_alignment;
79 int x_padding;
80 int y_padding;
81 int fixed_image_height;
82 gboolean fill;
83};
84
85/* derived types so we can add our accessibility interfaces */
86static GType eel_labeled_image_button_get_type (void);
87static GType eel_labeled_image_check_button_get_type (void);
88static GType eel_labeled_image_radio_button_get_type (void);
89static GType eel_labeled_image_toggle_button_get_type (void);
90
91/* GtkWidgetClass methods */
92static GType eel_labeled_image_accessible_get_type (void);
93
94/* Private EelLabeledImage methods */
95static EelDimensions labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image);
96static EelDimensions labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image);
97static void labeled_image_ensure_label (EelLabeledImage *labeled_image);
98static void labeled_image_ensure_image (EelLabeledImage *labeled_image);
99static EelIRect labeled_image_get_content_bounds (const EelLabeledImage *labeled_image);
100static EelDimensions labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image);
101static void labeled_image_update_alignments (EelLabeledImage *labeled_image);
102static gboolean labeled_image_show_label (const EelLabeledImage *labeled_image);
103static gboolean labeled_image_show_image (const EelLabeledImage *labeled_image);
104
105static guint labeled_image_signals[LAST_SIGNAL] = { 0 };
106
107G_DEFINE_TYPE_WITH_PRIVATE (EelLabeledImage, eel_labeled_image, GTK_TYPE_CONTAINER)static void eel_labeled_image_init (EelLabeledImage *self); static
void eel_labeled_image_class_init (EelLabeledImageClass *klass
); static GType eel_labeled_image_get_type_once (void); static
gpointer eel_labeled_image_parent_class = ((void*)0); static
gint EelLabeledImage_private_offset; static void eel_labeled_image_class_intern_init
(gpointer klass) { eel_labeled_image_parent_class = g_type_class_peek_parent
(klass); if (EelLabeledImage_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelLabeledImage_private_offset); eel_labeled_image_class_init
((EelLabeledImageClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_labeled_image_get_instance_private
(EelLabeledImage *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EelLabeledImage_private_offset)))); } GType eel_labeled_image_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType eel_labeled_image_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_get_type ()), g_intern_static_string ("EelLabeledImage"
), sizeof (EelLabeledImageClass), (GClassInitFunc)(void (*)(void
)) eel_labeled_image_class_intern_init, sizeof (EelLabeledImage
), (GInstanceInitFunc)(void (*)(void)) eel_labeled_image_init
, (GTypeFlags) 0); { {{ EelLabeledImage_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (EelLabeledImagePrivate)); };} } return
g_define_type_id; }
108
109static void
110eel_labeled_image_init (EelLabeledImage *labeled_image)
111{
112 gtk_widget_set_has_window (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), FALSE(0));
113
114 labeled_image->details = eel_labeled_image_get_instance_private (labeled_image);
115 labeled_image->details->show_label = TRUE(!(0));
116 labeled_image->details->show_image = TRUE(!(0));
117 labeled_image->details->label_position = GTK_POS_BOTTOM;
118 labeled_image->details->spacing = DEFAULT_SPACING0;
119 labeled_image->details->x_padding = DEFAULT_X_PADDING0;
120 labeled_image->details->y_padding = DEFAULT_Y_PADDING0;
121 labeled_image->details->x_alignment = DEFAULT_X_ALIGNMENT0.5;
122 labeled_image->details->y_alignment = DEFAULT_Y_ALIGNMENT0.5;
123 labeled_image->details->fixed_image_height = 0;
124
125 eel_labeled_image_set_fill (labeled_image, FALSE(0));
126}
127
128static void
129eel_labeled_image_destroy (GtkWidget *object)
130{
131 EelLabeledImage *labeled_image;
132
133 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
134
135 if (labeled_image->details->image != NULL((void*)0))
136 {
137 gtk_widget_destroy (labeled_image->details->image);
138 }
139
140 if (labeled_image->details->label != NULL((void*)0))
141 {
142 gtk_widget_destroy (labeled_image->details->label);
143 }
144
145 GTK_WIDGET_CLASS (eel_labeled_image_parent_class)((((GtkWidgetClass*) (void *) ((eel_labeled_image_parent_class
)))))
->destroy (object);
146}
147
148/* GObjectClass methods */
149static void
150eel_labeled_image_set_property (GObject *object,
151 guint property_id,
152 const GValue *value,
153 GParamSpec *pspec)
154{
155 EelLabeledImage *labeled_image;
156
157 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_199
= 1; else _g_boolean_var_199 = 0; _g_boolean_var_199; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 157, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
158
159 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
160
161 switch (property_id)
162 {
163 case PROP_PIXBUF:
164 eel_labeled_image_set_pixbuf (labeled_image,
165 g_value_get_object (value));
166 break;
167
168 case PROP_LABEL:
169 eel_labeled_image_set_text (labeled_image, g_value_get_string (value));
170 break;
171
172 case PROP_LABEL_POSITION:
173 eel_labeled_image_set_label_position (labeled_image,
174 g_value_get_enum (value));
175 break;
176
177 case PROP_SHOW_LABEL:
178 eel_labeled_image_set_show_label (labeled_image,
179 g_value_get_boolean (value));
180 break;
181
182 case PROP_SHOW_IMAGE:
183 eel_labeled_image_set_show_image (labeled_image,
184 g_value_get_boolean (value));
185 break;
186
187 case PROP_SPACING:
188 eel_labeled_image_set_spacing (labeled_image,
189 g_value_get_uint (value));
190 break;
191
192 case PROP_X_PADDING:
193 eel_labeled_image_set_x_padding (labeled_image,
194 g_value_get_int (value));
195 break;
196
197 case PROP_Y_PADDING:
198 eel_labeled_image_set_y_padding (labeled_image,
199 g_value_get_int (value));
200 break;
201
202 case PROP_X_ALIGNMENT:
203 eel_labeled_image_set_x_alignment (labeled_image,
204 g_value_get_float (value));
205 break;
206
207 case PROP_Y_ALIGNMENT:
208 eel_labeled_image_set_y_alignment (labeled_image,
209 g_value_get_float (value));
210 break;
211
212 case PROP_FILL:
213 eel_labeled_image_set_fill (labeled_image,
214 g_value_get_boolean (value));
215 break;
216 default:
217 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 217
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
218 }
219}
220
221static void
222eel_labeled_image_get_property (GObject *object,
223 guint property_id,
224 GValue *value,
225 GParamSpec *pspec)
226{
227 EelLabeledImage *labeled_image;
228
229 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_200
= 1; else _g_boolean_var_200 = 0; _g_boolean_var_200; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 229, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
230
231 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
232
233 switch (property_id)
234 {
235 case PROP_LABEL:
236 if (labeled_image->details->label == NULL((void*)0))
237 {
238 g_value_set_string (value, NULL((void*)0));
239 }
240 else
241 {
242 g_value_set_string (value,
243 gtk_label_get_text (GTK_LABEL (((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
244 labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
));
245 }
246 break;
247
248 case PROP_LABEL_POSITION:
249 g_value_set_enum (value, eel_labeled_image_get_label_position (labeled_image));
250 break;
251
252 case PROP_SHOW_LABEL:
253 g_value_set_boolean (value, eel_labeled_image_get_show_label (labeled_image));
254 break;
255
256 case PROP_SHOW_IMAGE:
257 g_value_set_boolean (value, eel_labeled_image_get_show_image (labeled_image));
258 break;
259
260 case PROP_SPACING:
261 g_value_set_uint (value, eel_labeled_image_get_spacing (labeled_image));
262 break;
263
264 case PROP_X_PADDING:
265 g_value_set_int (value, eel_labeled_image_get_x_padding (labeled_image));
266 break;
267
268 case PROP_Y_PADDING:
269 g_value_set_int (value, eel_labeled_image_get_y_padding (labeled_image));
270 break;
271
272 case PROP_X_ALIGNMENT:
273 g_value_set_float (value, eel_labeled_image_get_x_alignment (labeled_image));
274 break;
275
276 case PROP_Y_ALIGNMENT:
277 g_value_set_float (value, eel_labeled_image_get_y_alignment (labeled_image));
278 break;
279
280 case PROP_FILL:
281 g_value_set_boolean (value, eel_labeled_image_get_fill (labeled_image));
282 break;
283
284 default:
285 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 285
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
286 }
287}
288
289/* GtkWidgetClass methods */
290static void
291eel_labeled_image_size_request (GtkWidget *widget,
292 GtkRequisition *requisition)
293{
294 EelLabeledImage *labeled_image;
295 EelDimensions content_dimensions;
296
297 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 297, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
298 g_assert (requisition != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (requisition != ((void*)0)) _g_boolean_var_202 = 1; else
_g_boolean_var_202 = 0; _g_boolean_var_202; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 298, ((const char*) (__func__
)), "requisition != NULL"); } while (0)
;
299
300 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
301
302 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
303
304 requisition->width =
305 MAX (1, content_dimensions.width)(((1) > (content_dimensions.width)) ? (1) : (content_dimensions
.width))
+
306 2 * labeled_image->details->x_padding;
307
308 requisition->height =
309 MAX (1, content_dimensions.height)(((1) > (content_dimensions.height)) ? (1) : (content_dimensions
.height))
+
310 2 * labeled_image->details->y_padding;
311}
312
313static void
314eel_labeled_image_get_preferred_width (GtkWidget *widget,
315 gint *minimum_width,
316 gint *natural_width)
317{
318 GtkRequisition req;
319 eel_labeled_image_size_request (widget, &req);
320 *minimum_width = *natural_width = req.width;
321}
322
323static void
324eel_labeled_image_get_preferred_height (GtkWidget *widget,
325 gint *minimum_height,
326 gint *natural_height)
327{
328 GtkRequisition req;
329 eel_labeled_image_size_request (widget, &req);
330 *minimum_height = *natural_height = req.height;
331}
332
333static void
334eel_labeled_image_size_allocate (GtkWidget *widget,
335 GtkAllocation *allocation)
336{
337 EelLabeledImage *labeled_image;
338 EelIRect image_bounds;
339 EelIRect label_bounds;
340
341 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 341, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
342 g_assert (allocation != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if (allocation != ((void*)0)) _g_boolean_var_204 = 1; else _g_boolean_var_204
= 0; _g_boolean_var_204; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 342, ((const char*) (__func__
)), "allocation != NULL"); } while (0)
;
343
344 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
345
346 gtk_widget_set_allocation (widget, allocation);
347
348 label_bounds = eel_labeled_image_get_label_bounds (labeled_image);
349 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
350 labeled_image->details->label,
351 label_bounds);
352
353 image_bounds = eel_labeled_image_get_image_bounds (labeled_image);
354 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
355 labeled_image->details->image,
356 image_bounds);
357}
358
359static int
360eel_labeled_image_draw (GtkWidget *widget,
361 cairo_t *cr)
362{
363 EelLabeledImage *labeled_image;
364 EelIRect label_bounds;
365 GtkStyleContext *context;
366
367 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 367, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
368 g_assert (gtk_widget_get_realized (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (gtk_widget_get_realized (widget)) _g_boolean_var_206 = 1
; else _g_boolean_var_206 = 0; _g_boolean_var_206; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-labeled-image.c", 368,
((const char*) (__func__)), "gtk_widget_get_realized (widget)"
); } while (0)
;
369
370 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
371
372 context = gtk_widget_get_style_context (widget);
373 gtk_style_context_save (context);
374
375 if (gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_SELECTED ||
376 gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_ACTIVE)
377 {
378 label_bounds = eel_labeled_image_get_label_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
379
380 gtk_widget_get_state_flags (widget);
381 gtk_render_background (context,
382 cr,
383 label_bounds.x0, label_bounds.y0,
384 label_bounds.x1 - label_bounds.x0,
385 label_bounds.y1 - label_bounds.y0);
386
387 gtk_render_frame (context,
388 cr,
389 label_bounds.x0, label_bounds.y0,
390 label_bounds.x1 - label_bounds.x0,
391 label_bounds.y1 - label_bounds.y0);
392 }
393
394 if (labeled_image_show_label (labeled_image))
395 {
396 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
397 labeled_image->details->label,
398 cr);
399 }
400
401 if (labeled_image_show_image (labeled_image))
402 {
403 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
404 labeled_image->details->image,
405 cr);
406 }
407
408 if (gtk_widget_has_focus (widget))
409 {
410 label_bounds = eel_labeled_image_get_image_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
411 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_NORMAL, TRUE(!(0)));
412 gtk_render_focus (context,
413 cr,
414 label_bounds.x0, label_bounds.y0,
415 label_bounds.x1 - label_bounds.x0,
416 label_bounds.y1 - label_bounds.y0);
417 }
418
419 gtk_style_context_restore (context);
420
421 return FALSE(0);
422}
423
424static void
425eel_labeled_image_map (GtkWidget *widget)
426{
427 EelLabeledImage *labeled_image;
428
429 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 429, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
430
431 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
432
433 gtk_widget_set_mapped (widget, TRUE(!(0)));
434
435 if (labeled_image_show_label (labeled_image))
436 {
437 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
438 }
439
440 if (labeled_image_show_image (labeled_image))
441 {
442 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
443 }
444}
445
446static void
447eel_labeled_image_unmap (GtkWidget *widget)
448{
449 EelLabeledImage *labeled_image;
450
451 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_208
= 1; else _g_boolean_var_208 = 0; _g_boolean_var_208; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 451, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
452
453 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
454
455 gtk_widget_set_mapped (widget, FALSE(0));
456
457 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
458 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
459}
460
461/* GtkContainerClass methods */
462static void
463eel_labeled_image_add (GtkContainer *container,
464 GtkWidget *child)
465{
466 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 466, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
467
468 eel_gtk_container_child_add (container, child);
469}
470
471static void
472eel_labeled_image_remove (GtkContainer *container,
473 GtkWidget *child)
474{
475 EelLabeledImage *labeled_image;
476
477 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_210
= 1; else _g_boolean_var_210 = 0; _g_boolean_var_210; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 477, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
478
479 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));;
480
481 g_assert (child == labeled_image->details->image || child == labeled_image->details->label)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (child == labeled_image->details->image || child ==
labeled_image->details->label) _g_boolean_var_211 = 1;
else _g_boolean_var_211 = 0; _g_boolean_var_211; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-labeled-image.c", 481,
((const char*) (__func__)), "child == labeled_image->details->image || child == labeled_image->details->label"
); } while (0)
;
482
483 eel_gtk_container_child_remove (container, child);
484
485 if (labeled_image->details->image == child)
486 {
487 labeled_image->details->image = NULL((void*)0);
488 }
489
490 if (labeled_image->details->label == child)
491 {
492 labeled_image->details->label = NULL((void*)0);
493 }
494}
495
496static void
497eel_labeled_image_forall (GtkContainer *container,
498 gboolean include_internals,
499 GtkCallback callback,
500 gpointer callback_data)
501{
502 EelLabeledImage *labeled_image;
503
504 g_assert (EEL_IS_LABELED_IMAGE (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (eel_labeled_image_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_212 = 1; else _g_boolean_var_212 = 0; _g_boolean_var_212
; }), 1)) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 504, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (container)"
); } while (0)
;
505 g_assert (callback != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if (callback != ((void*)0)) _g_boolean_var_213 = 1; else _g_boolean_var_213
= 0; _g_boolean_var_213; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 505, ((const char*) (__func__
)), "callback != NULL"); } while (0)
;
506
507 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));
508
509 if (include_internals)
510 {
511 if (labeled_image->details->image != NULL((void*)0))
512 {
513 (* callback) (labeled_image->details->image, callback_data);
514 }
515
516 if (labeled_image->details->label != NULL((void*)0))
517 {
518 (* callback) (labeled_image->details->label, callback_data);
519 }
520 }
521}
522
523/* Class init methods */
524static void
525eel_labeled_image_class_init (EelLabeledImageClass *labeled_image_class)
526{
527 GObjectClass *gobject_class = G_OBJECT_CLASS (labeled_image_class)((((GObjectClass*) (void *) ((labeled_image_class)))));
528 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (labeled_image_class)((((GtkWidgetClass*) (void *) ((labeled_image_class)))));
529 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (labeled_image_class)((((GtkContainerClass*) (void *) ((labeled_image_class)))));
530 GtkBindingSet *binding_set;
531
532 /* GObjectClass */
533 gobject_class->set_property = eel_labeled_image_set_property;
534 gobject_class->get_property = eel_labeled_image_get_property;
535
536 widget_class->destroy = eel_labeled_image_destroy;
537
538
539 /* GtkWidgetClass */
540 widget_class->size_allocate = eel_labeled_image_size_allocate;
541 widget_class->get_preferred_width = eel_labeled_image_get_preferred_width;
542 widget_class->get_preferred_height = eel_labeled_image_get_preferred_height;
543 widget_class->draw = eel_labeled_image_draw;
544
545 widget_class->map = eel_labeled_image_map;
546 widget_class->unmap = eel_labeled_image_unmap;
547
548 gtk_widget_class_set_accessible_type (widget_class, eel_labeled_image_accessible_get_type ());
549
550
551 /* GtkContainerClass */
552 container_class->add = eel_labeled_image_add;
553 container_class->remove = eel_labeled_image_remove;
554 container_class->forall = eel_labeled_image_forall;
555
556 labeled_image_signals[ACTIVATE] =
557 g_signal_new ("activate",
558 G_TYPE_FROM_CLASS (labeled_image_class)(((GTypeClass*) (labeled_image_class))->g_type),
559 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
560 G_STRUCT_OFFSET (EelLabeledImageClass,((glong) __builtin_offsetof(EelLabeledImageClass, activate))
561 activate)((glong) __builtin_offsetof(EelLabeledImageClass, activate)),
562 NULL((void*)0), NULL((void*)0),
563 g_cclosure_marshal_VOID__VOID,
564 G_TYPE_NONE((GType) ((1) << (2))), 0);
565 widget_class->activate_signal = labeled_image_signals[ACTIVATE];
566
567 binding_set = gtk_binding_set_by_class (gobject_class);
568
569 gtk_binding_entry_add_signal (binding_set,
570 GDK_KEY_Return0xff0d, 0,
571 "activate", 0);
572 gtk_binding_entry_add_signal (binding_set,
573 GDK_KEY_KP_Enter0xff8d, 0,
574 "activate", 0);
575 gtk_binding_entry_add_signal (binding_set,
576 GDK_KEY_space0x020, 0,
577 "activate", 0);
578
579
580 /* Properties */
581 g_object_class_install_property (
582 gobject_class,
583 PROP_PIXBUF,
584 g_param_spec_object ("pixbuf", NULL((void*)0), NULL((void*)0),
585 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ()), G_PARAM_READWRITE));
586
587 g_object_class_install_property (
588 gobject_class,
589 PROP_LABEL,
590 g_param_spec_string ("label", NULL((void*)0), NULL((void*)0),
591 "", G_PARAM_READWRITE));
592
593
594 g_object_class_install_property (
595 gobject_class,
596 PROP_LABEL_POSITION,
597 g_param_spec_enum ("label_position", NULL((void*)0), NULL((void*)0),
598 GTK_TYPE_POSITION_TYPE(gtk_position_type_get_type ()),
599 GTK_POS_BOTTOM,
600 G_PARAM_READWRITE));
601
602 g_object_class_install_property (
603 gobject_class,
604 PROP_SHOW_LABEL,
605 g_param_spec_boolean ("show_label", NULL((void*)0), NULL((void*)0),
606 TRUE(!(0)), G_PARAM_READWRITE));
607
608 g_object_class_install_property (
609 gobject_class,
610 PROP_SHOW_IMAGE,
611 g_param_spec_boolean ("show_image", NULL((void*)0), NULL((void*)0),
612 TRUE(!(0)), G_PARAM_READWRITE));
613
614
615 g_object_class_install_property (
616 gobject_class,
617 PROP_SPACING,
618 g_param_spec_uint ("spacing", NULL((void*)0), NULL((void*)0),
619 0,
620 G_MAXINT2147483647,
621 DEFAULT_SPACING0,
622 G_PARAM_READWRITE));
623
624 g_object_class_install_property (
625 gobject_class,
626 PROP_X_PADDING,
627 g_param_spec_int ("x_padding", NULL((void*)0), NULL((void*)0),
628 0,
629 G_MAXINT2147483647,
630 DEFAULT_X_PADDING0,
631 G_PARAM_READWRITE));
632
633 g_object_class_install_property (
634 gobject_class,
635 PROP_Y_PADDING,
636 g_param_spec_int ("y_padding", NULL((void*)0), NULL((void*)0),
637 0,
638 G_MAXINT2147483647,
639 DEFAULT_Y_PADDING0,
640 G_PARAM_READWRITE));
641
642 g_object_class_install_property (
643 gobject_class,
644 PROP_X_ALIGNMENT,
645 g_param_spec_float ("x_alignment", NULL((void*)0), NULL((void*)0),
646 0.0,
647 1.0,
648 DEFAULT_X_ALIGNMENT0.5,
649 G_PARAM_READWRITE));
650
651 g_object_class_install_property (
652 gobject_class,
653 PROP_Y_ALIGNMENT,
654 g_param_spec_float ("y_alignment", NULL((void*)0), NULL((void*)0),
655 0.0,
656 1.0,
657 DEFAULT_Y_ALIGNMENT0.5,
658 G_PARAM_READWRITE));
659
660 g_object_class_install_property (
661 gobject_class,
662 PROP_FILL,
663 g_param_spec_boolean ("fill", NULL((void*)0), NULL((void*)0),
664 FALSE(0),
665 G_PARAM_READWRITE));
666
667}
668
669/* Private EelLabeledImage methods */
670static gboolean
671is_fixed_height (const EelLabeledImage *labeled_image)
672{
673 return labeled_image->details->fixed_image_height > 0;
674}
675
676static EelDimensions
677labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image)
678{
679 EelDimensions image_dimensions;
680 GtkRequisition image_requisition;
681
682 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_214 = 1; else _g_boolean_var_214 =
0; _g_boolean_var_214; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 682, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
683
684 if (!labeled_image_show_image (labeled_image))
685 {
686 return eel_dimensions_empty;
687 }
688
689 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
690
691 image_dimensions.width = (int) image_requisition.width;
692 image_dimensions.height = (int) image_requisition.height;
693
694 if (is_fixed_height (labeled_image))
695 {
696 image_dimensions.height = labeled_image->details->fixed_image_height;
697 }
698
699 return image_dimensions;
700}
701
702static EelDimensions
703labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image)
704{
705 EelDimensions label_dimensions;
706 GtkRequisition label_requisition;
707
708 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 708, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
709
710 if (!labeled_image_show_label (labeled_image))
711 {
712 return eel_dimensions_empty;
713 }
714
715 gtk_widget_get_preferred_size (labeled_image->details->label, &label_requisition, NULL((void*)0));
716
717 label_dimensions.width = (int) label_requisition.width;
718 label_dimensions.height = (int) label_requisition.height;
719
720 return label_dimensions;
721}
722
723static EelIRect
724labeled_image_get_image_bounds_fill (const EelLabeledImage *labeled_image)
725{
726 EelIRect image_bounds;
727 EelDimensions image_dimensions;
728 EelIRect content_bounds;
729 EelIRect bounds;
730
731 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_216 = 1; else _g_boolean_var_216 =
0; _g_boolean_var_216; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 731, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
732
733 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
734
735 if (eel_dimensions_are_empty (image_dimensions))
736 {
737 return eel_irect_empty;
738 }
739
740 content_bounds = labeled_image_get_content_bounds (labeled_image);
741 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
742
743 if (!labeled_image_show_label (labeled_image))
744 {
745 image_bounds = bounds;
746 }
747 else
748 {
749 switch (labeled_image->details->label_position)
750 {
751 case GTK_POS_LEFT:
752 image_bounds.y0 = bounds.y0;
753 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
754 image_bounds.y1 = bounds.y1;
755 image_bounds.x1 = bounds.x1;
756 break;
757
758 case GTK_POS_RIGHT:
759 image_bounds.y0 = bounds.y0;
760 image_bounds.x0 = bounds.x0;
761 image_bounds.y1 = bounds.y1;
762 image_bounds.x1 = content_bounds.x0 + image_dimensions.width;
763 break;
764
765 case GTK_POS_TOP:
766 image_bounds.x0 = bounds.x0;
767 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
768 image_bounds.x1 = bounds.x1;
769 image_bounds.y1 = bounds.y1;
770 break;
771
772 case GTK_POS_BOTTOM:
773 image_bounds.x0 = bounds.x0;
774 image_bounds.y0 = bounds.y0;
775 image_bounds.x1 = bounds.x1;
776 image_bounds.y1 = content_bounds.y0 + image_dimensions.height;
777 break;
778
779 default:
780 image_bounds.x0 = 0;
781 image_bounds.y0 = 0;
782 image_bounds.x1 = 0;
783 image_bounds.y1 = 0;
784 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 784
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
785 }
786 }
787
788 return image_bounds;
789}
790
791EelIRect
792eel_labeled_image_get_image_bounds (const EelLabeledImage *labeled_image)
793{
794 EelDimensions image_dimensions;
795 EelDimensions label_dimensions;
796 GtkRequisition image_requisition;
797 EelIRect image_bounds;
798 EelIRect content_bounds;
799
800 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_217 = 1; else _g_boolean_var_217 =
0; _g_boolean_var_217; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
801
802 if (labeled_image->details->fill)
803 {
804 return labeled_image_get_image_bounds_fill (labeled_image);
805 }
806
807 /* get true real dimensions if we're in fixed height mode */
808 if (is_fixed_height (labeled_image) && labeled_image_show_image (labeled_image))
809 {
810 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
811 image_dimensions.width = (int) image_requisition.width;
812 image_dimensions.height = (int) image_requisition.height;
813 }
814 else
815 {
816 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
817 }
818
819 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
820
821 if (eel_dimensions_are_empty (image_dimensions))
822 {
823 return eel_irect_empty;
824 }
825
826 content_bounds = labeled_image_get_content_bounds (labeled_image);
827
828 if (!labeled_image_show_label (labeled_image))
829 {
830 image_bounds.x0 =
831 content_bounds.x0 +
832 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
833 image_bounds.y0 =
834 content_bounds.y0 +
835 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
836 }
837 else
838 {
839 switch (labeled_image->details->label_position)
840 {
841 case GTK_POS_LEFT:
842 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
843 image_bounds.y0 =
844 content_bounds.y0 +
845 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
846 break;
847
848 case GTK_POS_RIGHT:
849 image_bounds.x0 = content_bounds.x0;
850 image_bounds.y0 =
851 content_bounds.y0 +
852 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
853 break;
854
855 case GTK_POS_TOP:
856 image_bounds.x0 =
857 content_bounds.x0 +
858 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
859 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
860 break;
861
862 case GTK_POS_BOTTOM:
863 image_bounds.x0 =
864 content_bounds.x0 +
865 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
866
867 if (is_fixed_height (labeled_image))
868 {
869 image_bounds.y0 = content_bounds.y0 + eel_irect_get_height (content_bounds)
870 - image_dimensions.height
871 - label_dimensions.height
872 - labeled_image->details->spacing;
873 }
874 else
875 {
876 image_bounds.y0 = content_bounds.y0;
877 }
878
879 break;
880
881 default:
882 image_bounds.x0 = 0;
883 image_bounds.y0 = 0;
884 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 884
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
885 }
886 }
887
888 image_bounds.x1 = image_bounds.x0 + image_dimensions.width;
889 image_bounds.y1 = image_bounds.y0 + image_dimensions.height;
890
891 return image_bounds;
892}
893
894static EelIRect
895labeled_image_get_label_bounds_fill (const EelLabeledImage *labeled_image)
896{
897 EelIRect label_bounds;
898 EelDimensions label_dimensions;
899 EelIRect content_bounds;
900 EelIRect bounds;
901
902 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_218
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_218 = 1; else _g_boolean_var_218 =
0; _g_boolean_var_218; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 902, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
903
904 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
905
906 if (eel_dimensions_are_empty (label_dimensions))
907 {
908 return eel_irect_empty;
909 }
910
911 content_bounds = labeled_image_get_content_bounds (labeled_image);
912 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
913
914 /* Only the label is shown */
915 if (!labeled_image_show_image (labeled_image))
916 {
917 label_bounds = bounds;
918 /* Both label and image are shown */
919 }
920 else
921 {
922 switch (labeled_image->details->label_position)
923 {
924 case GTK_POS_LEFT:
925 label_bounds.y0 = bounds.y0;
926 label_bounds.x0 = bounds.x0;
927 label_bounds.y1 = bounds.y1;
928 label_bounds.x1 = content_bounds.x0 + label_dimensions.width;
929 break;
930
931 case GTK_POS_RIGHT:
932 label_bounds.y0 = bounds.y0;
933 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
934 label_bounds.y1 = bounds.y1;
935 label_bounds.x1 = bounds.x1;
936 break;
937
938 case GTK_POS_TOP:
939 label_bounds.x0 = bounds.x0;
940 label_bounds.y0 = bounds.y0;
941 label_bounds.x1 = bounds.x1;
942 label_bounds.y1 = content_bounds.y0 + label_dimensions.height;
943 break;
944
945 case GTK_POS_BOTTOM:
946 label_bounds.x0 = bounds.x0;
947 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
948 label_bounds.x1 = bounds.x1;
949 label_bounds.y1 = bounds.y1;
950 break;
951
952 default:
953 label_bounds.x0 = 0;
954 label_bounds.y0 = 0;
955 label_bounds.x1 = 0;
956 label_bounds.y1 = 0;
957 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 957
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
958 }
959 }
960
961 return label_bounds;
962}
963
964EelIRect
965eel_labeled_image_get_label_bounds (const EelLabeledImage *labeled_image)
966{
967 EelIRect label_bounds;
968 EelDimensions label_dimensions;
969 EelIRect content_bounds;
970
971 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_219
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_219 = 1; else _g_boolean_var_219 =
0; _g_boolean_var_219; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
972
973 if (labeled_image->details->fill)
974 {
975 return labeled_image_get_label_bounds_fill (labeled_image);
976 }
977
978 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
979
980 if (eel_dimensions_are_empty (label_dimensions))
981 {
982 return eel_irect_empty;
983 }
984
985 content_bounds = labeled_image_get_content_bounds (labeled_image);
986
987 /* Only the label is shown */
988 if (!labeled_image_show_image (labeled_image))
989 {
990 label_bounds.x0 =
991 content_bounds.x0 +
992 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
993 label_bounds.y0 =
994 content_bounds.y0 +
995 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
996 /* Both label and image are shown */
997 }
998 else
999 {
1000 switch (labeled_image->details->label_position)
1001 {
1002 case GTK_POS_LEFT:
1003 label_bounds.x0 = content_bounds.x0;
1004 label_bounds.y0 =
1005 content_bounds.y0 +
1006 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1007 break;
1008
1009 case GTK_POS_RIGHT:
1010 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
1011 label_bounds.y0 =
1012 content_bounds.y0 +
1013 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1014 break;
1015
1016 case GTK_POS_TOP:
1017 label_bounds.x0 =
1018 content_bounds.x0 +
1019 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1020 label_bounds.y0 = content_bounds.y0;
1021 break;
1022
1023 case GTK_POS_BOTTOM:
1024 label_bounds.x0 =
1025 content_bounds.x0 +
1026 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1027 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
1028 break;
1029
1030 default:
1031 label_bounds.x0 = 0;
1032 label_bounds.y0 = 0;
1033 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 1033
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1034 }
1035 }
1036
1037 label_bounds.x1 = label_bounds.x0 + label_dimensions.width;
1038 label_bounds.y1 = label_bounds.y0 + label_dimensions.height;
1039
1040 return label_bounds;
1041}
1042
1043static void
1044labeled_image_update_alignments (EelLabeledImage *labeled_image)
1045{
1046
1047 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_220
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_220 = 1; else _g_boolean_var_220 =
0; _g_boolean_var_220; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1047, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1048
1049 if (labeled_image->details->label != NULL((void*)0))
1050 {
1051 if (labeled_image->details->fill)
1052 {
1053 float x_alignment;
1054 float y_alignment;
1055
1056 x_alignment = gtk_label_get_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
1057 y_alignment = gtk_label_get_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
1058
1059 /* Only the label is shown */
1060 if (!labeled_image_show_image (labeled_image))
1061 {
1062 x_alignment = 0.5;
1063 y_alignment = 0.5;
1064 /* Both label and image are shown */
1065 }
1066 else
1067 {
1068 switch (labeled_image->details->label_position)
1069 {
1070 case GTK_POS_LEFT:
1071 x_alignment = 1.0;
1072 y_alignment = 0.5;
1073 break;
1074
1075 case GTK_POS_RIGHT:
1076 x_alignment = 0.0;
1077 y_alignment = 0.5;
1078 break;
1079
1080 case GTK_POS_TOP:
1081 x_alignment = 0.5;
1082 y_alignment = 1.0;
1083 break;
1084
1085 case GTK_POS_BOTTOM:
1086 x_alignment = 0.5;
1087 y_alignment = 0.0;
1088 break;
1089 }
1090
1091 }
1092
1093 gtk_label_set_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, x_alignment);
1094 gtk_label_set_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, y_alignment);
1095 }
1096 }
1097
1098 if (labeled_image->details->image != NULL((void*)0))
1099 {
1100 if (labeled_image->details->fill)
1101 {
1102 float x_alignment;
1103 float y_alignment;
1104
1105 x_alignment = gtk_widget_get_halign (labeled_image->details->image);
Value stored to 'x_alignment' is never read
1106 y_alignment = gtk_widget_get_valign (labeled_image->details->image);
1107
1108 /* Only the image is shown */
1109 if (!labeled_image_show_label (labeled_image))
1110 {
1111 x_alignment = 0.5;
1112 y_alignment = 0.5;
1113 /* Both label and image are shown */
1114 }
1115 else
1116 {
1117 switch (labeled_image->details->label_position)
1118 {
1119 case GTK_POS_LEFT:
1120 x_alignment = 0.0;
1121 y_alignment = 0.5;
1122 break;
1123
1124 case GTK_POS_RIGHT:
1125 x_alignment = 1.0;
1126 y_alignment = 0.5;
1127 break;
1128
1129 case GTK_POS_TOP:
1130 x_alignment = 0.5;
1131 y_alignment = 0.0;
1132 break;
1133
1134 case GTK_POS_BOTTOM:
1135 x_alignment = 0.5;
1136 y_alignment = 1.0;
1137 break;
1138 }
1139 }
1140
1141 gtk_widget_set_halign (labeled_image->details->image, x_alignment);
1142 gtk_widget_set_valign (labeled_image->details->image, y_alignment);
1143 }
1144 }
1145}
1146
1147static EelDimensions
1148labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image)
1149{
1150 EelDimensions image_dimensions;
1151 EelDimensions label_dimensions;
1152 EelDimensions content_dimensions;
1153
1154 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_221
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1154, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1155
1156 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
1157 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
1158
1159 content_dimensions = eel_dimensions_empty;
1160
1161 /* Both shown */
1162 if (!eel_dimensions_are_empty (image_dimensions) && !eel_dimensions_are_empty (label_dimensions))
1163 {
1164 content_dimensions.width =
1165 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1166 switch (labeled_image->details->label_position)
1167 {
1168 case GTK_POS_LEFT:
1169 case GTK_POS_RIGHT:
1170 content_dimensions.width =
1171 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1172 content_dimensions.height = MAX (image_dimensions.height, label_dimensions.height)(((image_dimensions.height) > (label_dimensions.height)) ?
(image_dimensions.height) : (label_dimensions.height))
;
1173 break;
1174
1175 case GTK_POS_TOP:
1176 case GTK_POS_BOTTOM:
1177 content_dimensions.width = MAX (image_dimensions.width, label_dimensions.width)(((image_dimensions.width) > (label_dimensions.width)) ? (
image_dimensions.width) : (label_dimensions.width))
;
1178 content_dimensions.height =
1179 image_dimensions.height + labeled_image->details->spacing + label_dimensions.height;
1180 break;
1181 }
1182 /* Only image shown */
1183 }
1184 else if (!eel_dimensions_are_empty (image_dimensions))
1185 {
1186 content_dimensions.width = image_dimensions.width;
1187 content_dimensions.height = image_dimensions.height;
1188 /* Only label shown */
1189 }
1190 else
1191 {
1192 content_dimensions.width = label_dimensions.width;
1193 content_dimensions.height = label_dimensions.height;
1194 }
1195
1196 return content_dimensions;
1197}
1198
1199static EelIRect
1200labeled_image_get_content_bounds (const EelLabeledImage *labeled_image)
1201{
1202 EelDimensions content_dimensions;
1203 EelIRect content_bounds;
1204 EelIRect bounds;
1205
1206 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_222 = 1; else _g_boolean_var_222 =
0; _g_boolean_var_222; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1206, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1207
1208 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1209
1210 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
1211 content_bounds = eel_irect_align (bounds,
1212 content_dimensions.width,
1213 content_dimensions.height,
1214 labeled_image->details->x_alignment,
1215 labeled_image->details->y_alignment);
1216
1217 return content_bounds;
1218}
1219
1220static void
1221labeled_image_ensure_label (EelLabeledImage *labeled_image)
1222{
1223 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_223
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_223 = 1; else _g_boolean_var_223 =
0; _g_boolean_var_223; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1223, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1224
1225 if (labeled_image->details->label != NULL((void*)0))
1226 {
1227 return;
1228 }
1229
1230 labeled_image->details->label = gtk_label_new (NULL((void*)0));
1231 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->label);
1232 gtk_widget_show (labeled_image->details->label);
1233}
1234
1235static void
1236labeled_image_ensure_image (EelLabeledImage *labeled_image)
1237{
1238 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_224
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_224 = 1; else _g_boolean_var_224 =
0; _g_boolean_var_224; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1238, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1239
1240 if (labeled_image->details->image != NULL((void*)0))
1241 {
1242 return;
1243 }
1244
1245 labeled_image->details->image = gtk_image_new ();
1246 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->image);
1247 gtk_widget_show (labeled_image->details->image);
1248}
1249
1250static gboolean
1251labeled_image_show_image (const EelLabeledImage *labeled_image)
1252{
1253 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_225
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_225 = 1; else _g_boolean_var_225 =
0; _g_boolean_var_225; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1253, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1254
1255 return labeled_image->details->image != NULL((void*)0) && labeled_image->details->show_image;
1256}
1257
1258static gboolean
1259labeled_image_show_label (const EelLabeledImage *labeled_image)
1260{
1261 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_226
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1261, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1262
1263 return labeled_image->details->label != NULL((void*)0) && labeled_image->details->show_label;
1264}
1265
1266/**
1267 * eel_labeled_image_new:
1268 * @text: Text to use for label or NULL.
1269 * @pixbuf: Pixbuf to use for image or NULL.
1270 *
1271 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1272 * NULL then the LabeledImage will show a label. If the &pixbuf parameter is not
1273 * NULL then the LabeledImage will show a pixbuf. Either of these can be NULL at
1274 * creation time.
1275 *
1276 * Later in the lifetime of the widget you can invoke methods that affect the
1277 * label and/or the image. If at creation time these were NULL, then they will
1278 * be created as neeeded.
1279 *
1280 * Thus, using this widget in place of EelImage or EelLabel is "free" with
1281 * only the GtkWidget and function call overhead.
1282 *
1283 */
1284GtkWidget*
1285eel_labeled_image_new (const char *text,
1286 GdkPixbuf *pixbuf)
1287{
1288 EelLabeledImage *labeled_image;
1289
1290 labeled_image = EEL_LABELED_IMAGE (gtk_widget_new (eel_labeled_image_get_type (), NULL))((((EelLabeledImage*) (void *) ((gtk_widget_new (eel_labeled_image_get_type
(), ((void*)0)))))))
;
1291
1292 if (text != NULL((void*)0))
1293 {
1294 eel_labeled_image_set_text (labeled_image, text);
1295 }
1296
1297 if (pixbuf != NULL((void*)0))
1298 {
1299 eel_labeled_image_set_pixbuf (labeled_image, pixbuf);
1300 }
1301
1302 labeled_image_update_alignments (labeled_image);
1303
1304 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1305}
1306
1307/**
1308 * eel_labeled_image_new_from_file_name:
1309 * @text: Text to use for label or NULL.
1310 * @file_name: File name of picture to use for pixbuf. Cannot be NULL.
1311 *
1312 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1313 * NULL then the LabeledImage will show a label.
1314 *
1315 */
1316GtkWidget*
1317eel_labeled_image_new_from_file_name (const char *text,
1318 const char *pixbuf_file_name)
1319{
1320 EelLabeledImage *labeled_image;
1321
1322 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_227 = 1;
else _g_boolean_var_227 = 0; _g_boolean_var_227; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1323
1324 labeled_image = EEL_LABELED_IMAGE (eel_labeled_image_new (text, NULL))((((EelLabeledImage*) (void *) ((eel_labeled_image_new (text,
((void*)0)))))))
;
1325 eel_labeled_image_set_pixbuf_from_file_name (labeled_image, pixbuf_file_name);
1326 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1327}
1328
1329/**
1330 * eel_labeled_image_set_label_position:
1331 * @labeled_image: A EelLabeledImage.
1332 * @label_position: The position of the label with respect to the image.
1333 *
1334 * Set the position of the label with respect to the image as follows:
1335 *
1336 * GTK_POS_LEFT:
1337 * [ <label> <image> ]
1338 *
1339 * GTK_POS_RIGHT:
1340 * [ <image> <label> ]
1341 *
1342 * GTK_POS_TOP:
1343 * [ <label> ]
1344 * [ <image> ]
1345 *
1346 * GTK_POS_BOTTOM:
1347 * [ <image> ]
1348 * [ <label> ]
1349 *
1350 */
1351void
1352eel_labeled_image_set_label_position (EelLabeledImage *labeled_image,
1353 GtkPositionType label_position)
1354{
1355 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_228 = 1; else _g_boolean_var_228 =
0; _g_boolean_var_228; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1356 g_return_if_fail (label_position >= GTK_POS_LEFT)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if (label_position >= GTK_POS_LEFT) _g_boolean_var_229 =
1; else _g_boolean_var_229 = 0; _g_boolean_var_229; }), 1)))
{ } else { g_return_if_fail_warning ("Eel", ((const char*) (
__func__)), "label_position >= GTK_POS_LEFT"); return; } }
while (0)
;
1357 g_return_if_fail (label_position <= GTK_POS_BOTTOM)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_230
; if (label_position <= GTK_POS_BOTTOM) _g_boolean_var_230
= 1; else _g_boolean_var_230 = 0; _g_boolean_var_230; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "label_position <= GTK_POS_BOTTOM"); return;
} } while (0)
;
1358
1359 if (labeled_image->details->label_position == label_position)
1360 {
1361 return;
1362 }
1363
1364 labeled_image->details->label_position = label_position;
1365
1366 labeled_image_update_alignments (labeled_image);
1367
1368 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1369}
1370
1371/**
1372 * eel_labeled_image_get_label_postiion:
1373 * @labeled_image: A EelLabeledImage.
1374 *
1375 * Returns an enumeration indicating the position of the label with respect to the image.
1376 */
1377GtkPositionType
1378eel_labeled_image_get_label_position (const EelLabeledImage *labeled_image)
1379{
1380 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1381
1382 return labeled_image->details->label_position;
1383}
1384
1385/**
1386 * eel_labeled_image_set_show_label:
1387 * @labeled_image: A EelLabeledImage.
1388 * @show_image: A boolean value indicating whether the label should be shown.
1389 *
1390 * Update the labeled image to either show or hide the internal label widget.
1391 * This function doesnt have any effect if the LabeledImage doesnt already
1392 * contain an label.
1393 */
1394void
1395eel_labeled_image_set_show_label (EelLabeledImage *labeled_image,
1396 gboolean show_label)
1397{
1398 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_232
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1399
1400 if (labeled_image->details->show_label == show_label)
1401 {
1402 return;
1403 }
1404
1405 labeled_image->details->show_label = show_label;
1406
1407 if (labeled_image->details->label != NULL((void*)0))
1408 {
1409 if (labeled_image->details->show_label)
1410 {
1411 gtk_widget_show (labeled_image->details->label);
1412 }
1413 else
1414 {
1415 gtk_widget_hide (labeled_image->details->label);
1416 }
1417 }
1418
1419 labeled_image_update_alignments (labeled_image);
1420
1421 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1422}
1423
1424/**
1425 * eel_labeled_image_get_show_label:
1426 * @labeled_image: A EelLabeledImage.
1427 *
1428 * Returns a boolean value indicating whether the internal label is shown.
1429 */
1430gboolean
1431eel_labeled_image_get_show_label (const EelLabeledImage *labeled_image)
1432{
1433 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_233
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1434
1435 return labeled_image->details->show_label;
1436}
1437
1438/**
1439 * eel_labeled_image_set_show_image:
1440 * @labeled_image: A EelLabeledImage.
1441 * @show_image: A boolean value indicating whether the image should be shown.
1442 *
1443 * Update the labeled image to either show or hide the internal image widget.
1444 * This function doesnt have any effect if the LabeledImage doesnt already
1445 * contain an image.
1446 */
1447void
1448eel_labeled_image_set_show_image (EelLabeledImage *labeled_image,
1449 gboolean show_image)
1450{
1451 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_234
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_234 = 1; else _g_boolean_var_234 =
0; _g_boolean_var_234; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1452
1453 if (labeled_image->details->show_image == show_image)
1454 {
1455 return;
1456 }
1457
1458 labeled_image->details->show_image = show_image;
1459
1460 if (labeled_image->details->image != NULL((void*)0))
1461 {
1462 if (labeled_image->details->show_image)
1463 {
1464 gtk_widget_show (labeled_image->details->image);
1465 }
1466 else
1467 {
1468 gtk_widget_hide (labeled_image->details->image);
1469 }
1470 }
1471
1472 labeled_image_update_alignments (labeled_image);
1473
1474 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1475}
1476
1477/**
1478 * eel_labeled_image_get_show_image:
1479 * @labeled_image: A EelLabeledImage.
1480 *
1481 * Returns a boolean value indicating whether the internal image is shown.
1482 */
1483gboolean
1484eel_labeled_image_get_show_image (const EelLabeledImage *labeled_image)
1485{
1486 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_235
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1487
1488 return labeled_image->details->show_image;
1489}
1490
1491
1492/**
1493 * eel_labeled_image_set_fixed_image_height:
1494 * @labeled_image: A EelLabeledImage.
1495 * @fixed_image_height: The new fixed image height.
1496 *
1497 * Normally, we measure the height of images, but it's sometimes useful
1498 * to use a fixed height for all the images. This routine sets the
1499 * image height to the passed in value
1500 *
1501 */
1502void
1503eel_labeled_image_set_fixed_image_height (EelLabeledImage *labeled_image,
1504 int new_height)
1505{
1506 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_236
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_236 = 1; else _g_boolean_var_236 =
0; _g_boolean_var_236; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1507
1508 if (labeled_image->details->fixed_image_height == new_height)
1509 {
1510 return;
1511 }
1512
1513 labeled_image->details->fixed_image_height = new_height;
1514
1515 labeled_image_update_alignments (labeled_image);
1516
1517 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1518}
1519
1520/**
1521 * eel_labeled_image_set_selected:
1522 * @labeled_image: A EelLabeledImage.
1523 * @selected: A boolean value indicating whether the labeled image
1524 * should be selected.
1525 *
1526 * Selects or deselects the labeled image.
1527 *
1528 */
1529void
1530eel_labeled_image_set_selected (EelLabeledImage *labeled_image,
1531 gboolean selected)
1532{
1533 GtkStateFlags state;
1534 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_237
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1535
1536 state = selected ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_NORMAL;
1537
1538 gtk_widget_set_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), state, TRUE(!(0)));
1539 gtk_widget_set_state_flags (labeled_image->details->image, state, TRUE(!(0)));
1540 gtk_widget_set_state_flags (labeled_image->details->label, state, TRUE(!(0)));
1541
1542}
1543
1544/**
1545 * eel_labeled_image_get_selected:
1546 * @labeled_image: A EelLabeledImage.
1547 *
1548 * Returns the selected state of the labeled image.
1549 *
1550 */
1551gboolean
1552eel_labeled_image_get_selected (EelLabeledImage *labeled_image)
1553{
1554 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_238
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_238 = 1; else _g_boolean_var_238 =
0; _g_boolean_var_238; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return ((0)); } } while (0)
;
1555
1556 return gtk_widget_get_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))))) == GTK_STATE_FLAG_SELECTED;
1557}
1558
1559/**
1560 * eel_labeled_image_set_spacing:
1561 * @labeled_image: A EelLabeledImage.
1562 * @spacing: The new spacing between label and image.
1563 *
1564 * Set the spacing between label and image. This will only affect
1565 * the geometry of the widget if both a label and image are currently
1566 * visible.
1567 *
1568 */
1569void
1570eel_labeled_image_set_spacing (EelLabeledImage *labeled_image,
1571 guint spacing)
1572{
1573 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_239
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_239 = 1; else _g_boolean_var_239 =
0; _g_boolean_var_239; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1574
1575 if (labeled_image->details->spacing == spacing)
1576 {
1577 return;
1578 }
1579
1580 labeled_image->details->spacing = spacing;
1581
1582 labeled_image_update_alignments (labeled_image);
1583
1584 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1585}
1586
1587/**
1588 * eel_labeled_image_get_spacing:
1589 * @labeled_image: A EelLabeledImage.
1590 *
1591 * Returns: The spacing between the label and image.
1592 */
1593guint
1594eel_labeled_image_get_spacing (const EelLabeledImage *labeled_image)
1595{
1596 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_240
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_240 = 1; else _g_boolean_var_240 =
0; _g_boolean_var_240; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1597
1598 return labeled_image->details->spacing;
1599}
1600
1601/**
1602 * eel_labeled_image_set_x_padding:
1603 * @labeled_image: A EelLabeledImage.
1604 * @x_padding: The new horizontal padding.
1605 *
1606 * Set horizontal padding for the EelLabeledImage. The padding
1607 * attribute work just like that in GtkMisc.
1608 */
1609void
1610eel_labeled_image_set_x_padding (EelLabeledImage *labeled_image,
1611 int x_padding)
1612{
1613 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_241
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_241 = 1; else _g_boolean_var_241 =
0; _g_boolean_var_241; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1614
1615 x_padding = MAX (0, x_padding)(((0) > (x_padding)) ? (0) : (x_padding));
1616
1617 if (labeled_image->details->x_padding == x_padding)
1618 {
1619 return;
1620 }
1621
1622 labeled_image->details->x_padding = x_padding;
1623 labeled_image_update_alignments (labeled_image);
1624 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1625}
1626
1627/**
1628 * eel_labeled_image_get_x_padding:
1629 * @labeled_image: A EelLabeledImage.
1630 *
1631 * Returns: The horizontal padding for the LabeledImage's content.
1632 */
1633int
1634eel_labeled_image_get_x_padding (const EelLabeledImage *labeled_image)
1635{
1636 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_242
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1637
1638 return labeled_image->details->x_padding;
1639}
1640
1641/**
1642 * eel_labeled_image_set_y_padding:
1643 * @labeled_image: A EelLabeledImage.
1644 * @x_padding: The new vertical padding.
1645 *
1646 * Set vertical padding for the EelLabeledImage. The padding
1647 * attribute work just like that in GtkMisc.
1648 */
1649void
1650eel_labeled_image_set_y_padding (EelLabeledImage *labeled_image,
1651 int y_padding)
1652{
1653 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_243
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1654
1655 y_padding = MAX (0, y_padding)(((0) > (y_padding)) ? (0) : (y_padding));
1656
1657 if (labeled_image->details->y_padding == y_padding)
1658 {
1659 return;
1660 }
1661
1662 labeled_image->details->y_padding = y_padding;
1663 labeled_image_update_alignments (labeled_image);
1664 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1665}
1666
1667/**
1668 * eel_labeled_image_get_x_padding:
1669 * @labeled_image: A EelLabeledImage.
1670 *
1671 * Returns: The vertical padding for the LabeledImage's content.
1672 */
1673int
1674eel_labeled_image_get_y_padding (const EelLabeledImage *labeled_image)
1675{
1676 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1677
1678 return labeled_image->details->y_padding;
1679}
1680
1681/**
1682 * eel_labeled_image_set_x_alignment:
1683 * @labeled_image: A EelLabeledImage.
1684 * @x_alignment: The new horizontal alignment.
1685 *
1686 * Set horizontal alignment for the EelLabeledImage's content.
1687 * The 'content' is the union of the image and label. The alignment
1688 * attribute work just like that in GtkMisc.
1689 */
1690void
1691eel_labeled_image_set_x_alignment (EelLabeledImage *labeled_image,
1692 float x_alignment)
1693{
1694 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_245
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1695
1696 x_alignment = MAX (0, x_alignment)(((0) > (x_alignment)) ? (0) : (x_alignment));
1697 x_alignment = MIN (1.0, x_alignment)(((1.0) < (x_alignment)) ? (1.0) : (x_alignment));
1698
1699 if (labeled_image->details->x_alignment == x_alignment)
1700 {
1701 return;
1702 }
1703
1704 labeled_image->details->x_alignment = x_alignment;
1705 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1706}
1707
1708/**
1709 * eel_labeled_image_get_x_alignment:
1710 * @labeled_image: A EelLabeledImage.
1711 *
1712 * Returns: The horizontal alignment for the LabeledImage's content.
1713 */
1714float
1715eel_labeled_image_get_x_alignment (const EelLabeledImage *labeled_image)
1716{
1717 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_246
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1718
1719 return labeled_image->details->x_alignment;
1720}
1721
1722/**
1723 * eel_labeled_image_set_y_alignment:
1724 * @labeled_image: A EelLabeledImage.
1725 * @y_alignment: The new vertical alignment.
1726 *
1727 * Set vertical alignment for the EelLabeledImage's content.
1728 * The 'content' is the union of the image and label. The alignment
1729 * attribute work just like that in GtkMisc.
1730 */
1731void
1732eel_labeled_image_set_y_alignment (EelLabeledImage *labeled_image,
1733 float y_alignment)
1734{
1735 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_247
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1736
1737 y_alignment = MAX (0, y_alignment)(((0) > (y_alignment)) ? (0) : (y_alignment));
1738 y_alignment = MIN (1.0, y_alignment)(((1.0) < (y_alignment)) ? (1.0) : (y_alignment));
1739
1740 if (labeled_image->details->y_alignment == y_alignment)
1741 {
1742 return;
1743 }
1744
1745 labeled_image->details->y_alignment = y_alignment;
1746 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1747}
1748
1749/**
1750 * eel_labeled_image_get_y_alignment:
1751 * @labeled_image: A EelLabeledImage.
1752 *
1753 * Returns: The vertical alignment for the LabeledImage's content.
1754 */
1755float
1756eel_labeled_image_get_y_alignment (const EelLabeledImage *labeled_image)
1757{
1758 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_248
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_248 = 1; else _g_boolean_var_248 =
0; _g_boolean_var_248; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1759
1760 return labeled_image->details->y_alignment;
1761}
1762
1763/**
1764 * eel_labeled_image_set_fill:
1765 * @labeled_image: A EelLabeledImage.
1766 * @fill: A boolean value indicating whether the internal image and label
1767 * widgets should fill all the available allocation.
1768 *
1769 * By default the internal image and label wigets are sized to their natural
1770 * preferred geometry. You can use the 'fill' attribute of LabeledImage
1771 * to have the internal widgets fill as much of the LabeledImage allocation
1772 * as is available.
1773 */
1774void
1775eel_labeled_image_set_fill (EelLabeledImage *labeled_image,
1776 gboolean fill)
1777{
1778 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_249
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_249 = 1; else _g_boolean_var_249 =
0; _g_boolean_var_249; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1779
1780 if (labeled_image->details->fill == fill)
1781 {
1782 return;
1783 }
1784
1785 labeled_image->details->fill = fill;
1786
1787 labeled_image_update_alignments (labeled_image);
1788
1789 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1790}
1791
1792/**
1793 * eel_labeled_image_get_fill:
1794 * @labeled_image: A EelLabeledImage.
1795 *
1796 * Retruns a boolean value indicating whether the internal widgets fill
1797 * all the available allocation.
1798 */
1799gboolean
1800eel_labeled_image_get_fill (const EelLabeledImage *labeled_image)
1801{
1802 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_250
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1803
1804 return labeled_image->details->fill;
1805}
1806
1807static void
1808eel_labled_set_mnemonic_widget (GtkWidget *image_widget,
1809 GtkWidget *mnemonic_widget)
1810{
1811 EelLabeledImage *image;
1812
1813 g_assert (EEL_IS_LABELED_IMAGE (image_widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_251
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_widget)); GType __t = (eel_labeled_image_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_251 = 1; else _g_boolean_var_251 =
0; _g_boolean_var_251; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1813, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (image_widget)"); } while (0)
;
1814
1815 image = EEL_LABELED_IMAGE (image_widget)((((EelLabeledImage*) (void *) ((image_widget)))));
1816
1817 if (image->details->label)
1818 gtk_label_set_mnemonic_widget
1819 (GTK_LABEL (image->details->label)((((GtkLabel*) (void *) ((image->details->label))))), mnemonic_widget);
1820}
1821
1822/**
1823 * eel_labeled_image_button_new:
1824 * @text: Text to use for label or NULL.
1825 * @pixbuf: Pixbuf to use for image or NULL.
1826 *
1827 * Create a stock GtkButton with a EelLabeledImage child.
1828 *
1829 */
1830GtkWidget *
1831eel_labeled_image_button_new (const char *text,
1832 GdkPixbuf *pixbuf)
1833{
1834 GtkWidget *button;
1835 GtkWidget *labeled_image;
1836
1837 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1838 labeled_image = eel_labeled_image_new (text, pixbuf);
1839 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1840 eel_labled_set_mnemonic_widget (labeled_image, button);
1841 gtk_widget_show (labeled_image);
1842
1843 return button;
1844}
1845
1846/**
1847 * eel_labeled_image_button_new_from_file_name:
1848 * @text: Text to use for label or NULL.
1849 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1850 *
1851 * Create a stock GtkToggleButton with a EelLabeledImage child.
1852 *
1853 */
1854GtkWidget *
1855eel_labeled_image_button_new_from_file_name (const char *text,
1856 const char *pixbuf_file_name)
1857{
1858 GtkWidget *button;
1859 GtkWidget *labeled_image;
1860
1861 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_252
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_252 = 1;
else _g_boolean_var_252 = 0; _g_boolean_var_252; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1862
1863 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1864 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1865 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1866 eel_labled_set_mnemonic_widget (labeled_image, button);
1867 gtk_widget_show (labeled_image);
1868
1869 return button;
1870}
1871
1872/**
1873 * eel_labeled_image_toggle_button_new:
1874 * @text: Text to use for label or NULL.
1875 * @pixbuf: Pixbuf to use for image or NULL.
1876 *
1877 * Create a stock GtkToggleButton with a EelLabeledImage child.
1878 *
1879 */
1880GtkWidget *
1881eel_labeled_image_toggle_button_new (const char *text,
1882 GdkPixbuf *pixbuf)
1883{
1884 GtkWidget *toggle_button;
1885 GtkWidget *labeled_image;
1886
1887 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1888 labeled_image = eel_labeled_image_new (text, pixbuf);
1889 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1890 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1891 gtk_widget_show (labeled_image);
1892
1893 return toggle_button;
1894}
1895
1896/**
1897 * eel_labeled_image_toggle_button_new_from_file_name:
1898 * @text: Text to use for label or NULL.
1899 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1900 *
1901 * Create a stock GtkToggleButton with a EelLabeledImage child.
1902 *
1903 */
1904GtkWidget *
1905eel_labeled_image_toggle_button_new_from_file_name (const char *text,
1906 const char *pixbuf_file_name)
1907{
1908 GtkWidget *toggle_button;
1909 GtkWidget *labeled_image;
1910
1911 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_253
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_253 = 1;
else _g_boolean_var_253 = 0; _g_boolean_var_253; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1912
1913 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1914 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1915 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1916 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1917 gtk_widget_show (labeled_image);
1918
1919 return toggle_button;
1920}
1921
1922/**
1923 * eel_labeled_image_toggle_button_new:
1924 * @text: Text to use for label or NULL.
1925 * @pixbuf: Pixbuf to use for image or NULL.
1926 *
1927 * Create a stock GtkToggleButton with a EelLabeledImage child.
1928 *
1929 * Returns: the new radio button.
1930 */
1931GtkWidget *
1932eel_labeled_image_radio_button_new (const char *text,
1933 GdkPixbuf *pixbuf)
1934{
1935 GtkWidget *radio_button;
1936 GtkWidget *labeled_image;
1937
1938 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1939 labeled_image = eel_labeled_image_new (text, pixbuf);
1940 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1941 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1942 gtk_widget_show (labeled_image);
1943
1944 return radio_button;
1945}
1946
1947/**
1948 * eel_labeled_image_radio_button_new_from_file_name:
1949 * @text: Text to use for label or NULL.
1950 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1951 *
1952 * Create a stock GtkRadioButton with a EelLabeledImage child.
1953 *
1954 * Returns: the new radio button.
1955 */
1956GtkWidget *
1957eel_labeled_image_radio_button_new_from_file_name (const char *text,
1958 const char *pixbuf_file_name)
1959{
1960 GtkWidget *radio_button;
1961 GtkWidget *labeled_image;
1962
1963 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_254
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_254 = 1;
else _g_boolean_var_254 = 0; _g_boolean_var_254; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1964
1965 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1966 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1967 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1968 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1969 gtk_widget_show (labeled_image);
1970
1971 return radio_button;
1972}
1973
1974/*
1975 * Workaround some bugs in GtkCheckButton where the widget
1976 * does not redraw properly after leave or focus out events
1977 *
1978 * The workaround is to draw a little bit more than the
1979 * widget itself - 4 pixels worth. For some reason the
1980 * widget does not properly redraw its edges.
1981 */
1982static void
1983button_leave_callback (GtkWidget *widget,
1984 gpointer callback_data)
1985{
1986 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_255
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 1986, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
1987
1988 if (gtk_widget_is_drawable (widget))
1989 {
1990 const int fudge = 4;
1991 EelIRect bounds;
1992
1993 bounds = eel_gtk_widget_get_bounds (widget);
1994
1995 bounds.x0 -= fudge;
1996 bounds.y0 -= fudge;
1997 bounds.x1 += fudge;
1998 bounds.y1 += fudge;
1999
2000 gtk_widget_queue_draw_area (gtk_widget_get_parent (widget),
2001 bounds.x0,
2002 bounds.y0,
2003 eel_irect_get_width (bounds),
2004 eel_irect_get_height (bounds));
2005 }
2006}
2007
2008static gint
2009button_focus_out_event_callback (GtkWidget *widget,
2010 GdkEventFocus *event,
2011 gpointer callback_data)
2012{
2013 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_256
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 2013, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
2014
2015 button_leave_callback (widget, callback_data);
2016
2017 return FALSE(0);
2018}
2019
2020/**
2021 * eel_labeled_image_check_button_new:
2022 * @text: Text to use for label or NULL.
2023 * @pixbuf: Pixbuf to use for image or NULL.
2024 *
2025 * Create a stock GtkCheckButton with a EelLabeledImage child.
2026 *
2027 */
2028GtkWidget *
2029eel_labeled_image_check_button_new (const char *text,
2030 GdkPixbuf *pixbuf)
2031{
2032 GtkWidget *check_button;
2033 GtkWidget *labeled_image;
2034
2035 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2036 labeled_image = eel_labeled_image_new (text, pixbuf);
2037 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2038 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2039 gtk_widget_show (labeled_image);
2040
2041 /*
2042 * Workaround some bugs in GtkCheckButton where the widget
2043 * does not redraw properly after leave or focus out events
2044 */
2045 g_signal_connect (check_button, "leave",g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
2046 G_CALLBACK (button_leave_callback), NULL)g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
2047 g_signal_connect (check_button, "focus_out_event",g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
2048 G_CALLBACK (button_focus_out_event_callback), NULL)g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
;
2049
2050 return check_button;
2051}
2052
2053/**
2054 * eel_labeled_image_check_button_new_from_file_name:
2055 * @text: Text to use for label or NULL.
2056 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
2057 *
2058 * Create a stock GtkCheckButton with a EelLabeledImage child.
2059 *
2060 */
2061GtkWidget *
2062eel_labeled_image_check_button_new_from_file_name (const char *text,
2063 const char *pixbuf_file_name)
2064{
2065 GtkWidget *check_button;
2066 GtkWidget *labeled_image;
2067
2068 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_257
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_257 = 1;
else _g_boolean_var_257 = 0; _g_boolean_var_257; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
2069
2070 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2071 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
2072 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2073 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2074 gtk_widget_show (labeled_image);
2075
2076 return check_button;
2077}
2078
2079/*
2080 * The rest of the methods are proxies for those in EelImage and
2081 * EelLabel. We have all these so that we dont have to expose
2082 * our internal widgets at all. Probably more of these will be added
2083 * as they are needed.
2084 */
2085
2086/**
2087 * eel_labeled_image_set_pixbuf:
2088 * @labaled_image: A EelLabeledImage.
2089 * @pixbuf: New pixbuf to use or NULL.
2090 *
2091 * Change the pixbuf displayed by the LabeledImage. Note that the widget display
2092 * is only updated if the show_image attribute is TRUE.
2093 *
2094 * If no internal image widget exists as of yet, a new one will be created.
2095 *
2096 * A NULL &pixbuf will cause the internal image widget (if alive) to be destroyed.
2097 */
2098void
2099eel_labeled_image_set_pixbuf (EelLabeledImage *labeled_image,
2100 GdkPixbuf *pixbuf)
2101{
2102 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_258
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_258 = 1; else _g_boolean_var_258 =
0; _g_boolean_var_258; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2103
2104 if (pixbuf == NULL((void*)0))
2105 {
2106 if (labeled_image->details->image != NULL((void*)0))
2107 {
2108 gtk_widget_destroy (labeled_image->details->image);
2109 labeled_image->details->image = NULL((void*)0);
2110 }
2111
2112 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2113 }
2114 else
2115 {
2116 labeled_image_ensure_image (labeled_image);
2117 gtk_image_set_from_pixbuf (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf);
2118 }
2119}
2120
2121void
2122eel_labeled_image_set_pixbuf_from_file_name (EelLabeledImage *labeled_image,
2123 const char *pixbuf_file_name)
2124{
2125 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_259
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_259 = 1; else _g_boolean_var_259 =
0; _g_boolean_var_259; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2126
2127 labeled_image_ensure_image (labeled_image);
2128 gtk_image_set_from_file (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf_file_name);
2129}
2130
2131/**
2132 * eel_labeled_image_set_text:
2133 * @labaled_image: A EelLabeledImage.
2134 * @text: New text (with mnemnonic) to use or NULL.
2135 *
2136 * Change the text displayed by the LabeledImage. Note that the widget display
2137 * is only updated if the show_label attribute is TRUE.
2138 *
2139 * If no internal label widget exists as of yet, a new one will be created.
2140 *
2141 * A NULL &text will cause the internal label widget (if alive) to be destroyed.
2142 */
2143void
2144eel_labeled_image_set_text (EelLabeledImage *labeled_image,
2145 const char *text)
2146{
2147 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_260
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2148
2149 if (text == NULL((void*)0))
2150 {
2151 if (labeled_image->details->label)
2152 {
2153 gtk_widget_destroy (labeled_image->details->label);
2154 labeled_image->details->label = NULL((void*)0);
2155 }
2156
2157 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2158 }
2159 else
2160 {
2161 labeled_image_ensure_label (labeled_image);
2162 gtk_label_set_text_with_mnemonic
2163 (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, text);
2164 }
2165}
2166
2167char *
2168eel_labeled_image_get_text (const EelLabeledImage *labeled_image)
2169{
2170 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_261
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (((void*)0)); } } while (0)
;
2171
2172 if (labeled_image->details->label == NULL((void*)0))
2173 {
2174 return NULL((void*)0);
2175 }
2176
2177 return g_strdup (gtk_label_get_text (GTK_LABEL (labeled_image->details->label)))g_strdup_inline (gtk_label_get_text (((((GtkLabel*) (void *) (
(labeled_image->details->label)))))))
;
2178}
2179
2180void
2181eel_labeled_image_set_can_focus (EelLabeledImage *labeled_image,
2182 gboolean can_focus)
2183{
2184 gtk_widget_set_can_focus (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), can_focus);
2185}
2186
2187static AtkObjectClass *a11y_parent_class = NULL((void*)0);
2188
2189static void
2190eel_labeled_image_accessible_initialize (AtkObject *accessible,
2191 gpointer widget)
2192{
2193 a11y_parent_class->initialize (accessible, widget);
2194 atk_object_set_role (accessible, ATK_ROLE_IMAGE);
2195
2196}
2197
2198static EelLabeledImage *
2199get_image (gpointer object)
2200{
2201 GtkWidget *widget;
2202
2203 if (!(widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (object)((((GtkAccessible*) (void *) ((object))))))))
2204 {
2205 return NULL((void*)0);
2206 }
2207
2208 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; }))))
)
2209 widget = gtk_bin_get_child (GTK_BIN (widget)((((GtkBin*) (void *) ((widget))))));
2210
2211 return EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
2212}
2213
2214static const gchar* eel_labeled_image_accessible_get_name(AtkObject* accessible)
2215{
2216 EelLabeledImage* labeled_image;
2217
2218 labeled_image = get_image(accessible);
2219
2220 if (labeled_image && labeled_image->details && labeled_image->details->label)
2221 {
2222 return gtk_label_get_text(GTK_LABEL(labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
2223 }
2224
2225 g_warning("no label on '%p'", labeled_image);
2226
2227 return NULL((void*)0);
2228}
2229
2230static void
2231eel_labeled_image_accessible_image_get_size (AtkImage *image,
2232 gint *width,
2233 gint *height)
2234{
2235 EelLabeledImage *labeled_image;
2236 GtkAllocation allocation;
2237
2238 labeled_image = get_image (image);
2239
2240 if (!labeled_image || !labeled_image->details->image)
2241 {
2242 *width = *height = 0;
2243 return;
2244 }
2245
2246 gtk_widget_get_allocation (labeled_image->details->image, &allocation);
2247 *width = allocation.width;
2248 *height = allocation.height;
2249}
2250
2251static void
2252eel_labeled_image_accessible_image_interface_init (AtkImageIface *iface)
2253{
2254 iface->get_image_size = eel_labeled_image_accessible_image_get_size;
2255}
2256
2257typedef struct _EelLabeledImageAccessible EelLabeledImageAccessible;
2258typedef struct _EelLabeledImageAccessibleClass EelLabeledImageAccessibleClass;
2259
2260struct _EelLabeledImageAccessible
2261{
2262 GtkContainerAccessible parent;
2263};
2264
2265struct _EelLabeledImageAccessibleClass
2266{
2267 GtkContainerAccessibleClass parent_class;
2268};
2269
2270G_DEFINE_TYPE_WITH_CODE (EelLabeledImageAccessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2271 eel_labeled_image_accessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2272 GTK_TYPE_CONTAINER_ACCESSIBLE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2273 G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2274 eel_labeled_image_accessible_image_interface_init))static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
;
2275static void
2276eel_labeled_image_accessible_class_init (EelLabeledImageAccessibleClass *klass)
2277{
2278 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
2279 a11y_parent_class = g_type_class_peek_parent (klass);
2280
2281 atk_class->get_name = eel_labeled_image_accessible_get_name;
2282 atk_class->initialize = eel_labeled_image_accessible_initialize;
2283}
2284
2285static void
2286eel_labeled_image_accessible_init (EelLabeledImageAccessible *accessible)
2287{
2288}
2289
2290static void
2291eel_labeled_image_button_class_init (GtkWidgetClass *klass)
2292{
2293}
2294
2295static GType
2296eel_labeled_image_button_get_type (void)
2297{
2298 static GType type = 0;
2299
2300 if (!type)
2301 {
2302 GTypeInfo info =
2303 {
2304 sizeof (GtkButtonClass),
2305 (GBaseInitFunc) NULL((void*)0),
2306 (GBaseFinalizeFunc) NULL((void*)0),
2307 (GClassInitFunc) eel_labeled_image_button_class_init,
2308 NULL((void*)0), /* class_finalize */
2309 NULL((void*)0), /* class_data */
2310 sizeof (GtkButton),
2311 0, /* n_preallocs */
2312 (GInstanceInitFunc) NULL((void*)0)
2313 };
2314
2315 type = g_type_register_static
2316 (GTK_TYPE_BUTTON(gtk_button_get_type ()),
2317 "EelLabeledImageButton", &info, 0);
2318 }
2319
2320 return type;
2321}
2322
2323static GType
2324eel_labeled_image_check_button_get_type (void)
2325{
2326 static GType type = 0;
2327
2328 if (!type)
2329 {
2330 GTypeInfo info =
2331 {
2332 sizeof (GtkCheckButtonClass),
2333 (GBaseInitFunc) NULL((void*)0),
2334 (GBaseFinalizeFunc) NULL((void*)0),
2335 (GClassInitFunc) eel_labeled_image_button_class_init,
2336 NULL((void*)0), /* class_finalize */
2337 NULL((void*)0), /* class_data */
2338 sizeof (GtkCheckButton),
2339 0, /* n_preallocs */
2340 (GInstanceInitFunc) NULL((void*)0)
2341 };
2342
2343 type = g_type_register_static
2344 (GTK_TYPE_CHECK_BUTTON(gtk_check_button_get_type ()),
2345 "EelLabeledImageCheckButton", &info, 0);
2346 }
2347
2348 return type;
2349}
2350
2351static GType
2352eel_labeled_image_toggle_button_get_type (void)
2353{
2354 static GType type = 0;
2355
2356 if (!type)
2357 {
2358 GTypeInfo info =
2359 {
2360 sizeof (GtkToggleButtonClass),
2361 (GBaseInitFunc) NULL((void*)0),
2362 (GBaseFinalizeFunc) NULL((void*)0),
2363 (GClassInitFunc) eel_labeled_image_button_class_init,
2364 NULL((void*)0), /* class_finalize */
2365 NULL((void*)0), /* class_data */
2366 sizeof (GtkToggleButton),
2367 0, /* n_preallocs */
2368 (GInstanceInitFunc) NULL((void*)0)
2369 };
2370
2371 type = g_type_register_static
2372 (GTK_TYPE_TOGGLE_BUTTON(gtk_toggle_button_get_type ()),
2373 "EelLabeledImageToggleButton", &info, 0);
2374 }
2375
2376 return type;
2377}
2378
2379
2380static GType
2381eel_labeled_image_radio_button_get_type (void)
2382{
2383 static GType type = 0;
2384
2385 if (!type)
2386 {
2387 GTypeInfo info =
2388 {
2389 sizeof (GtkRadioButtonClass),
2390 (GBaseInitFunc) NULL((void*)0),
2391 (GBaseFinalizeFunc) NULL((void*)0),
2392 (GClassInitFunc) eel_labeled_image_button_class_init,
2393 NULL((void*)0), /* class_finalize */
2394 NULL((void*)0), /* class_data */
2395 sizeof (GtkRadioButton),
2396 0, /* n_preallocs */
2397 (GInstanceInitFunc) NULL((void*)0)
2398 };
2399
2400 type = g_type_register_static
2401 (GTK_TYPE_RADIO_BUTTON(gtk_radio_button_get_type ()),
2402 "EelLabeledImageRadioButton", &info, 0);
2403 }
2404
2405 return type;
2406}
diff --git a/2024-07-29-023715-6438-1/report-efae23.html b/2024-07-29-023715-6438-1/report-efae23.html new file mode 100644 index 000000000..bccfaa4e2 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-efae23.html @@ -0,0 +1,3086 @@ + + + +eel-labeled-image.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-labeled-image.c
Warning:line 1057, column 13
Value stored to 'y_alignment' 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 eel-labeled-image.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-labeled-image.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* eel-labeled-image.c - A labeled image.
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Ramiro Estrugo <ramiro@eazel.com>
23*/
24
25#include <config.h>
26#include "eel-labeled-image.h"
27
28#include "eel-art-extensions.h"
29#include "eel-art-gtk-extensions.h"
30#include "eel-gtk-container.h"
31#include "eel-gtk-extensions.h"
32#include "eel-accessibility.h"
33#include <gtk/gtk.h>
34#include <gtk/gtk-a11y.h>
35#include <gdk/gdkkeysyms.h>
36#include <atk/atkimage.h>
37
38#define DEFAULT_SPACING0 0
39#define DEFAULT_X_PADDING0 0
40#define DEFAULT_Y_PADDING0 0
41#define DEFAULT_X_ALIGNMENT0.5 0.5
42#define DEFAULT_Y_ALIGNMENT0.5 0.5
43
44/* Signals */
45enum
46{
47 ACTIVATE,
48 LAST_SIGNAL
49};
50
51/* Arguments */
52enum
53{
54 PROP_0,
55 PROP_FILL,
56 PROP_LABEL,
57 PROP_LABEL_POSITION,
58 PROP_PIXBUF,
59 PROP_SHOW_IMAGE,
60 PROP_SHOW_LABEL,
61 PROP_SPACING,
62 PROP_X_ALIGNMENT,
63 PROP_X_PADDING,
64 PROP_Y_ALIGNMENT,
65 PROP_Y_PADDING
66};
67
68/* Detail member struct */
69struct EelLabeledImagePrivate
70{
71 GtkWidget *image;
72 GtkWidget *label;
73 GtkPositionType label_position;
74 gboolean show_label;
75 gboolean show_image;
76 guint spacing;
77 float x_alignment;
78 float y_alignment;
79 int x_padding;
80 int y_padding;
81 int fixed_image_height;
82 gboolean fill;
83};
84
85/* derived types so we can add our accessibility interfaces */
86static GType eel_labeled_image_button_get_type (void);
87static GType eel_labeled_image_check_button_get_type (void);
88static GType eel_labeled_image_radio_button_get_type (void);
89static GType eel_labeled_image_toggle_button_get_type (void);
90
91/* GtkWidgetClass methods */
92static GType eel_labeled_image_accessible_get_type (void);
93
94/* Private EelLabeledImage methods */
95static EelDimensions labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image);
96static EelDimensions labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image);
97static void labeled_image_ensure_label (EelLabeledImage *labeled_image);
98static void labeled_image_ensure_image (EelLabeledImage *labeled_image);
99static EelIRect labeled_image_get_content_bounds (const EelLabeledImage *labeled_image);
100static EelDimensions labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image);
101static void labeled_image_update_alignments (EelLabeledImage *labeled_image);
102static gboolean labeled_image_show_label (const EelLabeledImage *labeled_image);
103static gboolean labeled_image_show_image (const EelLabeledImage *labeled_image);
104
105static guint labeled_image_signals[LAST_SIGNAL] = { 0 };
106
107G_DEFINE_TYPE_WITH_PRIVATE (EelLabeledImage, eel_labeled_image, GTK_TYPE_CONTAINER)static void eel_labeled_image_init (EelLabeledImage *self); static
void eel_labeled_image_class_init (EelLabeledImageClass *klass
); static GType eel_labeled_image_get_type_once (void); static
gpointer eel_labeled_image_parent_class = ((void*)0); static
gint EelLabeledImage_private_offset; static void eel_labeled_image_class_intern_init
(gpointer klass) { eel_labeled_image_parent_class = g_type_class_peek_parent
(klass); if (EelLabeledImage_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelLabeledImage_private_offset); eel_labeled_image_class_init
((EelLabeledImageClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_labeled_image_get_instance_private
(EelLabeledImage *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EelLabeledImage_private_offset)))); } GType eel_labeled_image_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType eel_labeled_image_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_get_type ()), g_intern_static_string ("EelLabeledImage"
), sizeof (EelLabeledImageClass), (GClassInitFunc)(void (*)(void
)) eel_labeled_image_class_intern_init, sizeof (EelLabeledImage
), (GInstanceInitFunc)(void (*)(void)) eel_labeled_image_init
, (GTypeFlags) 0); { {{ EelLabeledImage_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (EelLabeledImagePrivate)); };} } return
g_define_type_id; }
108
109static void
110eel_labeled_image_init (EelLabeledImage *labeled_image)
111{
112 gtk_widget_set_has_window (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), FALSE(0));
113
114 labeled_image->details = eel_labeled_image_get_instance_private (labeled_image);
115 labeled_image->details->show_label = TRUE(!(0));
116 labeled_image->details->show_image = TRUE(!(0));
117 labeled_image->details->label_position = GTK_POS_BOTTOM;
118 labeled_image->details->spacing = DEFAULT_SPACING0;
119 labeled_image->details->x_padding = DEFAULT_X_PADDING0;
120 labeled_image->details->y_padding = DEFAULT_Y_PADDING0;
121 labeled_image->details->x_alignment = DEFAULT_X_ALIGNMENT0.5;
122 labeled_image->details->y_alignment = DEFAULT_Y_ALIGNMENT0.5;
123 labeled_image->details->fixed_image_height = 0;
124
125 eel_labeled_image_set_fill (labeled_image, FALSE(0));
126}
127
128static void
129eel_labeled_image_destroy (GtkWidget *object)
130{
131 EelLabeledImage *labeled_image;
132
133 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
134
135 if (labeled_image->details->image != NULL((void*)0))
136 {
137 gtk_widget_destroy (labeled_image->details->image);
138 }
139
140 if (labeled_image->details->label != NULL((void*)0))
141 {
142 gtk_widget_destroy (labeled_image->details->label);
143 }
144
145 GTK_WIDGET_CLASS (eel_labeled_image_parent_class)((((GtkWidgetClass*) (void *) ((eel_labeled_image_parent_class
)))))
->destroy (object);
146}
147
148/* GObjectClass methods */
149static void
150eel_labeled_image_set_property (GObject *object,
151 guint property_id,
152 const GValue *value,
153 GParamSpec *pspec)
154{
155 EelLabeledImage *labeled_image;
156
157 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_136
= 1; else _g_boolean_var_136 = 0; _g_boolean_var_136; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 157, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
158
159 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
160
161 switch (property_id)
162 {
163 case PROP_PIXBUF:
164 eel_labeled_image_set_pixbuf (labeled_image,
165 g_value_get_object (value));
166 break;
167
168 case PROP_LABEL:
169 eel_labeled_image_set_text (labeled_image, g_value_get_string (value));
170 break;
171
172 case PROP_LABEL_POSITION:
173 eel_labeled_image_set_label_position (labeled_image,
174 g_value_get_enum (value));
175 break;
176
177 case PROP_SHOW_LABEL:
178 eel_labeled_image_set_show_label (labeled_image,
179 g_value_get_boolean (value));
180 break;
181
182 case PROP_SHOW_IMAGE:
183 eel_labeled_image_set_show_image (labeled_image,
184 g_value_get_boolean (value));
185 break;
186
187 case PROP_SPACING:
188 eel_labeled_image_set_spacing (labeled_image,
189 g_value_get_uint (value));
190 break;
191
192 case PROP_X_PADDING:
193 eel_labeled_image_set_x_padding (labeled_image,
194 g_value_get_int (value));
195 break;
196
197 case PROP_Y_PADDING:
198 eel_labeled_image_set_y_padding (labeled_image,
199 g_value_get_int (value));
200 break;
201
202 case PROP_X_ALIGNMENT:
203 eel_labeled_image_set_x_alignment (labeled_image,
204 g_value_get_float (value));
205 break;
206
207 case PROP_Y_ALIGNMENT:
208 eel_labeled_image_set_y_alignment (labeled_image,
209 g_value_get_float (value));
210 break;
211
212 case PROP_FILL:
213 eel_labeled_image_set_fill (labeled_image,
214 g_value_get_boolean (value));
215 break;
216 default:
217 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 217
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
218 }
219}
220
221static void
222eel_labeled_image_get_property (GObject *object,
223 guint property_id,
224 GValue *value,
225 GParamSpec *pspec)
226{
227 EelLabeledImage *labeled_image;
228
229 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_137
= 1; else _g_boolean_var_137 = 0; _g_boolean_var_137; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 229, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
230
231 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
232
233 switch (property_id)
234 {
235 case PROP_LABEL:
236 if (labeled_image->details->label == NULL((void*)0))
237 {
238 g_value_set_string (value, NULL((void*)0));
239 }
240 else
241 {
242 g_value_set_string (value,
243 gtk_label_get_text (GTK_LABEL (((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
244 labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
));
245 }
246 break;
247
248 case PROP_LABEL_POSITION:
249 g_value_set_enum (value, eel_labeled_image_get_label_position (labeled_image));
250 break;
251
252 case PROP_SHOW_LABEL:
253 g_value_set_boolean (value, eel_labeled_image_get_show_label (labeled_image));
254 break;
255
256 case PROP_SHOW_IMAGE:
257 g_value_set_boolean (value, eel_labeled_image_get_show_image (labeled_image));
258 break;
259
260 case PROP_SPACING:
261 g_value_set_uint (value, eel_labeled_image_get_spacing (labeled_image));
262 break;
263
264 case PROP_X_PADDING:
265 g_value_set_int (value, eel_labeled_image_get_x_padding (labeled_image));
266 break;
267
268 case PROP_Y_PADDING:
269 g_value_set_int (value, eel_labeled_image_get_y_padding (labeled_image));
270 break;
271
272 case PROP_X_ALIGNMENT:
273 g_value_set_float (value, eel_labeled_image_get_x_alignment (labeled_image));
274 break;
275
276 case PROP_Y_ALIGNMENT:
277 g_value_set_float (value, eel_labeled_image_get_y_alignment (labeled_image));
278 break;
279
280 case PROP_FILL:
281 g_value_set_boolean (value, eel_labeled_image_get_fill (labeled_image));
282 break;
283
284 default:
285 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 285
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
286 }
287}
288
289/* GtkWidgetClass methods */
290static void
291eel_labeled_image_size_request (GtkWidget *widget,
292 GtkRequisition *requisition)
293{
294 EelLabeledImage *labeled_image;
295 EelDimensions content_dimensions;
296
297 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 297, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
298 g_assert (requisition != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if (requisition != ((void*)0)) _g_boolean_var_139 = 1; else
_g_boolean_var_139 = 0; _g_boolean_var_139; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 298, ((const char*) (__func__
)), "requisition != NULL"); } while (0)
;
299
300 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
301
302 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
303
304 requisition->width =
305 MAX (1, content_dimensions.width)(((1) > (content_dimensions.width)) ? (1) : (content_dimensions
.width))
+
306 2 * labeled_image->details->x_padding;
307
308 requisition->height =
309 MAX (1, content_dimensions.height)(((1) > (content_dimensions.height)) ? (1) : (content_dimensions
.height))
+
310 2 * labeled_image->details->y_padding;
311}
312
313static void
314eel_labeled_image_get_preferred_width (GtkWidget *widget,
315 gint *minimum_width,
316 gint *natural_width)
317{
318 GtkRequisition req;
319 eel_labeled_image_size_request (widget, &req);
320 *minimum_width = *natural_width = req.width;
321}
322
323static void
324eel_labeled_image_get_preferred_height (GtkWidget *widget,
325 gint *minimum_height,
326 gint *natural_height)
327{
328 GtkRequisition req;
329 eel_labeled_image_size_request (widget, &req);
330 *minimum_height = *natural_height = req.height;
331}
332
333static void
334eel_labeled_image_size_allocate (GtkWidget *widget,
335 GtkAllocation *allocation)
336{
337 EelLabeledImage *labeled_image;
338 EelIRect image_bounds;
339 EelIRect label_bounds;
340
341 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_140
= 1; else _g_boolean_var_140 = 0; _g_boolean_var_140; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 341, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
342 g_assert (allocation != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (allocation != ((void*)0)) _g_boolean_var_141 = 1; else _g_boolean_var_141
= 0; _g_boolean_var_141; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 342, ((const char*) (__func__
)), "allocation != NULL"); } while (0)
;
343
344 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
345
346 gtk_widget_set_allocation (widget, allocation);
347
348 label_bounds = eel_labeled_image_get_label_bounds (labeled_image);
349 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
350 labeled_image->details->label,
351 label_bounds);
352
353 image_bounds = eel_labeled_image_get_image_bounds (labeled_image);
354 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
355 labeled_image->details->image,
356 image_bounds);
357}
358
359static int
360eel_labeled_image_draw (GtkWidget *widget,
361 cairo_t *cr)
362{
363 EelLabeledImage *labeled_image;
364 EelIRect label_bounds;
365 GtkStyleContext *context;
366
367 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 367, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
368 g_assert (gtk_widget_get_realized (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if (gtk_widget_get_realized (widget)) _g_boolean_var_143 = 1
; else _g_boolean_var_143 = 0; _g_boolean_var_143; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-labeled-image.c", 368,
((const char*) (__func__)), "gtk_widget_get_realized (widget)"
); } while (0)
;
369
370 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
371
372 context = gtk_widget_get_style_context (widget);
373 gtk_style_context_save (context);
374
375 if (gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_SELECTED ||
376 gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_ACTIVE)
377 {
378 label_bounds = eel_labeled_image_get_label_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
379
380 gtk_widget_get_state_flags (widget);
381 gtk_render_background (context,
382 cr,
383 label_bounds.x0, label_bounds.y0,
384 label_bounds.x1 - label_bounds.x0,
385 label_bounds.y1 - label_bounds.y0);
386
387 gtk_render_frame (context,
388 cr,
389 label_bounds.x0, label_bounds.y0,
390 label_bounds.x1 - label_bounds.x0,
391 label_bounds.y1 - label_bounds.y0);
392 }
393
394 if (labeled_image_show_label (labeled_image))
395 {
396 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
397 labeled_image->details->label,
398 cr);
399 }
400
401 if (labeled_image_show_image (labeled_image))
402 {
403 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
404 labeled_image->details->image,
405 cr);
406 }
407
408 if (gtk_widget_has_focus (widget))
409 {
410 label_bounds = eel_labeled_image_get_image_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
411 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_NORMAL, TRUE(!(0)));
412 gtk_render_focus (context,
413 cr,
414 label_bounds.x0, label_bounds.y0,
415 label_bounds.x1 - label_bounds.x0,
416 label_bounds.y1 - label_bounds.y0);
417 }
418
419 gtk_style_context_restore (context);
420
421 return FALSE(0);
422}
423
424static void
425eel_labeled_image_map (GtkWidget *widget)
426{
427 EelLabeledImage *labeled_image;
428
429 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 429, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
430
431 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
432
433 gtk_widget_set_mapped (widget, TRUE(!(0)));
434
435 if (labeled_image_show_label (labeled_image))
436 {
437 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
438 }
439
440 if (labeled_image_show_image (labeled_image))
441 {
442 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
443 }
444}
445
446static void
447eel_labeled_image_unmap (GtkWidget *widget)
448{
449 EelLabeledImage *labeled_image;
450
451 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 451, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
452
453 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
454
455 gtk_widget_set_mapped (widget, FALSE(0));
456
457 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
458 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
459}
460
461/* GtkContainerClass methods */
462static void
463eel_labeled_image_add (GtkContainer *container,
464 GtkWidget *child)
465{
466 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_146
= 1; else _g_boolean_var_146 = 0; _g_boolean_var_146; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 466, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
467
468 eel_gtk_container_child_add (container, child);
469}
470
471static void
472eel_labeled_image_remove (GtkContainer *container,
473 GtkWidget *child)
474{
475 EelLabeledImage *labeled_image;
476
477 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 477, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
478
479 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));;
480
481 g_assert (child == labeled_image->details->image || child == labeled_image->details->label)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_148
; if (child == labeled_image->details->image || child ==
labeled_image->details->label) _g_boolean_var_148 = 1;
else _g_boolean_var_148 = 0; _g_boolean_var_148; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-labeled-image.c", 481,
((const char*) (__func__)), "child == labeled_image->details->image || child == labeled_image->details->label"
); } while (0)
;
482
483 eel_gtk_container_child_remove (container, child);
484
485 if (labeled_image->details->image == child)
486 {
487 labeled_image->details->image = NULL((void*)0);
488 }
489
490 if (labeled_image->details->label == child)
491 {
492 labeled_image->details->label = NULL((void*)0);
493 }
494}
495
496static void
497eel_labeled_image_forall (GtkContainer *container,
498 gboolean include_internals,
499 GtkCallback callback,
500 gpointer callback_data)
501{
502 EelLabeledImage *labeled_image;
503
504 g_assert (EEL_IS_LABELED_IMAGE (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 504, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (container)"
); } while (0)
;
505 g_assert (callback != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (callback != ((void*)0)) _g_boolean_var_150 = 1; else _g_boolean_var_150
= 0; _g_boolean_var_150; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 505, ((const char*) (__func__
)), "callback != NULL"); } while (0)
;
506
507 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));
508
509 if (include_internals)
510 {
511 if (labeled_image->details->image != NULL((void*)0))
512 {
513 (* callback) (labeled_image->details->image, callback_data);
514 }
515
516 if (labeled_image->details->label != NULL((void*)0))
517 {
518 (* callback) (labeled_image->details->label, callback_data);
519 }
520 }
521}
522
523/* Class init methods */
524static void
525eel_labeled_image_class_init (EelLabeledImageClass *labeled_image_class)
526{
527 GObjectClass *gobject_class = G_OBJECT_CLASS (labeled_image_class)((((GObjectClass*) (void *) ((labeled_image_class)))));
528 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (labeled_image_class)((((GtkWidgetClass*) (void *) ((labeled_image_class)))));
529 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (labeled_image_class)((((GtkContainerClass*) (void *) ((labeled_image_class)))));
530 GtkBindingSet *binding_set;
531
532 /* GObjectClass */
533 gobject_class->set_property = eel_labeled_image_set_property;
534 gobject_class->get_property = eel_labeled_image_get_property;
535
536 widget_class->destroy = eel_labeled_image_destroy;
537
538
539 /* GtkWidgetClass */
540 widget_class->size_allocate = eel_labeled_image_size_allocate;
541 widget_class->get_preferred_width = eel_labeled_image_get_preferred_width;
542 widget_class->get_preferred_height = eel_labeled_image_get_preferred_height;
543 widget_class->draw = eel_labeled_image_draw;
544
545 widget_class->map = eel_labeled_image_map;
546 widget_class->unmap = eel_labeled_image_unmap;
547
548 gtk_widget_class_set_accessible_type (widget_class, eel_labeled_image_accessible_get_type ());
549
550
551 /* GtkContainerClass */
552 container_class->add = eel_labeled_image_add;
553 container_class->remove = eel_labeled_image_remove;
554 container_class->forall = eel_labeled_image_forall;
555
556 labeled_image_signals[ACTIVATE] =
557 g_signal_new ("activate",
558 G_TYPE_FROM_CLASS (labeled_image_class)(((GTypeClass*) (labeled_image_class))->g_type),
559 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
560 G_STRUCT_OFFSET (EelLabeledImageClass,((glong) __builtin_offsetof(EelLabeledImageClass, activate))
561 activate)((glong) __builtin_offsetof(EelLabeledImageClass, activate)),
562 NULL((void*)0), NULL((void*)0),
563 g_cclosure_marshal_VOID__VOID,
564 G_TYPE_NONE((GType) ((1) << (2))), 0);
565 widget_class->activate_signal = labeled_image_signals[ACTIVATE];
566
567 binding_set = gtk_binding_set_by_class (gobject_class);
568
569 gtk_binding_entry_add_signal (binding_set,
570 GDK_KEY_Return0xff0d, 0,
571 "activate", 0);
572 gtk_binding_entry_add_signal (binding_set,
573 GDK_KEY_KP_Enter0xff8d, 0,
574 "activate", 0);
575 gtk_binding_entry_add_signal (binding_set,
576 GDK_KEY_space0x020, 0,
577 "activate", 0);
578
579
580 /* Properties */
581 g_object_class_install_property (
582 gobject_class,
583 PROP_PIXBUF,
584 g_param_spec_object ("pixbuf", NULL((void*)0), NULL((void*)0),
585 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ()), G_PARAM_READWRITE));
586
587 g_object_class_install_property (
588 gobject_class,
589 PROP_LABEL,
590 g_param_spec_string ("label", NULL((void*)0), NULL((void*)0),
591 "", G_PARAM_READWRITE));
592
593
594 g_object_class_install_property (
595 gobject_class,
596 PROP_LABEL_POSITION,
597 g_param_spec_enum ("label_position", NULL((void*)0), NULL((void*)0),
598 GTK_TYPE_POSITION_TYPE(gtk_position_type_get_type ()),
599 GTK_POS_BOTTOM,
600 G_PARAM_READWRITE));
601
602 g_object_class_install_property (
603 gobject_class,
604 PROP_SHOW_LABEL,
605 g_param_spec_boolean ("show_label", NULL((void*)0), NULL((void*)0),
606 TRUE(!(0)), G_PARAM_READWRITE));
607
608 g_object_class_install_property (
609 gobject_class,
610 PROP_SHOW_IMAGE,
611 g_param_spec_boolean ("show_image", NULL((void*)0), NULL((void*)0),
612 TRUE(!(0)), G_PARAM_READWRITE));
613
614
615 g_object_class_install_property (
616 gobject_class,
617 PROP_SPACING,
618 g_param_spec_uint ("spacing", NULL((void*)0), NULL((void*)0),
619 0,
620 G_MAXINT2147483647,
621 DEFAULT_SPACING0,
622 G_PARAM_READWRITE));
623
624 g_object_class_install_property (
625 gobject_class,
626 PROP_X_PADDING,
627 g_param_spec_int ("x_padding", NULL((void*)0), NULL((void*)0),
628 0,
629 G_MAXINT2147483647,
630 DEFAULT_X_PADDING0,
631 G_PARAM_READWRITE));
632
633 g_object_class_install_property (
634 gobject_class,
635 PROP_Y_PADDING,
636 g_param_spec_int ("y_padding", NULL((void*)0), NULL((void*)0),
637 0,
638 G_MAXINT2147483647,
639 DEFAULT_Y_PADDING0,
640 G_PARAM_READWRITE));
641
642 g_object_class_install_property (
643 gobject_class,
644 PROP_X_ALIGNMENT,
645 g_param_spec_float ("x_alignment", NULL((void*)0), NULL((void*)0),
646 0.0,
647 1.0,
648 DEFAULT_X_ALIGNMENT0.5,
649 G_PARAM_READWRITE));
650
651 g_object_class_install_property (
652 gobject_class,
653 PROP_Y_ALIGNMENT,
654 g_param_spec_float ("y_alignment", NULL((void*)0), NULL((void*)0),
655 0.0,
656 1.0,
657 DEFAULT_Y_ALIGNMENT0.5,
658 G_PARAM_READWRITE));
659
660 g_object_class_install_property (
661 gobject_class,
662 PROP_FILL,
663 g_param_spec_boolean ("fill", NULL((void*)0), NULL((void*)0),
664 FALSE(0),
665 G_PARAM_READWRITE));
666
667}
668
669/* Private EelLabeledImage methods */
670static gboolean
671is_fixed_height (const EelLabeledImage *labeled_image)
672{
673 return labeled_image->details->fixed_image_height > 0;
674}
675
676static EelDimensions
677labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image)
678{
679 EelDimensions image_dimensions;
680 GtkRequisition image_requisition;
681
682 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_151 = 1; else _g_boolean_var_151 =
0; _g_boolean_var_151; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 682, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
683
684 if (!labeled_image_show_image (labeled_image))
685 {
686 return eel_dimensions_empty;
687 }
688
689 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
690
691 image_dimensions.width = (int) image_requisition.width;
692 image_dimensions.height = (int) image_requisition.height;
693
694 if (is_fixed_height (labeled_image))
695 {
696 image_dimensions.height = labeled_image->details->fixed_image_height;
697 }
698
699 return image_dimensions;
700}
701
702static EelDimensions
703labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image)
704{
705 EelDimensions label_dimensions;
706 GtkRequisition label_requisition;
707
708 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_152 = 1; else _g_boolean_var_152 =
0; _g_boolean_var_152; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 708, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
709
710 if (!labeled_image_show_label (labeled_image))
711 {
712 return eel_dimensions_empty;
713 }
714
715 gtk_widget_get_preferred_size (labeled_image->details->label, &label_requisition, NULL((void*)0));
716
717 label_dimensions.width = (int) label_requisition.width;
718 label_dimensions.height = (int) label_requisition.height;
719
720 return label_dimensions;
721}
722
723static EelIRect
724labeled_image_get_image_bounds_fill (const EelLabeledImage *labeled_image)
725{
726 EelIRect image_bounds;
727 EelDimensions image_dimensions;
728 EelIRect content_bounds;
729 EelIRect bounds;
730
731 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_153 = 1; else _g_boolean_var_153 =
0; _g_boolean_var_153; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 731, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
732
733 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
734
735 if (eel_dimensions_are_empty (image_dimensions))
736 {
737 return eel_irect_empty;
738 }
739
740 content_bounds = labeled_image_get_content_bounds (labeled_image);
741 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
742
743 if (!labeled_image_show_label (labeled_image))
744 {
745 image_bounds = bounds;
746 }
747 else
748 {
749 switch (labeled_image->details->label_position)
750 {
751 case GTK_POS_LEFT:
752 image_bounds.y0 = bounds.y0;
753 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
754 image_bounds.y1 = bounds.y1;
755 image_bounds.x1 = bounds.x1;
756 break;
757
758 case GTK_POS_RIGHT:
759 image_bounds.y0 = bounds.y0;
760 image_bounds.x0 = bounds.x0;
761 image_bounds.y1 = bounds.y1;
762 image_bounds.x1 = content_bounds.x0 + image_dimensions.width;
763 break;
764
765 case GTK_POS_TOP:
766 image_bounds.x0 = bounds.x0;
767 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
768 image_bounds.x1 = bounds.x1;
769 image_bounds.y1 = bounds.y1;
770 break;
771
772 case GTK_POS_BOTTOM:
773 image_bounds.x0 = bounds.x0;
774 image_bounds.y0 = bounds.y0;
775 image_bounds.x1 = bounds.x1;
776 image_bounds.y1 = content_bounds.y0 + image_dimensions.height;
777 break;
778
779 default:
780 image_bounds.x0 = 0;
781 image_bounds.y0 = 0;
782 image_bounds.x1 = 0;
783 image_bounds.y1 = 0;
784 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 784
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
785 }
786 }
787
788 return image_bounds;
789}
790
791EelIRect
792eel_labeled_image_get_image_bounds (const EelLabeledImage *labeled_image)
793{
794 EelDimensions image_dimensions;
795 EelDimensions label_dimensions;
796 GtkRequisition image_requisition;
797 EelIRect image_bounds;
798 EelIRect content_bounds;
799
800 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
801
802 if (labeled_image->details->fill)
803 {
804 return labeled_image_get_image_bounds_fill (labeled_image);
805 }
806
807 /* get true real dimensions if we're in fixed height mode */
808 if (is_fixed_height (labeled_image) && labeled_image_show_image (labeled_image))
809 {
810 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
811 image_dimensions.width = (int) image_requisition.width;
812 image_dimensions.height = (int) image_requisition.height;
813 }
814 else
815 {
816 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
817 }
818
819 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
820
821 if (eel_dimensions_are_empty (image_dimensions))
822 {
823 return eel_irect_empty;
824 }
825
826 content_bounds = labeled_image_get_content_bounds (labeled_image);
827
828 if (!labeled_image_show_label (labeled_image))
829 {
830 image_bounds.x0 =
831 content_bounds.x0 +
832 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
833 image_bounds.y0 =
834 content_bounds.y0 +
835 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
836 }
837 else
838 {
839 switch (labeled_image->details->label_position)
840 {
841 case GTK_POS_LEFT:
842 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
843 image_bounds.y0 =
844 content_bounds.y0 +
845 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
846 break;
847
848 case GTK_POS_RIGHT:
849 image_bounds.x0 = content_bounds.x0;
850 image_bounds.y0 =
851 content_bounds.y0 +
852 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
853 break;
854
855 case GTK_POS_TOP:
856 image_bounds.x0 =
857 content_bounds.x0 +
858 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
859 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
860 break;
861
862 case GTK_POS_BOTTOM:
863 image_bounds.x0 =
864 content_bounds.x0 +
865 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
866
867 if (is_fixed_height (labeled_image))
868 {
869 image_bounds.y0 = content_bounds.y0 + eel_irect_get_height (content_bounds)
870 - image_dimensions.height
871 - label_dimensions.height
872 - labeled_image->details->spacing;
873 }
874 else
875 {
876 image_bounds.y0 = content_bounds.y0;
877 }
878
879 break;
880
881 default:
882 image_bounds.x0 = 0;
883 image_bounds.y0 = 0;
884 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 884
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
885 }
886 }
887
888 image_bounds.x1 = image_bounds.x0 + image_dimensions.width;
889 image_bounds.y1 = image_bounds.y0 + image_dimensions.height;
890
891 return image_bounds;
892}
893
894static EelIRect
895labeled_image_get_label_bounds_fill (const EelLabeledImage *labeled_image)
896{
897 EelIRect label_bounds;
898 EelDimensions label_dimensions;
899 EelIRect content_bounds;
900 EelIRect bounds;
901
902 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 902, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
903
904 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
905
906 if (eel_dimensions_are_empty (label_dimensions))
907 {
908 return eel_irect_empty;
909 }
910
911 content_bounds = labeled_image_get_content_bounds (labeled_image);
912 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
913
914 /* Only the label is shown */
915 if (!labeled_image_show_image (labeled_image))
916 {
917 label_bounds = bounds;
918 /* Both label and image are shown */
919 }
920 else
921 {
922 switch (labeled_image->details->label_position)
923 {
924 case GTK_POS_LEFT:
925 label_bounds.y0 = bounds.y0;
926 label_bounds.x0 = bounds.x0;
927 label_bounds.y1 = bounds.y1;
928 label_bounds.x1 = content_bounds.x0 + label_dimensions.width;
929 break;
930
931 case GTK_POS_RIGHT:
932 label_bounds.y0 = bounds.y0;
933 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
934 label_bounds.y1 = bounds.y1;
935 label_bounds.x1 = bounds.x1;
936 break;
937
938 case GTK_POS_TOP:
939 label_bounds.x0 = bounds.x0;
940 label_bounds.y0 = bounds.y0;
941 label_bounds.x1 = bounds.x1;
942 label_bounds.y1 = content_bounds.y0 + label_dimensions.height;
943 break;
944
945 case GTK_POS_BOTTOM:
946 label_bounds.x0 = bounds.x0;
947 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
948 label_bounds.x1 = bounds.x1;
949 label_bounds.y1 = bounds.y1;
950 break;
951
952 default:
953 label_bounds.x0 = 0;
954 label_bounds.y0 = 0;
955 label_bounds.x1 = 0;
956 label_bounds.y1 = 0;
957 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 957
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
958 }
959 }
960
961 return label_bounds;
962}
963
964EelIRect
965eel_labeled_image_get_label_bounds (const EelLabeledImage *labeled_image)
966{
967 EelIRect label_bounds;
968 EelDimensions label_dimensions;
969 EelIRect content_bounds;
970
971 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
972
973 if (labeled_image->details->fill)
974 {
975 return labeled_image_get_label_bounds_fill (labeled_image);
976 }
977
978 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
979
980 if (eel_dimensions_are_empty (label_dimensions))
981 {
982 return eel_irect_empty;
983 }
984
985 content_bounds = labeled_image_get_content_bounds (labeled_image);
986
987 /* Only the label is shown */
988 if (!labeled_image_show_image (labeled_image))
989 {
990 label_bounds.x0 =
991 content_bounds.x0 +
992 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
993 label_bounds.y0 =
994 content_bounds.y0 +
995 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
996 /* Both label and image are shown */
997 }
998 else
999 {
1000 switch (labeled_image->details->label_position)
1001 {
1002 case GTK_POS_LEFT:
1003 label_bounds.x0 = content_bounds.x0;
1004 label_bounds.y0 =
1005 content_bounds.y0 +
1006 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1007 break;
1008
1009 case GTK_POS_RIGHT:
1010 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
1011 label_bounds.y0 =
1012 content_bounds.y0 +
1013 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1014 break;
1015
1016 case GTK_POS_TOP:
1017 label_bounds.x0 =
1018 content_bounds.x0 +
1019 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1020 label_bounds.y0 = content_bounds.y0;
1021 break;
1022
1023 case GTK_POS_BOTTOM:
1024 label_bounds.x0 =
1025 content_bounds.x0 +
1026 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1027 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
1028 break;
1029
1030 default:
1031 label_bounds.x0 = 0;
1032 label_bounds.y0 = 0;
1033 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 1033
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1034 }
1035 }
1036
1037 label_bounds.x1 = label_bounds.x0 + label_dimensions.width;
1038 label_bounds.y1 = label_bounds.y0 + label_dimensions.height;
1039
1040 return label_bounds;
1041}
1042
1043static void
1044labeled_image_update_alignments (EelLabeledImage *labeled_image)
1045{
1046
1047 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1047, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1048
1049 if (labeled_image->details->label != NULL((void*)0))
1050 {
1051 if (labeled_image->details->fill)
1052 {
1053 float x_alignment;
1054 float y_alignment;
1055
1056 x_alignment = gtk_label_get_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
1057 y_alignment = gtk_label_get_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
)
;
Value stored to 'y_alignment' is never read
1058
1059 /* Only the label is shown */
1060 if (!labeled_image_show_image (labeled_image))
1061 {
1062 x_alignment = 0.5;
1063 y_alignment = 0.5;
1064 /* Both label and image are shown */
1065 }
1066 else
1067 {
1068 switch (labeled_image->details->label_position)
1069 {
1070 case GTK_POS_LEFT:
1071 x_alignment = 1.0;
1072 y_alignment = 0.5;
1073 break;
1074
1075 case GTK_POS_RIGHT:
1076 x_alignment = 0.0;
1077 y_alignment = 0.5;
1078 break;
1079
1080 case GTK_POS_TOP:
1081 x_alignment = 0.5;
1082 y_alignment = 1.0;
1083 break;
1084
1085 case GTK_POS_BOTTOM:
1086 x_alignment = 0.5;
1087 y_alignment = 0.0;
1088 break;
1089 }
1090
1091 }
1092
1093 gtk_label_set_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, x_alignment);
1094 gtk_label_set_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, y_alignment);
1095 }
1096 }
1097
1098 if (labeled_image->details->image != NULL((void*)0))
1099 {
1100 if (labeled_image->details->fill)
1101 {
1102 float x_alignment;
1103 float y_alignment;
1104
1105 x_alignment = gtk_widget_get_halign (labeled_image->details->image);
1106 y_alignment = gtk_widget_get_valign (labeled_image->details->image);
1107
1108 /* Only the image is shown */
1109 if (!labeled_image_show_label (labeled_image))
1110 {
1111 x_alignment = 0.5;
1112 y_alignment = 0.5;
1113 /* Both label and image are shown */
1114 }
1115 else
1116 {
1117 switch (labeled_image->details->label_position)
1118 {
1119 case GTK_POS_LEFT:
1120 x_alignment = 0.0;
1121 y_alignment = 0.5;
1122 break;
1123
1124 case GTK_POS_RIGHT:
1125 x_alignment = 1.0;
1126 y_alignment = 0.5;
1127 break;
1128
1129 case GTK_POS_TOP:
1130 x_alignment = 0.5;
1131 y_alignment = 0.0;
1132 break;
1133
1134 case GTK_POS_BOTTOM:
1135 x_alignment = 0.5;
1136 y_alignment = 1.0;
1137 break;
1138 }
1139 }
1140
1141 gtk_widget_set_halign (labeled_image->details->image, x_alignment);
1142 gtk_widget_set_valign (labeled_image->details->image, y_alignment);
1143 }
1144 }
1145}
1146
1147static EelDimensions
1148labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image)
1149{
1150 EelDimensions image_dimensions;
1151 EelDimensions label_dimensions;
1152 EelDimensions content_dimensions;
1153
1154 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1154, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1155
1156 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
1157 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
1158
1159 content_dimensions = eel_dimensions_empty;
1160
1161 /* Both shown */
1162 if (!eel_dimensions_are_empty (image_dimensions) && !eel_dimensions_are_empty (label_dimensions))
1163 {
1164 content_dimensions.width =
1165 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1166 switch (labeled_image->details->label_position)
1167 {
1168 case GTK_POS_LEFT:
1169 case GTK_POS_RIGHT:
1170 content_dimensions.width =
1171 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1172 content_dimensions.height = MAX (image_dimensions.height, label_dimensions.height)(((image_dimensions.height) > (label_dimensions.height)) ?
(image_dimensions.height) : (label_dimensions.height))
;
1173 break;
1174
1175 case GTK_POS_TOP:
1176 case GTK_POS_BOTTOM:
1177 content_dimensions.width = MAX (image_dimensions.width, label_dimensions.width)(((image_dimensions.width) > (label_dimensions.width)) ? (
image_dimensions.width) : (label_dimensions.width))
;
1178 content_dimensions.height =
1179 image_dimensions.height + labeled_image->details->spacing + label_dimensions.height;
1180 break;
1181 }
1182 /* Only image shown */
1183 }
1184 else if (!eel_dimensions_are_empty (image_dimensions))
1185 {
1186 content_dimensions.width = image_dimensions.width;
1187 content_dimensions.height = image_dimensions.height;
1188 /* Only label shown */
1189 }
1190 else
1191 {
1192 content_dimensions.width = label_dimensions.width;
1193 content_dimensions.height = label_dimensions.height;
1194 }
1195
1196 return content_dimensions;
1197}
1198
1199static EelIRect
1200labeled_image_get_content_bounds (const EelLabeledImage *labeled_image)
1201{
1202 EelDimensions content_dimensions;
1203 EelIRect content_bounds;
1204 EelIRect bounds;
1205
1206 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1206, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1207
1208 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1209
1210 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
1211 content_bounds = eel_irect_align (bounds,
1212 content_dimensions.width,
1213 content_dimensions.height,
1214 labeled_image->details->x_alignment,
1215 labeled_image->details->y_alignment);
1216
1217 return content_bounds;
1218}
1219
1220static void
1221labeled_image_ensure_label (EelLabeledImage *labeled_image)
1222{
1223 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_160 = 1; else _g_boolean_var_160 =
0; _g_boolean_var_160; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1223, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1224
1225 if (labeled_image->details->label != NULL((void*)0))
1226 {
1227 return;
1228 }
1229
1230 labeled_image->details->label = gtk_label_new (NULL((void*)0));
1231 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->label);
1232 gtk_widget_show (labeled_image->details->label);
1233}
1234
1235static void
1236labeled_image_ensure_image (EelLabeledImage *labeled_image)
1237{
1238 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_161 = 1; else _g_boolean_var_161 =
0; _g_boolean_var_161; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1238, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1239
1240 if (labeled_image->details->image != NULL((void*)0))
1241 {
1242 return;
1243 }
1244
1245 labeled_image->details->image = gtk_image_new ();
1246 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->image);
1247 gtk_widget_show (labeled_image->details->image);
1248}
1249
1250static gboolean
1251labeled_image_show_image (const EelLabeledImage *labeled_image)
1252{
1253 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1253, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1254
1255 return labeled_image->details->image != NULL((void*)0) && labeled_image->details->show_image;
1256}
1257
1258static gboolean
1259labeled_image_show_label (const EelLabeledImage *labeled_image)
1260{
1261 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_163 = 1; else _g_boolean_var_163 =
0; _g_boolean_var_163; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1261, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1262
1263 return labeled_image->details->label != NULL((void*)0) && labeled_image->details->show_label;
1264}
1265
1266/**
1267 * eel_labeled_image_new:
1268 * @text: Text to use for label or NULL.
1269 * @pixbuf: Pixbuf to use for image or NULL.
1270 *
1271 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1272 * NULL then the LabeledImage will show a label. If the &pixbuf parameter is not
1273 * NULL then the LabeledImage will show a pixbuf. Either of these can be NULL at
1274 * creation time.
1275 *
1276 * Later in the lifetime of the widget you can invoke methods that affect the
1277 * label and/or the image. If at creation time these were NULL, then they will
1278 * be created as neeeded.
1279 *
1280 * Thus, using this widget in place of EelImage or EelLabel is "free" with
1281 * only the GtkWidget and function call overhead.
1282 *
1283 */
1284GtkWidget*
1285eel_labeled_image_new (const char *text,
1286 GdkPixbuf *pixbuf)
1287{
1288 EelLabeledImage *labeled_image;
1289
1290 labeled_image = EEL_LABELED_IMAGE (gtk_widget_new (eel_labeled_image_get_type (), NULL))((((EelLabeledImage*) (void *) ((gtk_widget_new (eel_labeled_image_get_type
(), ((void*)0)))))))
;
1291
1292 if (text != NULL((void*)0))
1293 {
1294 eel_labeled_image_set_text (labeled_image, text);
1295 }
1296
1297 if (pixbuf != NULL((void*)0))
1298 {
1299 eel_labeled_image_set_pixbuf (labeled_image, pixbuf);
1300 }
1301
1302 labeled_image_update_alignments (labeled_image);
1303
1304 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1305}
1306
1307/**
1308 * eel_labeled_image_new_from_file_name:
1309 * @text: Text to use for label or NULL.
1310 * @file_name: File name of picture to use for pixbuf. Cannot be NULL.
1311 *
1312 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1313 * NULL then the LabeledImage will show a label.
1314 *
1315 */
1316GtkWidget*
1317eel_labeled_image_new_from_file_name (const char *text,
1318 const char *pixbuf_file_name)
1319{
1320 EelLabeledImage *labeled_image;
1321
1322 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_164 = 1;
else _g_boolean_var_164 = 0; _g_boolean_var_164; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1323
1324 labeled_image = EEL_LABELED_IMAGE (eel_labeled_image_new (text, NULL))((((EelLabeledImage*) (void *) ((eel_labeled_image_new (text,
((void*)0)))))))
;
1325 eel_labeled_image_set_pixbuf_from_file_name (labeled_image, pixbuf_file_name);
1326 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1327}
1328
1329/**
1330 * eel_labeled_image_set_label_position:
1331 * @labeled_image: A EelLabeledImage.
1332 * @label_position: The position of the label with respect to the image.
1333 *
1334 * Set the position of the label with respect to the image as follows:
1335 *
1336 * GTK_POS_LEFT:
1337 * [ <label> <image> ]
1338 *
1339 * GTK_POS_RIGHT:
1340 * [ <image> <label> ]
1341 *
1342 * GTK_POS_TOP:
1343 * [ <label> ]
1344 * [ <image> ]
1345 *
1346 * GTK_POS_BOTTOM:
1347 * [ <image> ]
1348 * [ <label> ]
1349 *
1350 */
1351void
1352eel_labeled_image_set_label_position (EelLabeledImage *labeled_image,
1353 GtkPositionType label_position)
1354{
1355 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1356 g_return_if_fail (label_position >= GTK_POS_LEFT)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if (label_position >= GTK_POS_LEFT) _g_boolean_var_166 =
1; else _g_boolean_var_166 = 0; _g_boolean_var_166; }), 1)))
{ } else { g_return_if_fail_warning ("Eel", ((const char*) (
__func__)), "label_position >= GTK_POS_LEFT"); return; } }
while (0)
;
1357 g_return_if_fail (label_position <= GTK_POS_BOTTOM)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if (label_position <= GTK_POS_BOTTOM) _g_boolean_var_167
= 1; else _g_boolean_var_167 = 0; _g_boolean_var_167; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "label_position <= GTK_POS_BOTTOM"); return;
} } while (0)
;
1358
1359 if (labeled_image->details->label_position == label_position)
1360 {
1361 return;
1362 }
1363
1364 labeled_image->details->label_position = label_position;
1365
1366 labeled_image_update_alignments (labeled_image);
1367
1368 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1369}
1370
1371/**
1372 * eel_labeled_image_get_label_postiion:
1373 * @labeled_image: A EelLabeledImage.
1374 *
1375 * Returns an enumeration indicating the position of the label with respect to the image.
1376 */
1377GtkPositionType
1378eel_labeled_image_get_label_position (const EelLabeledImage *labeled_image)
1379{
1380 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1381
1382 return labeled_image->details->label_position;
1383}
1384
1385/**
1386 * eel_labeled_image_set_show_label:
1387 * @labeled_image: A EelLabeledImage.
1388 * @show_image: A boolean value indicating whether the label should be shown.
1389 *
1390 * Update the labeled image to either show or hide the internal label widget.
1391 * This function doesnt have any effect if the LabeledImage doesnt already
1392 * contain an label.
1393 */
1394void
1395eel_labeled_image_set_show_label (EelLabeledImage *labeled_image,
1396 gboolean show_label)
1397{
1398 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_169 = 1; else _g_boolean_var_169 =
0; _g_boolean_var_169; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1399
1400 if (labeled_image->details->show_label == show_label)
1401 {
1402 return;
1403 }
1404
1405 labeled_image->details->show_label = show_label;
1406
1407 if (labeled_image->details->label != NULL((void*)0))
1408 {
1409 if (labeled_image->details->show_label)
1410 {
1411 gtk_widget_show (labeled_image->details->label);
1412 }
1413 else
1414 {
1415 gtk_widget_hide (labeled_image->details->label);
1416 }
1417 }
1418
1419 labeled_image_update_alignments (labeled_image);
1420
1421 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1422}
1423
1424/**
1425 * eel_labeled_image_get_show_label:
1426 * @labeled_image: A EelLabeledImage.
1427 *
1428 * Returns a boolean value indicating whether the internal label is shown.
1429 */
1430gboolean
1431eel_labeled_image_get_show_label (const EelLabeledImage *labeled_image)
1432{
1433 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_170 = 1; else _g_boolean_var_170 =
0; _g_boolean_var_170; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1434
1435 return labeled_image->details->show_label;
1436}
1437
1438/**
1439 * eel_labeled_image_set_show_image:
1440 * @labeled_image: A EelLabeledImage.
1441 * @show_image: A boolean value indicating whether the image should be shown.
1442 *
1443 * Update the labeled image to either show or hide the internal image widget.
1444 * This function doesnt have any effect if the LabeledImage doesnt already
1445 * contain an image.
1446 */
1447void
1448eel_labeled_image_set_show_image (EelLabeledImage *labeled_image,
1449 gboolean show_image)
1450{
1451 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_171 = 1; else _g_boolean_var_171 =
0; _g_boolean_var_171; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1452
1453 if (labeled_image->details->show_image == show_image)
1454 {
1455 return;
1456 }
1457
1458 labeled_image->details->show_image = show_image;
1459
1460 if (labeled_image->details->image != NULL((void*)0))
1461 {
1462 if (labeled_image->details->show_image)
1463 {
1464 gtk_widget_show (labeled_image->details->image);
1465 }
1466 else
1467 {
1468 gtk_widget_hide (labeled_image->details->image);
1469 }
1470 }
1471
1472 labeled_image_update_alignments (labeled_image);
1473
1474 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1475}
1476
1477/**
1478 * eel_labeled_image_get_show_image:
1479 * @labeled_image: A EelLabeledImage.
1480 *
1481 * Returns a boolean value indicating whether the internal image is shown.
1482 */
1483gboolean
1484eel_labeled_image_get_show_image (const EelLabeledImage *labeled_image)
1485{
1486 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1487
1488 return labeled_image->details->show_image;
1489}
1490
1491
1492/**
1493 * eel_labeled_image_set_fixed_image_height:
1494 * @labeled_image: A EelLabeledImage.
1495 * @fixed_image_height: The new fixed image height.
1496 *
1497 * Normally, we measure the height of images, but it's sometimes useful
1498 * to use a fixed height for all the images. This routine sets the
1499 * image height to the passed in value
1500 *
1501 */
1502void
1503eel_labeled_image_set_fixed_image_height (EelLabeledImage *labeled_image,
1504 int new_height)
1505{
1506 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1507
1508 if (labeled_image->details->fixed_image_height == new_height)
1509 {
1510 return;
1511 }
1512
1513 labeled_image->details->fixed_image_height = new_height;
1514
1515 labeled_image_update_alignments (labeled_image);
1516
1517 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1518}
1519
1520/**
1521 * eel_labeled_image_set_selected:
1522 * @labeled_image: A EelLabeledImage.
1523 * @selected: A boolean value indicating whether the labeled image
1524 * should be selected.
1525 *
1526 * Selects or deselects the labeled image.
1527 *
1528 */
1529void
1530eel_labeled_image_set_selected (EelLabeledImage *labeled_image,
1531 gboolean selected)
1532{
1533 GtkStateFlags state;
1534 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_174 = 1; else _g_boolean_var_174 =
0; _g_boolean_var_174; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1535
1536 state = selected ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_NORMAL;
1537
1538 gtk_widget_set_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), state, TRUE(!(0)));
1539 gtk_widget_set_state_flags (labeled_image->details->image, state, TRUE(!(0)));
1540 gtk_widget_set_state_flags (labeled_image->details->label, state, TRUE(!(0)));
1541
1542}
1543
1544/**
1545 * eel_labeled_image_get_selected:
1546 * @labeled_image: A EelLabeledImage.
1547 *
1548 * Returns the selected state of the labeled image.
1549 *
1550 */
1551gboolean
1552eel_labeled_image_get_selected (EelLabeledImage *labeled_image)
1553{
1554 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_175 = 1; else _g_boolean_var_175 =
0; _g_boolean_var_175; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return ((0)); } } while (0)
;
1555
1556 return gtk_widget_get_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))))) == GTK_STATE_FLAG_SELECTED;
1557}
1558
1559/**
1560 * eel_labeled_image_set_spacing:
1561 * @labeled_image: A EelLabeledImage.
1562 * @spacing: The new spacing between label and image.
1563 *
1564 * Set the spacing between label and image. This will only affect
1565 * the geometry of the widget if both a label and image are currently
1566 * visible.
1567 *
1568 */
1569void
1570eel_labeled_image_set_spacing (EelLabeledImage *labeled_image,
1571 guint spacing)
1572{
1573 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1574
1575 if (labeled_image->details->spacing == spacing)
1576 {
1577 return;
1578 }
1579
1580 labeled_image->details->spacing = spacing;
1581
1582 labeled_image_update_alignments (labeled_image);
1583
1584 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1585}
1586
1587/**
1588 * eel_labeled_image_get_spacing:
1589 * @labeled_image: A EelLabeledImage.
1590 *
1591 * Returns: The spacing between the label and image.
1592 */
1593guint
1594eel_labeled_image_get_spacing (const EelLabeledImage *labeled_image)
1595{
1596 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_177 = 1; else _g_boolean_var_177 =
0; _g_boolean_var_177; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1597
1598 return labeled_image->details->spacing;
1599}
1600
1601/**
1602 * eel_labeled_image_set_x_padding:
1603 * @labeled_image: A EelLabeledImage.
1604 * @x_padding: The new horizontal padding.
1605 *
1606 * Set horizontal padding for the EelLabeledImage. The padding
1607 * attribute work just like that in GtkMisc.
1608 */
1609void
1610eel_labeled_image_set_x_padding (EelLabeledImage *labeled_image,
1611 int x_padding)
1612{
1613 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_178 = 1; else _g_boolean_var_178 =
0; _g_boolean_var_178; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1614
1615 x_padding = MAX (0, x_padding)(((0) > (x_padding)) ? (0) : (x_padding));
1616
1617 if (labeled_image->details->x_padding == x_padding)
1618 {
1619 return;
1620 }
1621
1622 labeled_image->details->x_padding = x_padding;
1623 labeled_image_update_alignments (labeled_image);
1624 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1625}
1626
1627/**
1628 * eel_labeled_image_get_x_padding:
1629 * @labeled_image: A EelLabeledImage.
1630 *
1631 * Returns: The horizontal padding for the LabeledImage's content.
1632 */
1633int
1634eel_labeled_image_get_x_padding (const EelLabeledImage *labeled_image)
1635{
1636 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_179 = 1; else _g_boolean_var_179 =
0; _g_boolean_var_179; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1637
1638 return labeled_image->details->x_padding;
1639}
1640
1641/**
1642 * eel_labeled_image_set_y_padding:
1643 * @labeled_image: A EelLabeledImage.
1644 * @x_padding: The new vertical padding.
1645 *
1646 * Set vertical padding for the EelLabeledImage. The padding
1647 * attribute work just like that in GtkMisc.
1648 */
1649void
1650eel_labeled_image_set_y_padding (EelLabeledImage *labeled_image,
1651 int y_padding)
1652{
1653 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_180 = 1; else _g_boolean_var_180 =
0; _g_boolean_var_180; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1654
1655 y_padding = MAX (0, y_padding)(((0) > (y_padding)) ? (0) : (y_padding));
1656
1657 if (labeled_image->details->y_padding == y_padding)
1658 {
1659 return;
1660 }
1661
1662 labeled_image->details->y_padding = y_padding;
1663 labeled_image_update_alignments (labeled_image);
1664 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1665}
1666
1667/**
1668 * eel_labeled_image_get_x_padding:
1669 * @labeled_image: A EelLabeledImage.
1670 *
1671 * Returns: The vertical padding for the LabeledImage's content.
1672 */
1673int
1674eel_labeled_image_get_y_padding (const EelLabeledImage *labeled_image)
1675{
1676 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1677
1678 return labeled_image->details->y_padding;
1679}
1680
1681/**
1682 * eel_labeled_image_set_x_alignment:
1683 * @labeled_image: A EelLabeledImage.
1684 * @x_alignment: The new horizontal alignment.
1685 *
1686 * Set horizontal alignment for the EelLabeledImage's content.
1687 * The 'content' is the union of the image and label. The alignment
1688 * attribute work just like that in GtkMisc.
1689 */
1690void
1691eel_labeled_image_set_x_alignment (EelLabeledImage *labeled_image,
1692 float x_alignment)
1693{
1694 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_182 = 1; else _g_boolean_var_182 =
0; _g_boolean_var_182; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1695
1696 x_alignment = MAX (0, x_alignment)(((0) > (x_alignment)) ? (0) : (x_alignment));
1697 x_alignment = MIN (1.0, x_alignment)(((1.0) < (x_alignment)) ? (1.0) : (x_alignment));
1698
1699 if (labeled_image->details->x_alignment == x_alignment)
1700 {
1701 return;
1702 }
1703
1704 labeled_image->details->x_alignment = x_alignment;
1705 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1706}
1707
1708/**
1709 * eel_labeled_image_get_x_alignment:
1710 * @labeled_image: A EelLabeledImage.
1711 *
1712 * Returns: The horizontal alignment for the LabeledImage's content.
1713 */
1714float
1715eel_labeled_image_get_x_alignment (const EelLabeledImage *labeled_image)
1716{
1717 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_183 = 1; else _g_boolean_var_183 =
0; _g_boolean_var_183; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1718
1719 return labeled_image->details->x_alignment;
1720}
1721
1722/**
1723 * eel_labeled_image_set_y_alignment:
1724 * @labeled_image: A EelLabeledImage.
1725 * @y_alignment: The new vertical alignment.
1726 *
1727 * Set vertical alignment for the EelLabeledImage's content.
1728 * The 'content' is the union of the image and label. The alignment
1729 * attribute work just like that in GtkMisc.
1730 */
1731void
1732eel_labeled_image_set_y_alignment (EelLabeledImage *labeled_image,
1733 float y_alignment)
1734{
1735 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_184 = 1; else _g_boolean_var_184 =
0; _g_boolean_var_184; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1736
1737 y_alignment = MAX (0, y_alignment)(((0) > (y_alignment)) ? (0) : (y_alignment));
1738 y_alignment = MIN (1.0, y_alignment)(((1.0) < (y_alignment)) ? (1.0) : (y_alignment));
1739
1740 if (labeled_image->details->y_alignment == y_alignment)
1741 {
1742 return;
1743 }
1744
1745 labeled_image->details->y_alignment = y_alignment;
1746 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1747}
1748
1749/**
1750 * eel_labeled_image_get_y_alignment:
1751 * @labeled_image: A EelLabeledImage.
1752 *
1753 * Returns: The vertical alignment for the LabeledImage's content.
1754 */
1755float
1756eel_labeled_image_get_y_alignment (const EelLabeledImage *labeled_image)
1757{
1758 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_185 = 1; else _g_boolean_var_185 =
0; _g_boolean_var_185; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1759
1760 return labeled_image->details->y_alignment;
1761}
1762
1763/**
1764 * eel_labeled_image_set_fill:
1765 * @labeled_image: A EelLabeledImage.
1766 * @fill: A boolean value indicating whether the internal image and label
1767 * widgets should fill all the available allocation.
1768 *
1769 * By default the internal image and label wigets are sized to their natural
1770 * preferred geometry. You can use the 'fill' attribute of LabeledImage
1771 * to have the internal widgets fill as much of the LabeledImage allocation
1772 * as is available.
1773 */
1774void
1775eel_labeled_image_set_fill (EelLabeledImage *labeled_image,
1776 gboolean fill)
1777{
1778 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1779
1780 if (labeled_image->details->fill == fill)
1781 {
1782 return;
1783 }
1784
1785 labeled_image->details->fill = fill;
1786
1787 labeled_image_update_alignments (labeled_image);
1788
1789 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1790}
1791
1792/**
1793 * eel_labeled_image_get_fill:
1794 * @labeled_image: A EelLabeledImage.
1795 *
1796 * Retruns a boolean value indicating whether the internal widgets fill
1797 * all the available allocation.
1798 */
1799gboolean
1800eel_labeled_image_get_fill (const EelLabeledImage *labeled_image)
1801{
1802 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1803
1804 return labeled_image->details->fill;
1805}
1806
1807static void
1808eel_labled_set_mnemonic_widget (GtkWidget *image_widget,
1809 GtkWidget *mnemonic_widget)
1810{
1811 EelLabeledImage *image;
1812
1813 g_assert (EEL_IS_LABELED_IMAGE (image_widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_widget)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1813, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (image_widget)"); } while (0)
;
1814
1815 image = EEL_LABELED_IMAGE (image_widget)((((EelLabeledImage*) (void *) ((image_widget)))));
1816
1817 if (image->details->label)
1818 gtk_label_set_mnemonic_widget
1819 (GTK_LABEL (image->details->label)((((GtkLabel*) (void *) ((image->details->label))))), mnemonic_widget);
1820}
1821
1822/**
1823 * eel_labeled_image_button_new:
1824 * @text: Text to use for label or NULL.
1825 * @pixbuf: Pixbuf to use for image or NULL.
1826 *
1827 * Create a stock GtkButton with a EelLabeledImage child.
1828 *
1829 */
1830GtkWidget *
1831eel_labeled_image_button_new (const char *text,
1832 GdkPixbuf *pixbuf)
1833{
1834 GtkWidget *button;
1835 GtkWidget *labeled_image;
1836
1837 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1838 labeled_image = eel_labeled_image_new (text, pixbuf);
1839 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1840 eel_labled_set_mnemonic_widget (labeled_image, button);
1841 gtk_widget_show (labeled_image);
1842
1843 return button;
1844}
1845
1846/**
1847 * eel_labeled_image_button_new_from_file_name:
1848 * @text: Text to use for label or NULL.
1849 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1850 *
1851 * Create a stock GtkToggleButton with a EelLabeledImage child.
1852 *
1853 */
1854GtkWidget *
1855eel_labeled_image_button_new_from_file_name (const char *text,
1856 const char *pixbuf_file_name)
1857{
1858 GtkWidget *button;
1859 GtkWidget *labeled_image;
1860
1861 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_189 = 1;
else _g_boolean_var_189 = 0; _g_boolean_var_189; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1862
1863 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1864 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1865 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1866 eel_labled_set_mnemonic_widget (labeled_image, button);
1867 gtk_widget_show (labeled_image);
1868
1869 return button;
1870}
1871
1872/**
1873 * eel_labeled_image_toggle_button_new:
1874 * @text: Text to use for label or NULL.
1875 * @pixbuf: Pixbuf to use for image or NULL.
1876 *
1877 * Create a stock GtkToggleButton with a EelLabeledImage child.
1878 *
1879 */
1880GtkWidget *
1881eel_labeled_image_toggle_button_new (const char *text,
1882 GdkPixbuf *pixbuf)
1883{
1884 GtkWidget *toggle_button;
1885 GtkWidget *labeled_image;
1886
1887 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1888 labeled_image = eel_labeled_image_new (text, pixbuf);
1889 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1890 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1891 gtk_widget_show (labeled_image);
1892
1893 return toggle_button;
1894}
1895
1896/**
1897 * eel_labeled_image_toggle_button_new_from_file_name:
1898 * @text: Text to use for label or NULL.
1899 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1900 *
1901 * Create a stock GtkToggleButton with a EelLabeledImage child.
1902 *
1903 */
1904GtkWidget *
1905eel_labeled_image_toggle_button_new_from_file_name (const char *text,
1906 const char *pixbuf_file_name)
1907{
1908 GtkWidget *toggle_button;
1909 GtkWidget *labeled_image;
1910
1911 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_190 = 1;
else _g_boolean_var_190 = 0; _g_boolean_var_190; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1912
1913 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1914 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1915 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1916 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1917 gtk_widget_show (labeled_image);
1918
1919 return toggle_button;
1920}
1921
1922/**
1923 * eel_labeled_image_toggle_button_new:
1924 * @text: Text to use for label or NULL.
1925 * @pixbuf: Pixbuf to use for image or NULL.
1926 *
1927 * Create a stock GtkToggleButton with a EelLabeledImage child.
1928 *
1929 * Returns: the new radio button.
1930 */
1931GtkWidget *
1932eel_labeled_image_radio_button_new (const char *text,
1933 GdkPixbuf *pixbuf)
1934{
1935 GtkWidget *radio_button;
1936 GtkWidget *labeled_image;
1937
1938 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1939 labeled_image = eel_labeled_image_new (text, pixbuf);
1940 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1941 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1942 gtk_widget_show (labeled_image);
1943
1944 return radio_button;
1945}
1946
1947/**
1948 * eel_labeled_image_radio_button_new_from_file_name:
1949 * @text: Text to use for label or NULL.
1950 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1951 *
1952 * Create a stock GtkRadioButton with a EelLabeledImage child.
1953 *
1954 * Returns: the new radio button.
1955 */
1956GtkWidget *
1957eel_labeled_image_radio_button_new_from_file_name (const char *text,
1958 const char *pixbuf_file_name)
1959{
1960 GtkWidget *radio_button;
1961 GtkWidget *labeled_image;
1962
1963 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_191 = 1;
else _g_boolean_var_191 = 0; _g_boolean_var_191; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1964
1965 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1966 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1967 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1968 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1969 gtk_widget_show (labeled_image);
1970
1971 return radio_button;
1972}
1973
1974/*
1975 * Workaround some bugs in GtkCheckButton where the widget
1976 * does not redraw properly after leave or focus out events
1977 *
1978 * The workaround is to draw a little bit more than the
1979 * widget itself - 4 pixels worth. For some reason the
1980 * widget does not properly redraw its edges.
1981 */
1982static void
1983button_leave_callback (GtkWidget *widget,
1984 gpointer callback_data)
1985{
1986 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 1986, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
1987
1988 if (gtk_widget_is_drawable (widget))
1989 {
1990 const int fudge = 4;
1991 EelIRect bounds;
1992
1993 bounds = eel_gtk_widget_get_bounds (widget);
1994
1995 bounds.x0 -= fudge;
1996 bounds.y0 -= fudge;
1997 bounds.x1 += fudge;
1998 bounds.y1 += fudge;
1999
2000 gtk_widget_queue_draw_area (gtk_widget_get_parent (widget),
2001 bounds.x0,
2002 bounds.y0,
2003 eel_irect_get_width (bounds),
2004 eel_irect_get_height (bounds));
2005 }
2006}
2007
2008static gint
2009button_focus_out_event_callback (GtkWidget *widget,
2010 GdkEventFocus *event,
2011 gpointer callback_data)
2012{
2013 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_193
= 1; else _g_boolean_var_193 = 0; _g_boolean_var_193; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 2013, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
2014
2015 button_leave_callback (widget, callback_data);
2016
2017 return FALSE(0);
2018}
2019
2020/**
2021 * eel_labeled_image_check_button_new:
2022 * @text: Text to use for label or NULL.
2023 * @pixbuf: Pixbuf to use for image or NULL.
2024 *
2025 * Create a stock GtkCheckButton with a EelLabeledImage child.
2026 *
2027 */
2028GtkWidget *
2029eel_labeled_image_check_button_new (const char *text,
2030 GdkPixbuf *pixbuf)
2031{
2032 GtkWidget *check_button;
2033 GtkWidget *labeled_image;
2034
2035 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2036 labeled_image = eel_labeled_image_new (text, pixbuf);
2037 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2038 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2039 gtk_widget_show (labeled_image);
2040
2041 /*
2042 * Workaround some bugs in GtkCheckButton where the widget
2043 * does not redraw properly after leave or focus out events
2044 */
2045 g_signal_connect (check_button, "leave",g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
2046 G_CALLBACK (button_leave_callback), NULL)g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
2047 g_signal_connect (check_button, "focus_out_event",g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
2048 G_CALLBACK (button_focus_out_event_callback), NULL)g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
;
2049
2050 return check_button;
2051}
2052
2053/**
2054 * eel_labeled_image_check_button_new_from_file_name:
2055 * @text: Text to use for label or NULL.
2056 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
2057 *
2058 * Create a stock GtkCheckButton with a EelLabeledImage child.
2059 *
2060 */
2061GtkWidget *
2062eel_labeled_image_check_button_new_from_file_name (const char *text,
2063 const char *pixbuf_file_name)
2064{
2065 GtkWidget *check_button;
2066 GtkWidget *labeled_image;
2067
2068 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_194 = 1;
else _g_boolean_var_194 = 0; _g_boolean_var_194; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
2069
2070 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2071 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
2072 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2073 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2074 gtk_widget_show (labeled_image);
2075
2076 return check_button;
2077}
2078
2079/*
2080 * The rest of the methods are proxies for those in EelImage and
2081 * EelLabel. We have all these so that we dont have to expose
2082 * our internal widgets at all. Probably more of these will be added
2083 * as they are needed.
2084 */
2085
2086/**
2087 * eel_labeled_image_set_pixbuf:
2088 * @labaled_image: A EelLabeledImage.
2089 * @pixbuf: New pixbuf to use or NULL.
2090 *
2091 * Change the pixbuf displayed by the LabeledImage. Note that the widget display
2092 * is only updated if the show_image attribute is TRUE.
2093 *
2094 * If no internal image widget exists as of yet, a new one will be created.
2095 *
2096 * A NULL &pixbuf will cause the internal image widget (if alive) to be destroyed.
2097 */
2098void
2099eel_labeled_image_set_pixbuf (EelLabeledImage *labeled_image,
2100 GdkPixbuf *pixbuf)
2101{
2102 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2103
2104 if (pixbuf == NULL((void*)0))
2105 {
2106 if (labeled_image->details->image != NULL((void*)0))
2107 {
2108 gtk_widget_destroy (labeled_image->details->image);
2109 labeled_image->details->image = NULL((void*)0);
2110 }
2111
2112 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2113 }
2114 else
2115 {
2116 labeled_image_ensure_image (labeled_image);
2117 gtk_image_set_from_pixbuf (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf);
2118 }
2119}
2120
2121void
2122eel_labeled_image_set_pixbuf_from_file_name (EelLabeledImage *labeled_image,
2123 const char *pixbuf_file_name)
2124{
2125 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_196 = 1; else _g_boolean_var_196 =
0; _g_boolean_var_196; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2126
2127 labeled_image_ensure_image (labeled_image);
2128 gtk_image_set_from_file (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf_file_name);
2129}
2130
2131/**
2132 * eel_labeled_image_set_text:
2133 * @labaled_image: A EelLabeledImage.
2134 * @text: New text (with mnemnonic) to use or NULL.
2135 *
2136 * Change the text displayed by the LabeledImage. Note that the widget display
2137 * is only updated if the show_label attribute is TRUE.
2138 *
2139 * If no internal label widget exists as of yet, a new one will be created.
2140 *
2141 * A NULL &text will cause the internal label widget (if alive) to be destroyed.
2142 */
2143void
2144eel_labeled_image_set_text (EelLabeledImage *labeled_image,
2145 const char *text)
2146{
2147 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_197 = 1; else _g_boolean_var_197 =
0; _g_boolean_var_197; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2148
2149 if (text == NULL((void*)0))
2150 {
2151 if (labeled_image->details->label)
2152 {
2153 gtk_widget_destroy (labeled_image->details->label);
2154 labeled_image->details->label = NULL((void*)0);
2155 }
2156
2157 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2158 }
2159 else
2160 {
2161 labeled_image_ensure_label (labeled_image);
2162 gtk_label_set_text_with_mnemonic
2163 (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, text);
2164 }
2165}
2166
2167char *
2168eel_labeled_image_get_text (const EelLabeledImage *labeled_image)
2169{
2170 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (((void*)0)); } } while (0)
;
2171
2172 if (labeled_image->details->label == NULL((void*)0))
2173 {
2174 return NULL((void*)0);
2175 }
2176
2177 return g_strdup (gtk_label_get_text (GTK_LABEL (labeled_image->details->label)))g_strdup_inline (gtk_label_get_text (((((GtkLabel*) (void *) (
(labeled_image->details->label)))))))
;
2178}
2179
2180void
2181eel_labeled_image_set_can_focus (EelLabeledImage *labeled_image,
2182 gboolean can_focus)
2183{
2184 gtk_widget_set_can_focus (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), can_focus);
2185}
2186
2187static AtkObjectClass *a11y_parent_class = NULL((void*)0);
2188
2189static void
2190eel_labeled_image_accessible_initialize (AtkObject *accessible,
2191 gpointer widget)
2192{
2193 a11y_parent_class->initialize (accessible, widget);
2194 atk_object_set_role (accessible, ATK_ROLE_IMAGE);
2195
2196}
2197
2198static EelLabeledImage *
2199get_image (gpointer object)
2200{
2201 GtkWidget *widget;
2202
2203 if (!(widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (object)((((GtkAccessible*) (void *) ((object))))))))
2204 {
2205 return NULL((void*)0);
2206 }
2207
2208 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; }))))
)
2209 widget = gtk_bin_get_child (GTK_BIN (widget)((((GtkBin*) (void *) ((widget))))));
2210
2211 return EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
2212}
2213
2214static const gchar* eel_labeled_image_accessible_get_name(AtkObject* accessible)
2215{
2216 EelLabeledImage* labeled_image;
2217
2218 labeled_image = get_image(accessible);
2219
2220 if (labeled_image && labeled_image->details && labeled_image->details->label)
2221 {
2222 return gtk_label_get_text(GTK_LABEL(labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
2223 }
2224
2225 g_warning("no label on '%p'", labeled_image);
2226
2227 return NULL((void*)0);
2228}
2229
2230static void
2231eel_labeled_image_accessible_image_get_size (AtkImage *image,
2232 gint *width,
2233 gint *height)
2234{
2235 EelLabeledImage *labeled_image;
2236 GtkAllocation allocation;
2237
2238 labeled_image = get_image (image);
2239
2240 if (!labeled_image || !labeled_image->details->image)
2241 {
2242 *width = *height = 0;
2243 return;
2244 }
2245
2246 gtk_widget_get_allocation (labeled_image->details->image, &allocation);
2247 *width = allocation.width;
2248 *height = allocation.height;
2249}
2250
2251static void
2252eel_labeled_image_accessible_image_interface_init (AtkImageIface *iface)
2253{
2254 iface->get_image_size = eel_labeled_image_accessible_image_get_size;
2255}
2256
2257typedef struct _EelLabeledImageAccessible EelLabeledImageAccessible;
2258typedef struct _EelLabeledImageAccessibleClass EelLabeledImageAccessibleClass;
2259
2260struct _EelLabeledImageAccessible
2261{
2262 GtkContainerAccessible parent;
2263};
2264
2265struct _EelLabeledImageAccessibleClass
2266{
2267 GtkContainerAccessibleClass parent_class;
2268};
2269
2270G_DEFINE_TYPE_WITH_CODE (EelLabeledImageAccessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2271 eel_labeled_image_accessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2272 GTK_TYPE_CONTAINER_ACCESSIBLE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2273 G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2274 eel_labeled_image_accessible_image_interface_init))static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
;
2275static void
2276eel_labeled_image_accessible_class_init (EelLabeledImageAccessibleClass *klass)
2277{
2278 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
2279 a11y_parent_class = g_type_class_peek_parent (klass);
2280
2281 atk_class->get_name = eel_labeled_image_accessible_get_name;
2282 atk_class->initialize = eel_labeled_image_accessible_initialize;
2283}
2284
2285static void
2286eel_labeled_image_accessible_init (EelLabeledImageAccessible *accessible)
2287{
2288}
2289
2290static void
2291eel_labeled_image_button_class_init (GtkWidgetClass *klass)
2292{
2293}
2294
2295static GType
2296eel_labeled_image_button_get_type (void)
2297{
2298 static GType type = 0;
2299
2300 if (!type)
2301 {
2302 GTypeInfo info =
2303 {
2304 sizeof (GtkButtonClass),
2305 (GBaseInitFunc) NULL((void*)0),
2306 (GBaseFinalizeFunc) NULL((void*)0),
2307 (GClassInitFunc) eel_labeled_image_button_class_init,
2308 NULL((void*)0), /* class_finalize */
2309 NULL((void*)0), /* class_data */
2310 sizeof (GtkButton),
2311 0, /* n_preallocs */
2312 (GInstanceInitFunc) NULL((void*)0)
2313 };
2314
2315 type = g_type_register_static
2316 (GTK_TYPE_BUTTON(gtk_button_get_type ()),
2317 "EelLabeledImageButton", &info, 0);
2318 }
2319
2320 return type;
2321}
2322
2323static GType
2324eel_labeled_image_check_button_get_type (void)
2325{
2326 static GType type = 0;
2327
2328 if (!type)
2329 {
2330 GTypeInfo info =
2331 {
2332 sizeof (GtkCheckButtonClass),
2333 (GBaseInitFunc) NULL((void*)0),
2334 (GBaseFinalizeFunc) NULL((void*)0),
2335 (GClassInitFunc) eel_labeled_image_button_class_init,
2336 NULL((void*)0), /* class_finalize */
2337 NULL((void*)0), /* class_data */
2338 sizeof (GtkCheckButton),
2339 0, /* n_preallocs */
2340 (GInstanceInitFunc) NULL((void*)0)
2341 };
2342
2343 type = g_type_register_static
2344 (GTK_TYPE_CHECK_BUTTON(gtk_check_button_get_type ()),
2345 "EelLabeledImageCheckButton", &info, 0);
2346 }
2347
2348 return type;
2349}
2350
2351static GType
2352eel_labeled_image_toggle_button_get_type (void)
2353{
2354 static GType type = 0;
2355
2356 if (!type)
2357 {
2358 GTypeInfo info =
2359 {
2360 sizeof (GtkToggleButtonClass),
2361 (GBaseInitFunc) NULL((void*)0),
2362 (GBaseFinalizeFunc) NULL((void*)0),
2363 (GClassInitFunc) eel_labeled_image_button_class_init,
2364 NULL((void*)0), /* class_finalize */
2365 NULL((void*)0), /* class_data */
2366 sizeof (GtkToggleButton),
2367 0, /* n_preallocs */
2368 (GInstanceInitFunc) NULL((void*)0)
2369 };
2370
2371 type = g_type_register_static
2372 (GTK_TYPE_TOGGLE_BUTTON(gtk_toggle_button_get_type ()),
2373 "EelLabeledImageToggleButton", &info, 0);
2374 }
2375
2376 return type;
2377}
2378
2379
2380static GType
2381eel_labeled_image_radio_button_get_type (void)
2382{
2383 static GType type = 0;
2384
2385 if (!type)
2386 {
2387 GTypeInfo info =
2388 {
2389 sizeof (GtkRadioButtonClass),
2390 (GBaseInitFunc) NULL((void*)0),
2391 (GBaseFinalizeFunc) NULL((void*)0),
2392 (GClassInitFunc) eel_labeled_image_button_class_init,
2393 NULL((void*)0), /* class_finalize */
2394 NULL((void*)0), /* class_data */
2395 sizeof (GtkRadioButton),
2396 0, /* n_preallocs */
2397 (GInstanceInitFunc) NULL((void*)0)
2398 };
2399
2400 type = g_type_register_static
2401 (GTK_TYPE_RADIO_BUTTON(gtk_radio_button_get_type ()),
2402 "EelLabeledImageRadioButton", &info, 0);
2403 }
2404
2405 return type;
2406}
diff --git a/2024-07-29-023715-6438-1/report-f8875c.html b/2024-07-29-023715-6438-1/report-f8875c.html new file mode 100644 index 000000000..f8c33a8d2 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-f8875c.html @@ -0,0 +1,902 @@ + + + +eel-vfs-extensions.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-vfs-extensions.c
Warning:line 127, column 21
Access of 'char' element in the region at index -1
+ +

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 eel-vfs-extensions.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-vfs-extensions.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* eel-vfs-extensions.c - mate-vfs extensions. Its likely some of these will
4 be part of mate-vfs in the future.
5
6 Copyright (C) 1999, 2000 Eazel, Inc.
7
8 The Mate Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 The Mate 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 the Mate Library; see the file COPYING.LIB. If not,
20 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 Authors: Darin Adler <darin@eazel.com>
24 Pavel Cisler <pavel@eazel.com>
25 Mike Fleming <mfleming@eazel.com>
26 John Sullivan <sullivan@eazel.com>
27*/
28
29#include <config.h>
30#include "eel-vfs-extensions.h"
31#include "eel-glib-extensions.h"
32#include "eel-lib-self-check-functions.h"
33#include <glib.h>
34#include <glib/gi18n-lib.h>
35#include <gio/gio.h>
36
37#include "eel-string.h"
38
39#include <string.h>
40#include <stdlib.h>
41
42gboolean
43eel_uri_is_trash (const char *uri)
44{
45 return eel_istr_has_prefix (uri, "trash:");
46}
47
48gboolean
49eel_uri_is_search (const char *uri)
50{
51 return eel_istr_has_prefix (uri, EEL_SEARCH_URI"x-caja-search:");
52}
53
54gboolean
55eel_uri_is_desktop (const char *uri)
56{
57 return eel_istr_has_prefix (uri, EEL_DESKTOP_URI"x-caja-desktop:");
58}
59
60char *
61eel_make_valid_utf8 (const char *name)
62{
63 GString *string;
64 const char *remainder, *invalid;
65 int remaining_bytes;
66
67 string = NULL((void*)0);
68 remainder = name;
69 remaining_bytes = strlen (name);
70
71 while (remaining_bytes != 0)
72 {
73 int valid_bytes;
74
75 if (g_utf8_validate (remainder, remaining_bytes, &invalid))
76 {
77 break;
78 }
79 valid_bytes = invalid - remainder;
80
81 if (string == NULL((void*)0))
82 {
83 string = g_string_sized_new (remaining_bytes);
84 }
85 g_string_append_len (string, remainder, valid_bytes)g_string_append_len_inline (string, remainder, valid_bytes);
86 g_string_append_c (string, '?')g_string_append_c_inline (string, '?');
87
88 remaining_bytes -= valid_bytes + 1;
89 remainder = invalid + 1;
90 }
91
92 if (string == NULL((void*)0))
93 {
94 return g_strdup (name)g_strdup_inline (name);
95 }
96
97 g_string_append (string, remainder)(__builtin_constant_p (remainder) ? __extension__ ({ const char
* const __val = (remainder); g_string_append_len_inline (string
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (__val != ((void*)0)) _g_boolean_var_16 = 1; else _g_boolean_var_16
= 0; _g_boolean_var_16; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
string, remainder, (gssize) -1))
;
98 g_string_append (string, _(" (invalid Unicode)"))(__builtin_constant_p (((char *) g_dgettext ("caja", " (invalid Unicode)"
))) ? __extension__ ({ const char * const __val = (((char *) g_dgettext
("caja", " (invalid Unicode)"))); g_string_append_len_inline
(string, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (__val != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
string, ((char *) g_dgettext ("caja", " (invalid Unicode)")),
(gssize) -1))
;
99 g_assert (g_utf8_validate (string->str, -1, NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (g_utf8_validate (string->str, -1, ((void*)0))) _g_boolean_var_18
= 1; else _g_boolean_var_18 = 0; _g_boolean_var_18; }), 1)) ;
else g_assertion_message_expr ("Eel", "eel-vfs-extensions.c"
, 99, ((const char*) (__func__)), "g_utf8_validate (string->str, -1, NULL)"
); } while (0)
;
100
101 return g_string_free (string, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((string
), ((0))) : g_string_free_and_steal (string)) : (g_string_free
) ((string), ((0))))
;
102}
103
104char *
105eel_filename_strip_extension (const char * filename_with_extension)
106{
107 char *filename, *end, *end2;
108
109 if (filename_with_extension
13.1
'filename_with_extension' is not equal to NULL
== NULL((void*)0))
14
Taking false branch
110 {
111 return NULL((void*)0);
112 }
113
114 filename = g_strdup (filename_with_extension)g_strdup_inline (filename_with_extension);
115
116 end = strrchr (filename, '.');
117
118 if (end && end != filename)
15
Assuming 'end' is non-null
16
Assuming 'end' is not equal to 'filename'
119 {
120 if (strcmp (end, ".gz") == 0 ||
121 strcmp (end, ".bz2") == 0 ||
122 strcmp (end, ".sit") == 0 ||
123 strcmp (end, ".Z") == 0)
124 {
125 end2 = end - 1;
126 while (end2 > filename &&
17
Assuming 'end2' is > 'filename'
127 *end2 != '.')
18
Access of 'char' element in the region at index -1
128 {
129 end2--;
130 }
131 if (end2 != filename)
132 {
133 end = end2;
134 }
135 }
136 *end = '\0';
137 }
138
139 return filename;
140}
141
142void
143eel_filename_get_rename_region (const char *filename,
144 int *start_offset,
145 int *end_offset)
146{
147 char *filename_without_extension;
148
149 g_return_if_fail (start_offset != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (start_offset != ((void*)0)) _g_boolean_var_19 = 1; else
_g_boolean_var_19 = 0; _g_boolean_var_19; }), 1))) { } else {
g_return_if_fail_warning ("Eel", ((const char*) (__func__)),
"start_offset != NULL"); return; } } while (0)
;
1
Assuming 'start_offset' is not equal to null
2
Taking true branch
3
Taking true branch
4
Loop condition is false. Exiting loop
150 g_return_if_fail (end_offset != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (end_offset != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "end_offset != NULL"); return
; } } while (0)
;
5
Assuming 'end_offset' is not equal to null
6
Taking true branch
7
Taking true branch
8
Loop condition is false. Exiting loop
151
152 *start_offset = 0;
153 *end_offset = 0;
154
155 g_return_if_fail (filename != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (filename != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "filename != NULL"); return
; } } while (0)
;
9
Assuming 'filename' is not equal to null
10
Taking true branch
11
Taking true branch
12
Loop condition is false. Exiting loop
156
157 filename_without_extension = eel_filename_strip_extension (filename);
13
Calling 'eel_filename_strip_extension'
158 *end_offset = g_utf8_strlen (filename_without_extension, -1);
159
160 g_free (filename_without_extension);
161}
diff --git a/2024-07-29-023715-6438-1/report-f8a52c.html b/2024-07-29-023715-6438-1/report-f8a52c.html new file mode 100644 index 000000000..78d3a6c04 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-f8a52c.html @@ -0,0 +1,2681 @@ + + + +caja-icon-dnd.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-private/caja-icon-dnd.c
Warning:line 627, column 5
Value stored to 'result' 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 caja-icon-dnd.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 -fdebug-compilation-dir=/rootdir/libcaja-private -fcoverage-compilation-dir=/rootdir/libcaja-private -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SYSCONFDIR="/usr/local/etc" -D CAJA_DATADIR="/usr/local/share/caja" -D CAJA_EXTENSIONDIR="/usr/local/lib/caja/extensions-2.0" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-icon-dnd.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* caja-icon-dnd.c - Drag & drop handling for the icon container widget.
4
5 Copyright (C) 1999, 2000 Free Software Foundation
6 Copyright (C) 2000 Eazel, Inc.
7
8 The Mate Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 The Mate 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 the Mate Library; see the file COPYING.LIB. If not,
20 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 Authors: Ettore Perazzoli <ettore@gnu.org>,
24 Darin Adler <darin@bentspoon.com>,
25 Andy Hertzfeld <andy@eazel.com>
26 Pavel Cisler <pavel@eazel.com>
27
28
29 XDS support: Benedikt Meurer <benny@xfce.org> (adapted by Amos Brocco <amos.brocco@unifr.ch>)
30
31*/
32
33
34#include <config.h>
35#include <math.h>
36#include <stdio.h>
37#include <string.h>
38
39#include <gdk/gdkkeysyms.h>
40#include <gdk/gdkx.h>
41#include <gtk/gtk.h>
42#include <glib/gi18n.h>
43
44#include <eel/eel-background.h>
45#include <eel/eel-gdk-pixbuf-extensions.h>
46#include <eel/eel-glib-extensions.h>
47#include <eel/eel-mate-extensions.h>
48#include <eel/eel-graphic-effects.h>
49#include <eel/eel-gtk-extensions.h>
50#include <eel/eel-gtk-macros.h>
51#include <eel/eel-stock-dialogs.h>
52#include <eel/eel-string.h>
53#include <eel/eel-vfs-extensions.h>
54#include <eel/eel-canvas-rect-ellipse.h>
55
56#include "caja-icon-dnd.h"
57#include "caja-debug-log.h"
58#include "caja-file-dnd.h"
59#include "caja-icon-private.h"
60#include "caja-link.h"
61#include "caja-metadata.h"
62#include "caja-file-utilities.h"
63#include "caja-file-changes-queue.h"
64
65static const GtkTargetEntry drag_types [] =
66{
67 { CAJA_ICON_DND_MATE_ICON_LIST_TYPE"x-special/mate-icon-list", 0, CAJA_ICON_DND_MATE_ICON_LIST },
68 { CAJA_ICON_DND_URI_LIST_TYPE"text/uri-list", 0, CAJA_ICON_DND_URI_LIST },
69};
70
71static const GtkTargetEntry drop_types [] =
72{
73 { CAJA_ICON_DND_MATE_ICON_LIST_TYPE"x-special/mate-icon-list", 0, CAJA_ICON_DND_MATE_ICON_LIST },
74 /* prefer "_NETSCAPE_URL" over "text/uri-list" to satisfy web browsers. */
75 { CAJA_ICON_DND_NETSCAPE_URL_TYPE"_NETSCAPE_URL", 0, CAJA_ICON_DND_NETSCAPE_URL },
76 { CAJA_ICON_DND_URI_LIST_TYPE"text/uri-list", 0, CAJA_ICON_DND_URI_LIST },
77 { CAJA_ICON_DND_COLOR_TYPE"application/x-color", 0, CAJA_ICON_DND_COLOR },
78 { CAJA_ICON_DND_BGIMAGE_TYPE"property/bgimage", 0, CAJA_ICON_DND_BGIMAGE },
79 { CAJA_ICON_DND_KEYWORD_TYPE"property/keyword", 0, CAJA_ICON_DND_KEYWORD },
80 { CAJA_ICON_DND_RESET_BACKGROUND_TYPE"x-special/mate-reset-background", 0, CAJA_ICON_DND_RESET_BACKGROUND },
81 { CAJA_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", 0, CAJA_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */
82 { CAJA_ICON_DND_RAW_TYPE"application/octet-stream", 0, CAJA_ICON_DND_RAW },
83 /* Must be last: */
84 { CAJA_ICON_DND_ROOTWINDOW_DROP_TYPE"application/x-rootwindow-drop", 0, CAJA_ICON_DND_ROOTWINDOW_DROP }
85};
86static void stop_dnd_highlight (GtkWidget *widget);
87static void dnd_highlight_queue_redraw (GtkWidget *widget);
88
89static GtkTargetList *drop_types_list = NULL((void*)0);
90static GtkTargetList *drop_types_list_root = NULL((void*)0);
91
92static char * caja_icon_container_find_drop_target (CajaIconContainer *container,
93 GdkDragContext *context,
94 int x, int y, gboolean *icon_hit,
95 gboolean rewrite_desktop);
96
97static EelCanvasItem *
98create_selection_shadow (CajaIconContainer *container,
99 GList *list)
100{
101 EelCanvasGroup *group;
102 EelCanvas *canvas;
103 int max_x, max_y;
104 int min_x, min_y;
105 GList *p;
106 GtkAllocation allocation;
107
108 if (list == NULL((void*)0))
109 {
110 return NULL((void*)0);
111 }
112
113 /* if we're only dragging a single item, don't worry about the shadow */
114 if (list->next == NULL((void*)0))
115 {
116 return NULL((void*)0);
117 }
118
119 canvas = EEL_CANVAS (container)((((EelCanvas*) (void *) ((container)))));
120 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
121
122 /* Creating a big set of rectangles in the canvas can be expensive, so
123 we try to be smart and only create the maximum number of rectangles
124 that we will need, in the vertical/horizontal directions. */
125
126 max_x = allocation.width;
127 min_x = -max_x;
128
129 max_y = allocation.height;
130 min_y = -max_y;
131
132 /* Create a group, so that it's easier to move all the items around at
133 once. */
134 group = EEL_CANVAS_GROUP((((EelCanvasGroup*) (void *) ((eel_canvas_item_new (((((EelCanvasGroup
*) (void *) ((canvas->root))))), eel_canvas_group_get_type
(), ((void*)0)))))))
135 (eel_canvas_item_new (EEL_CANVAS_GROUP (canvas->root),((((EelCanvasGroup*) (void *) ((eel_canvas_item_new (((((EelCanvasGroup
*) (void *) ((canvas->root))))), eel_canvas_group_get_type
(), ((void*)0)))))))
136 eel_canvas_group_get_type (),((((EelCanvasGroup*) (void *) ((eel_canvas_item_new (((((EelCanvasGroup
*) (void *) ((canvas->root))))), eel_canvas_group_get_type
(), ((void*)0)))))))
137 NULL))((((EelCanvasGroup*) (void *) ((eel_canvas_item_new (((((EelCanvasGroup
*) (void *) ((canvas->root))))), eel_canvas_group_get_type
(), ((void*)0)))))))
;
138
139 for (p = list; p != NULL((void*)0); p = p->next)
140 {
141 CajaDragSelectionItem *item;
142 int x1, y1, x2, y2;
143 GdkRGBA black = { 0, 0, 0, 1 };
144
145 item = p->data;
146
147 if (!item->got_icon_position)
148 {
149 continue;
150 }
151
152 x1 = item->icon_x;
153 y1 = item->icon_y;
154 x2 = x1 + item->icon_width;
155 y2 = y1 + item->icon_height;
156
157 if (x2 >= min_x && x1 <= max_x && y2 >= min_y && y1 <= max_y)
158 eel_canvas_item_new
159 (group,
160 eel_canvas_rect_get_type (),
161 "x1", (double) x1,
162 "y1", (double) y1,
163 "x2", (double) x2,
164 "y2", (double) y2,
165 "outline-color-rgba", &black,
166 "outline-stippling", TRUE(!(0)),
167 "width_pixels", 1,
168 NULL((void*)0));
169 }
170
171 return EEL_CANVAS_ITEM (group)((((EelCanvasItem*) (void *) ((group)))));
172}
173
174/* Set the affine instead of the x and y position.
175 * Simple, and setting x and y was broken at one point.
176 */
177static void
178set_shadow_position (EelCanvasItem *shadow,
179 double x, double y)
180{
181 eel_canvas_item_set (shadow,
182 "x", x, "y", y,
183 NULL((void*)0));
184}
185
186
187/* Source-side handling of the drag. */
188
189/* iteration glue struct */
190typedef struct
191{
192 gpointer iterator_context;
193 CajaDragEachSelectedItemDataGet iteratee;
194 gpointer iteratee_data;
195} IconGetDataBinderContext;
196
197static void
198canvas_rect_world_to_widget (EelCanvas *canvas,
199 EelDRect *world_rect,
200 EelIRect *widget_rect)
201{
202 EelDRect window_rect;
203 GtkAdjustment *hadj, *vadj;
204
205 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
206 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))));
207
208 eel_canvas_world_to_window (canvas,
209 world_rect->x0, world_rect->y0,
210 &window_rect.x0, &window_rect.y0);
211 eel_canvas_world_to_window (canvas,
212 world_rect->x1, world_rect->y1,
213 &window_rect.x1, &window_rect.y1);
214 widget_rect->x0 = (int) window_rect.x0 - gtk_adjustment_get_value (hadj);
215 widget_rect->y0 = (int) window_rect.y0 - gtk_adjustment_get_value (vadj);
216 widget_rect->x1 = (int) window_rect.x1 - gtk_adjustment_get_value (hadj);
217 widget_rect->y1 = (int) window_rect.y1 - gtk_adjustment_get_value (vadj);
218}
219
220static void
221canvas_widget_to_world (EelCanvas *canvas,
222 double widget_x, double widget_y,
223 double *world_x, double *world_y)
224{
225 eel_canvas_window_to_world (canvas,
226 widget_x + gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))))),
227 widget_y + gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)((((GtkScrollable*) (void *) ((canvas))))))),
228 world_x, world_y);
229}
230
231static gboolean
232icon_get_data_binder (CajaIcon *icon, gpointer data)
233{
234 IconGetDataBinderContext *context;
235 EelDRect world_rect;
236 EelIRect widget_rect;
237 char *uri;
238 CajaIconContainer *container;
239
240 context = (IconGetDataBinderContext *)data;
241
242 g_assert (CAJA_IS_ICON_CONTAINER (context->iterator_context))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context->iterator_context)); GType __t = (caja_icon_container_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_29 = 1; else _g_boolean_var_29 = 0
; _g_boolean_var_29; }), 1)) ; else g_assertion_message_expr (
((gchar*) 0), "caja-icon-dnd.c", 242, ((const char*) (__func__
)), "CAJA_IS_ICON_CONTAINER (context->iterator_context)");
} while (0)
;
243
244 container = CAJA_ICON_CONTAINER (context->iterator_context)((((CajaIconContainer*) (void *) ((context->iterator_context
)))))
;
245
246 world_rect = caja_icon_canvas_item_get_icon_rectangle (icon->item);
247
248 canvas_rect_world_to_widget (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), &world_rect, &widget_rect);
249
250 uri = caja_icon_container_get_icon_uri (container, icon);
251 if (uri == NULL((void*)0))
252 {
253 g_warning ("no URI for one of the iterated icons");
254 return TRUE(!(0));
255 }
256
257 widget_rect = eel_irect_offset_by (widget_rect,
258 - container->details->dnd_info->drag_info.start_x,
259 - container->details->dnd_info->drag_info.start_y);
260
261 widget_rect = eel_irect_scale_by (widget_rect,
262 1 / EEL_CANVAS (container)((((EelCanvas*) (void *) ((container)))))->pixels_per_unit);
263
264 /* pass the uri, mouse-relative x/y and icon width/height */
265 context->iteratee (uri,
266 (int) widget_rect.x0,
267 (int) widget_rect.y0,
268 widget_rect.x1 - widget_rect.x0,
269 widget_rect.y1 - widget_rect.y0,
270 context->iteratee_data);
271
272 g_free (uri);
273
274 return TRUE(!(0));
275}
276
277/* Iterate over each selected icon in a CajaIconContainer,
278 * calling each_function on each.
279 */
280static void
281caja_icon_container_each_selected_icon (CajaIconContainer *container,
282 gboolean (*each_function) (CajaIcon *, gpointer), gpointer data)
283{
284 GList *p;
285 CajaIcon *icon = NULL((void*)0);
286
287 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
288 {
289 icon = p->data;
290 if (!icon->is_selected)
291 {
292 continue;
293 }
294 if (!each_function (icon, data))
295 {
296 return;
297 }
298 }
299}
300
301/* Adaptor function used with caja_icon_container_each_selected_icon
302 * to help iterate over all selected items, passing uris, x, y, w and h
303 * values to the iteratee
304 */
305static void
306each_icon_get_data_binder (CajaDragEachSelectedItemDataGet iteratee,
307 gpointer iterator_context, gpointer data)
308{
309 IconGetDataBinderContext context;
310 CajaIconContainer *container;
311
312 g_assert (CAJA_IS_ICON_CONTAINER (iterator_context))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((iterator_context)); GType __t = (caja_icon_container_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_30 = 1; else _g_boolean_var_30 = 0
; _g_boolean_var_30; }), 1)) ; else g_assertion_message_expr (
((gchar*) 0), "caja-icon-dnd.c", 312, ((const char*) (__func__
)), "CAJA_IS_ICON_CONTAINER (iterator_context)"); } while (0)
;
313 container = CAJA_ICON_CONTAINER (iterator_context)((((CajaIconContainer*) (void *) ((iterator_context)))));
314
315 context.iterator_context = iterator_context;
316 context.iteratee = iteratee;
317 context.iteratee_data = data;
318 caja_icon_container_each_selected_icon (container, icon_get_data_binder, &context);
319}
320
321/* Called when the data for drag&drop is needed */
322static void
323drag_data_get_callback (GtkWidget *widget,
324 GdkDragContext *context,
325 GtkSelectionData *selection_data,
326 guint info,
327 guint32 time,
328 gpointer data)
329{
330 g_assert (widget != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if (widget != ((void*)0)) _g_boolean_var_31 = 1; else _g_boolean_var_31
= 0; _g_boolean_var_31; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-dnd.c", 330, ((const char*) (__func__
)), "widget != NULL"); } while (0)
;
331 g_assert (CAJA_IS_ICON_CONTAINER (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (caja_icon_container_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_32
= 1; else _g_boolean_var_32 = 0; _g_boolean_var_32; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-icon-dnd.c"
, 331, ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (widget)"
); } while (0)
;
332 g_return_if_fail (context != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if (context != ((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__)), "context != NULL"
); return; } } while (0)
;
333
334 /* Call common function from caja-drag that set's up
335 * the selection data in the right format. Pass it means to
336 * iterate all the selected icons.
337 */
338 caja_drag_drag_data_get (widget, context, selection_data,
339 info, time, widget, each_icon_get_data_binder);
340}
341
342
343/* Target-side handling of the drag. */
344
345static void
346caja_icon_container_position_shadow (CajaIconContainer *container,
347 int x, int y)
348{
349 EelCanvasItem *shadow;
350 double world_x, world_y;
351
352 shadow = container->details->dnd_info->shadow;
353 if (shadow == NULL((void*)0))
354 {
355 return;
356 }
357
358 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), x, y,
359 &world_x, &world_y);
360
361 set_shadow_position (shadow, world_x, world_y);
362 eel_canvas_item_show (shadow);
363}
364
365static void
366caja_icon_container_dropped_icon_feedback (GtkWidget *widget,
367 GtkSelectionData *data,
368 int x, int y)
369{
370 CajaIconContainer *container;
371 CajaIconDndInfo *dnd_info;
372
373 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
374 dnd_info = container->details->dnd_info;
375
376 /* Delete old selection list. */
377 caja_drag_destroy_selection_list (dnd_info->drag_info.selection_list);
378 dnd_info->drag_info.selection_list = NULL((void*)0);
379
380 /* Delete old shadow if any. */
381 if (dnd_info->shadow != NULL((void*)0))
382 {
383 /* FIXME bugzilla.gnome.org 42484:
384 * Is a destroy really sufficient here? Who does the unref? */
385 eel_canvas_item_destroy (dnd_info->shadow);
386 }
387
388 /* Build the selection list and the shadow. */
389 dnd_info->drag_info.selection_list = caja_drag_build_selection_list (data);
390 dnd_info->shadow = create_selection_shadow (container, dnd_info->drag_info.selection_list);
391 caja_icon_container_position_shadow (container, x, y);
392}
393
394static char *
395get_direct_save_filename (GdkDragContext *context)
396{
397 guchar *prop_text;
398 gint prop_len;
399
400 if (!gdk_property_get (gdk_drag_context_get_source_window (context), gdk_atom_intern (CAJA_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", FALSE(0)),
401 gdk_atom_intern ("text/plain", FALSE(0)), 0, 1024, FALSE(0), NULL((void*)0), NULL((void*)0),
402 &prop_len, &prop_text))
403 {
404 return NULL((void*)0);
405 }
406
407 /* Zero-terminate the string */
408 prop_text = g_realloc (prop_text, prop_len + 1);
409 prop_text[prop_len] = '\0';
410
411 /* Verify that the file name provided by the source is valid */
412 if (*prop_text == '\0' ||
413 strchr ((const gchar *) prop_text, G_DIR_SEPARATOR'/') != NULL((void*)0))
414 {
415 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
416 "Invalid filename provided by XDS drag site");
417 g_free (prop_text);
418 return NULL((void*)0);
419 }
420
421 return prop_text;
422}
423
424static void
425set_direct_save_uri (GtkWidget *widget, GdkDragContext *context, CajaDragInfo *drag_info, int x, int y)
426{
427 char *filename, *drop_target;
428 gchar *uri;
429
430 drag_info->got_drop_data_type = TRUE(!(0));
431 drag_info->data_type = CAJA_ICON_DND_XDNDDIRECTSAVE;
432
433 uri = NULL((void*)0);
434
435 filename = get_direct_save_filename (context);
436 drop_target = caja_icon_container_find_drop_target (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
437 context, x, y, NULL((void*)0), TRUE(!(0)));
438
439 if (drop_target && eel_uri_is_trash (drop_target))
440 {
441 g_free (drop_target);
442 drop_target = NULL((void*)0); /* Cannot save to trash ...*/
443 }
444
445 if (filename != NULL((void*)0) && drop_target != NULL((void*)0))
446 {
447 GFile *base, *child;
448
449 /* Resolve relative path */
450 base = g_file_new_for_uri (drop_target);
451 child = g_file_get_child (base, filename);
452 uri = g_file_get_uri (child);
453 g_object_unref (base);
454 g_object_unref (child);
455
456 /* Change the uri property */
457 gdk_property_change (gdk_drag_context_get_source_window (context),
458 gdk_atom_intern (CAJA_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", FALSE(0)),
459 gdk_atom_intern ("text/plain", FALSE(0)), 8,
460 GDK_PROP_MODE_REPLACE, (const guchar *) uri,
461 strlen (uri));
462
463 drag_info->direct_save_uri = uri;
464 }
465
466 g_free (filename);
467 g_free (drop_target);
468}
469
470/* FIXME bugzilla.gnome.org 47445: Needs to become a shared function */
471static void
472get_data_on_first_target_we_support (GtkWidget *widget, GdkDragContext *context, guint32 time, int x, int y)
473{
474 GtkTargetList *list;
475 GdkAtom target;
476
477 if (drop_types_list == NULL((void*)0))
478 {
479 drop_types_list = gtk_target_list_new (drop_types,
480 G_N_ELEMENTS (drop_types)(sizeof (drop_types) / sizeof ((drop_types)[0])) - 1);
481 gtk_target_list_add_text_targets (drop_types_list, CAJA_ICON_DND_TEXT);
482 }
483 if (drop_types_list_root == NULL((void*)0))
484 {
485 drop_types_list_root = gtk_target_list_new (drop_types,
486 G_N_ELEMENTS (drop_types)(sizeof (drop_types) / sizeof ((drop_types)[0])));
487 gtk_target_list_add_text_targets (drop_types_list_root, CAJA_ICON_DND_TEXT);
488 }
489
490 if (caja_icon_container_get_is_desktop (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))))
491 {
492 list = drop_types_list_root;
493 }
494 else
495 {
496 list = drop_types_list;
497 }
498
499 target = gtk_drag_dest_find_target (widget, context, list);
500 if (target != GDK_NONE((GdkAtom)((gpointer) (gulong) (0))))
501 {
502 guint info;
503 CajaDragInfo *drag_info;
504 gboolean found;
505
506 drag_info = &(CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->dnd_info->drag_info);
507
508 found = gtk_target_list_find (list, target, &info);
509 g_assert (found)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if (found) _g_boolean_var_34 = 1; else _g_boolean_var_34 = 0
; _g_boolean_var_34; }), 1)) ; else g_assertion_message_expr (
((gchar*) 0), "caja-icon-dnd.c", 509, ((const char*) (__func__
)), "found"); } while (0)
;
510
511 /* Don't get_data for destructive ops */
512 if ((info == CAJA_ICON_DND_ROOTWINDOW_DROP ||
513 info == CAJA_ICON_DND_XDNDDIRECTSAVE) &&
514 !drag_info->drop_occured)
515 {
516 /* We can't call get_data here, because that would
517 make the source execute the rootwin action or the direct save */
518 drag_info->got_drop_data_type = TRUE(!(0));
519 drag_info->data_type = info;
520 }
521 else
522 {
523 if (info == CAJA_ICON_DND_XDNDDIRECTSAVE)
524 {
525 set_direct_save_uri (widget, context, drag_info, x, y);
526 }
527 gtk_drag_get_data (GTK_WIDGET (widget)((((GtkWidget*) (void *) ((widget))))), context,
528 target, time);
529 }
530 }
531}
532
533static void
534caja_icon_container_ensure_drag_data (CajaIconContainer *container,
535 GdkDragContext *context,
536 guint32 time)
537{
538 CajaIconDndInfo *dnd_info;
539
540 dnd_info = container->details->dnd_info;
541
542 if (!dnd_info->drag_info.got_drop_data_type)
543 {
544 get_data_on_first_target_we_support (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), context, time, 0, 0);
545 }
546}
547
548static void
549drag_end_callback (GtkWidget *widget,
550 GdkDragContext *context,
551 gpointer data)
552{
553 CajaIconContainer *container;
554 CajaIconDndInfo *dnd_info;
555
556 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
557 dnd_info = container->details->dnd_info;
558
559 caja_drag_destroy_selection_list (dnd_info->drag_info.selection_list);
560 dnd_info->drag_info.selection_list = NULL((void*)0);
561}
562
563static CajaIcon *
564caja_icon_container_item_at (CajaIconContainer *container,
565 int x, int y)
566{
567 GList *p;
568 int size;
569 EelDRect point;
570 EelIRect canvas_point;
571
572 /* build the hit-test rectangle. Base the size on the scale factor to ensure that it is
573 * non-empty even at the smallest scale factor
574 */
575
576 size = MAX (1, 1 + (1 / EEL_CANVAS (container)->pixels_per_unit))(((1) > (1 + (1 / ((((EelCanvas*) (void *) ((container))))
)->pixels_per_unit))) ? (1) : (1 + (1 / ((((EelCanvas*) (void
*) ((container)))))->pixels_per_unit)))
;
577 point.x0 = x;
578 point.y0 = y;
579 point.x1 = x + size;
580 point.y1 = y + size;
581
582 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
583 {
584 CajaIcon *icon;
585 icon = p->data;
586
587 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
588 point.x0,
589 point.y0,
590 &canvas_point.x0,
591 &canvas_point.y0);
592 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
593 point.x1,
594 point.y1,
595 &canvas_point.x1,
596 &canvas_point.y1);
597 if (caja_icon_canvas_item_hit_test_rectangle (icon->item, canvas_point))
598 {
599 return icon;
600 }
601 }
602
603 return NULL((void*)0);
604}
605
606static char *
607get_container_uri (CajaIconContainer *container)
608{
609 char *uri;
610
611 /* get the URI associated with the container */
612 uri = NULL((void*)0);
613 g_signal_emit_by_name (container, "get_container_uri", &uri);
614 return uri;
615}
616
617static gboolean
618caja_icon_container_selection_items_local (CajaIconContainer *container,
619 GList *items)
620{
621 char *container_uri_string;
622 gboolean result;
623
624 /* must have at least one item */
625 g_assert (items)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if (items) _g_boolean_var_35 = 1; else _g_boolean_var_35 = 0
; _g_boolean_var_35; }), 1)) ; else g_assertion_message_expr (
((gchar*) 0), "caja-icon-dnd.c", 625, ((const char*) (__func__
)), "items"); } while (0)
;
626
627 result = FALSE(0);
Value stored to 'result' is never read
628
629 /* get the URI associated with the container */
630 container_uri_string = get_container_uri (container);
631
632 if (eel_uri_is_desktop (container_uri_string))
633 {
634 result = caja_drag_items_on_desktop (items);
635 }
636 else
637 {
638 result = caja_drag_items_local (container_uri_string, items);
639 }
640 g_free (container_uri_string);
641
642 return result;
643}
644
645static GdkDragAction
646get_background_drag_action (CajaIconContainer *container,
647 GdkDragAction action)
648{
649 /* FIXME: This function is very FMDirectoryView specific, and
650 * should be moved out of caja-icon-dnd.c */
651 GdkDragAction valid_actions;
652
653 if (action == GDK_ACTION_ASK)
654 {
655 valid_actions = CAJA_DND_ACTION_SET_AS_FOLDER_BACKGROUND;
656 if (!eel_background_is_desktop (eel_get_widget_background (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))))))
657 {
658 valid_actions |= CAJA_DND_ACTION_SET_AS_GLOBAL_BACKGROUND;
659 }
660
661 action = caja_drag_drop_background_ask
662 (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), valid_actions);
663 }
664
665 return action;
666}
667
668static void
669receive_dropped_color (CajaIconContainer *container,
670 int x, int y,
671 GdkDragAction action,
672 GtkSelectionData *data)
673{
674 action = get_background_drag_action (container, action);
675
676 if (action > 0)
677 {
678 char *uri;
679
680 uri = get_container_uri (container);
681 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
682 "dropped color on icon container displaying %s", uri);
683 g_free (uri);
684
685 eel_background_set_dropped_color (eel_get_widget_background (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))),
686 GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))),
687 action, x, y, data);
688 }
689}
690
691/* handle dropped tile images */
692static void
693receive_dropped_tile_image (CajaIconContainer *container, GdkDragAction action, GtkSelectionData *data)
694{
695 g_assert (data != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if (data != ((void*)0)) _g_boolean_var_36 = 1; else _g_boolean_var_36
= 0; _g_boolean_var_36; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-dnd.c", 695, ((const char*) (__func__
)), "data != NULL"); } while (0)
;
696
697 action = get_background_drag_action (container, action);
698
699 if (action > 0)
700 {
701 char *uri;
702
703 uri = get_container_uri (container);
704 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
705 "dropped tile image on icon container displaying %s", uri);
706 g_free (uri);
707
708 eel_background_set_dropped_image (eel_get_widget_background (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))),
709 action, gtk_selection_data_get_data (data));
710 }
711}
712
713/* handle dropped keywords */
714static void
715receive_dropped_keyword (CajaIconContainer *container, const char *keyword, int x, int y)
716{
717 char *uri;
718 double world_x, world_y;
719
720 CajaIcon *drop_target_icon;
721 CajaFile *file;
722
723 g_assert (keyword != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if (keyword != ((void*)0)) _g_boolean_var_37 = 1; else _g_boolean_var_37
= 0; _g_boolean_var_37; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-icon-dnd.c", 723, ((const char*) (__func__
)), "keyword != NULL"); } while (0)
;
724
725 /* find the item we hit with our drop, if any */
726 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), x, y, &world_x, &world_y);
727 drop_target_icon = caja_icon_container_item_at (container, world_x, world_y);
728 if (drop_target_icon == NULL((void*)0))
729 {
730 return;
731 }
732
733 /* FIXME bugzilla.gnome.org 42485:
734 * This does not belong in the icon code.
735 * It has to be in the file manager.
736 * The icon code has no right to deal with the file directly.
737 * But luckily there's no issue of not getting a file object,
738 * so we don't have to worry about async. issues here.
739 */
740 uri = caja_icon_container_get_icon_uri (container, drop_target_icon);
741
742 caja_debug_log (FALSE(0), CAJA_DEBUG_LOG_DOMAIN_USER"USER",
743 "dropped emblem '%s' on icon container URI: %s",
744 keyword, uri);
745
746 file = caja_file_get_by_uri (uri);
747 g_free (uri);
748
749 caja_drag_file_receive_dropped_keyword (file, keyword);
750
751 caja_file_unref (file);
752 caja_icon_container_update_icon (container, drop_target_icon);
753}
754
755/* handle dropped url */
756static void
757receive_dropped_netscape_url (CajaIconContainer *container, const char *encoded_url, GdkDragContext *context, int x, int y)
758{
759 char *drop_target;
760
761 if (encoded_url == NULL((void*)0))
762 {
763 return;
764 }
765
766 drop_target = caja_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
767
768 g_signal_emit_by_name (container, "handle_netscape_url",
769 encoded_url,
770 drop_target,
771 gdk_drag_context_get_selected_action (context),
772 x, y);
773
774 g_free (drop_target);
775}
776
777/* handle dropped uri list */
778static void
779receive_dropped_uri_list (CajaIconContainer *container, const char *uri_list, GdkDragContext *context, int x, int y)
780{
781 char *drop_target;
782
783 if (uri_list == NULL((void*)0))
784 {
785 return;
786 }
787
788 drop_target = caja_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
789
790 g_signal_emit_by_name (container, "handle_uri_list",
791 uri_list,
792 drop_target,
793 gdk_drag_context_get_selected_action (context),
794 x, y);
795
796 g_free (drop_target);
797}
798
799/* handle dropped text */
800static void
801receive_dropped_text (CajaIconContainer *container, const char *text, GdkDragContext *context, int x, int y)
802{
803 char *drop_target;
804
805 if (text == NULL((void*)0))
806 {
807 return;
808 }
809
810 drop_target = caja_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
811
812 g_signal_emit_by_name (container, "handle_text",
813 text,
814 drop_target,
815 gdk_drag_context_get_selected_action (context),
816 x, y);
817
818 g_free (drop_target);
819}
820
821/* handle dropped raw data */
822static void
823receive_dropped_raw (CajaIconContainer *container, const char *raw_data, int length, const char *direct_save_uri, GdkDragContext *context, int x, int y)
824{
825 char *drop_target;
826
827 if (raw_data == NULL((void*)0))
828 {
829 return;
830 }
831
832 drop_target = caja_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
833
834 g_signal_emit_by_name (container, "handle_raw",
835 raw_data,
836 length,
837 drop_target,
838 direct_save_uri,
839 gdk_drag_context_get_selected_action (context),
840 x, y);
841
842 g_free (drop_target);
843}
844
845static int
846auto_scroll_timeout_callback (gpointer data)
847{
848 CajaIconContainer *container;
849 GtkWidget *widget;
850 float x_scroll_delta, y_scroll_delta;
851 GdkRectangle exposed_area;
852 GtkAllocation allocation;
853
854 g_assert (CAJA_IS_ICON_CONTAINER (data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = (caja_icon_container_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_38
= 1; else _g_boolean_var_38 = 0; _g_boolean_var_38; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-icon-dnd.c"
, 854, ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (data)"
); } while (0)
;
855 widget = GTK_WIDGET (data)((((GtkWidget*) (void *) ((data)))));
856 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
857
858 if (container->details->dnd_info->drag_info.waiting_to_autoscroll
859 && container->details->dnd_info->drag_info.start_auto_scroll_in > g_get_monotonic_time())
860 {
861 /* not yet */
862 return TRUE(!(0));
863 }
864
865 container->details->dnd_info->drag_info.waiting_to_autoscroll = FALSE(0);
866
867 caja_drag_autoscroll_calculate_delta (widget, &x_scroll_delta, &y_scroll_delta);
868 if (x_scroll_delta == 0 && y_scroll_delta == 0)
869 {
870 /* no work */
871 return TRUE(!(0));
872 }
873
874 /* Clear the old dnd highlight frame */
875 dnd_highlight_queue_redraw (widget);
876
877 if (!caja_icon_container_scroll (container, (int)x_scroll_delta, (int)y_scroll_delta))
878 {
879 /* the scroll value got pinned to a min or max adjustment value,
880 * we ended up not scrolling
881 */
882 return TRUE(!(0));
883 }
884
885 /* Make sure the dnd highlight frame is redrawn */
886 dnd_highlight_queue_redraw (widget);
887
888 /* update cached drag start offsets */
889 container->details->dnd_info->drag_info.start_x -= x_scroll_delta;
890 container->details->dnd_info->drag_info.start_y -= y_scroll_delta;
891
892 /* Due to a glitch in GtkLayout, whe need to do an explicit draw of the exposed
893 * area.
894 * Calculate the size of the area we need to draw
895 */
896 gtk_widget_get_allocation (widget, &allocation);
897 exposed_area.x = allocation.x;
898 exposed_area.y = allocation.y;
899 exposed_area.width = allocation.width;
900 exposed_area.height = allocation.height;
901
902 if (x_scroll_delta > 0)
903 {
904 exposed_area.x = exposed_area.width - x_scroll_delta;
905 }
906 else if (x_scroll_delta < 0)
907 {
908 exposed_area.width = -x_scroll_delta;
909 }
910
911 if (y_scroll_delta > 0)
912 {
913 exposed_area.y = exposed_area.height - y_scroll_delta;
914 }
915 else if (y_scroll_delta < 0)
916 {
917 exposed_area.height = -y_scroll_delta;
918 }
919
920 /* offset it to 0, 0 */
921 exposed_area.x -= allocation.x;
922 exposed_area.y -= allocation.y;
923
924 gtk_widget_queue_draw_area (widget,
925 exposed_area.x,
926 exposed_area.y,
927 exposed_area.width,
928 exposed_area.height);
929
930 return TRUE(!(0));
931}
932
933static void
934set_up_auto_scroll_if_needed (CajaIconContainer *container)
935{
936 caja_drag_autoscroll_start (&container->details->dnd_info->drag_info,
937 GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))),
938 auto_scroll_timeout_callback,
939 container);
940}
941
942static void
943stop_auto_scroll (CajaIconContainer *container)
944{
945 caja_drag_autoscroll_stop (&container->details->dnd_info->drag_info);
946}
947
948static void
949handle_local_move (CajaIconContainer *container,
950 double world_x, double world_y)
951{
952 GList *moved_icons, *p;
953 CajaFile *file;
954 char screen_string[32];
955 GdkScreen *screen;
956 time_t now;
957 CajaDragSelectionItem *item = NULL((void*)0);
958 CajaIcon *icon = NULL((void*)0);
959
960 if (container->details->auto_layout)
961 {
962 return;
963 }
964
965 time (&now);
966
967 /* Move and select the icons. */
968 moved_icons = NULL((void*)0);
969 for (p = container->details->dnd_info->drag_info.selection_list; p != NULL((void*)0); p = p->next)
970 {
971 item = p->data;
972
973 icon = caja_icon_container_get_icon_by_uri
974 (container, item->uri);
975
976 if (icon == NULL((void*)0))
977 {
978 /* probably dragged from another screen. Add it to
979 * this screen
980 */
981
982 file = caja_file_get_by_uri (item->uri);
983
984 screen = gtk_widget_get_screen (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
985 g_snprintf (screen_string, sizeof (screen_string), "%d",
986 gdk_x11_screen_get_screen_number (screen));
987 caja_file_set_metadata (file,
988 CAJA_METADATA_KEY_SCREEN"screen",
989 NULL((void*)0), screen_string);
990 caja_file_set_time_metadata (file,
991 CAJA_METADATA_KEY_ICON_POSITION_TIMESTAMP"caja-icon-position-timestamp", now);
992
993 caja_icon_container_add (container, CAJA_ICON_CONTAINER_ICON_DATA (file)((CajaIconData *) (file)));
994
995 icon = caja_icon_container_get_icon_by_uri
996 (container, item->uri);
997 }
998
999 if (item->got_icon_position)
1000 {
1001 caja_icon_container_move_icon
1002 (container, icon,
1003 world_x + item->icon_x, world_y + item->icon_y,
1004 icon->scale,
1005 TRUE(!(0)), TRUE(!(0)), TRUE(!(0)));
1006 }
1007 moved_icons = g_list_prepend (moved_icons, icon);
1008 }
1009 caja_icon_container_select_list_unselect_others
1010 (container, moved_icons);
1011 /* Might have been moved in a way that requires adjusting scroll region. */
1012 caja_icon_container_update_scroll_region (container);
1013 g_list_free (moved_icons);
1014}
1015
1016static void
1017handle_nonlocal_move (CajaIconContainer *container,
1018 GdkDragAction action,
1019 int x, int y,
1020 const char *target_uri,
1021 gboolean icon_hit)
1022{
1023 GList *source_uris, *p;
1024 GArray *source_item_locations;
1025 gboolean free_target_uri, is_rtl;
1026 GtkAllocation allocation;
1027
1028 if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0))
1029 {
1030 return;
1031 }
1032
1033 source_uris = NULL((void*)0);
1034 for (p = container->details->dnd_info->drag_info.selection_list; p != NULL((void*)0); p = p->next)
1035 {
1036 /* do a shallow copy of all the uri strings of the copied files */
1037 source_uris = g_list_prepend (source_uris, ((CajaDragSelectionItem *)p->data)->uri);
1038 }
1039 source_uris = g_list_reverse (source_uris);
1040
1041 is_rtl = caja_icon_container_is_layout_rtl (container);
1042
1043 source_item_locations = g_array_new (FALSE(0), TRUE(!(0)), sizeof (GdkPoint));
1044 if (!icon_hit)
1045 {
1046 int index;
1047
1048 /* Drop onto a container. Pass along the item points to allow placing
1049 * the items in their same relative positions in the new container.
1050 */
1051 source_item_locations = g_array_set_size (source_item_locations,
1052 g_list_length (container->details->dnd_info->drag_info.selection_list));
1053
1054 for (index = 0, p = container->details->dnd_info->drag_info.selection_list;
1055 p != NULL((void*)0); index++, p = p->next)
1056 {
1057 int item_x;
1058
1059 item_x = ((CajaDragSelectionItem *)p->data)->icon_x;
1060 if (is_rtl)
1061 item_x = -item_x - ((CajaDragSelectionItem *)p->data)->icon_width;
1062 g_array_index (source_item_locations, GdkPoint, index)(((GdkPoint*) (void *) (source_item_locations)->data) [(index
)])
.x = item_x;
1063 g_array_index (source_item_locations, GdkPoint, index)(((GdkPoint*) (void *) (source_item_locations)->data) [(index
)])
.y =
1064 ((CajaDragSelectionItem *)p->data)->icon_y;
1065 }
1066 }
1067
1068 free_target_uri = FALSE(0);
1069 /* Rewrite internal desktop URIs to the normal target uri */
1070 if (eel_uri_is_desktop (target_uri))
1071 {
1072 target_uri = caja_get_desktop_directory_uri ();
1073 free_target_uri = TRUE(!(0));
1074 }
1075
1076 if (is_rtl)
1077 {
1078 gtk_widget_get_allocation (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), &allocation);
1079 x = CANVAS_WIDTH (container, allocation)((allocation.width - container->details->left_margin - container
->details->right_margin) / ((((EelCanvas*) (void *) ((container
)))))->pixels_per_unit)
- x;
1080 }
1081
1082 /* start the copy */
1083 g_signal_emit_by_name (container, "move_copy_items",
1084 source_uris,
1085 source_item_locations,
1086 target_uri,
1087 action,
1088 x, y);
1089
1090 if (free_target_uri)
1091 {
1092 g_free ((char *)target_uri);
1093 }
1094
1095 g_list_free (source_uris);
1096 g_array_free (source_item_locations, TRUE(!(0)));
1097}
1098
1099static char *
1100caja_icon_container_find_drop_target (CajaIconContainer *container,
1101 GdkDragContext *context,
1102 int x, int y,
1103 gboolean *icon_hit,
1104 gboolean rewrite_desktop)
1105{
1106 CajaIcon *drop_target_icon;
1107 double world_x, world_y;
1108
1109 if (icon_hit)
1110 {
1111 *icon_hit = FALSE(0);
1112 }
1113
1114 if (!container->details->dnd_info->drag_info.got_drop_data_type)
1115 {
1116 return NULL((void*)0);
1117 }
1118
1119 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), x, y, &world_x, &world_y);
1120
1121 /* FIXME bugzilla.gnome.org 42485:
1122 * These "can_accept_items" tests need to be done by
1123 * the icon view, not here. This file is not supposed to know
1124 * that the target is a file.
1125 */
1126
1127 /* Find the item we hit with our drop, if any */
1128 drop_target_icon = caja_icon_container_item_at (container, world_x, world_y);
1129 if (drop_target_icon != NULL((void*)0))
1130 {
1131 char *icon_uri;
1132
1133 icon_uri = caja_icon_container_get_icon_uri (container, drop_target_icon);
1134 if (icon_uri != NULL((void*)0))
1135 {
1136 CajaFile *file;
1137
1138 file = caja_file_get_by_uri (icon_uri);
1139
1140 if (!caja_drag_can_accept_info (file,
1141 container->details->dnd_info->drag_info.data_type,
1142 container->details->dnd_info->drag_info.selection_list))
1143 {
1144 /* the item we dropped our selection on cannot accept the items,
1145 * do the same thing as if we just dropped the items on the canvas
1146 */
1147 drop_target_icon = NULL((void*)0);
1148 }
1149
1150 g_free (icon_uri);
1151 caja_file_unref (file);
1152 }
1153 }
1154
1155 if (drop_target_icon == NULL((void*)0))
1156 {
1157 char *container_uri;
1158
1159 if (icon_hit)
1160 {
1161 *icon_hit = FALSE(0);
1162 }
1163
1164 container_uri = get_container_uri (container);
1165
1166 if (rewrite_desktop &&
1167 container_uri != NULL((void*)0) &&
1168 eel_uri_is_desktop (container_uri))
1169 {
1170 g_free (container_uri);
1171 container_uri = caja_get_desktop_directory_uri ();
1172 }
1173
1174 return container_uri;
1175 }
1176
1177 if (icon_hit)
1178 {
1179 *icon_hit = TRUE(!(0));
1180 }
1181 return caja_icon_container_get_icon_drop_target_uri (container, drop_target_icon);
1182}
1183
1184static gboolean
1185selection_is_image_file (GList *selection_list)
1186{
1187 const char *mime_type;
1188 CajaDragSelectionItem *selected_item;
1189 gboolean result;
1190 GFile *location;
1191 GFileInfo *info;
1192
1193 /* Make sure only one item is selected */
1194 if (selection_list == NULL((void*)0) ||
1195 selection_list->next != NULL((void*)0))
1196 {
1197 return FALSE(0);
1198 }
1199
1200 selected_item = selection_list->data;
1201
1202 mime_type = NULL((void*)0);
1203
1204 location = g_file_new_for_uri (selected_item->uri);
1205 info = g_file_query_info (location,
1206 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type",
1207 0, NULL((void*)0), NULL((void*)0));
1208 if (info)
1209 {
1210 mime_type = g_file_info_get_content_type (info);
1211 }
1212
1213 result = eel_istr_has_prefix (mime_type, "image/");
1214
1215 if (info)
1216 {
1217 g_object_unref (info);
1218 }
1219 g_object_unref (location);
1220
1221 return result;
1222}
1223
1224
1225static void
1226caja_icon_container_receive_dropped_icons (CajaIconContainer *container,
1227 GdkDragContext *context,
1228 int x, int y)
1229{
1230 char *drop_target;
1231 gboolean local_move_only;
1232 double world_x, world_y;
1233 gboolean icon_hit;
1234 GdkDragAction action, real_action;
1235
1236 drop_target = NULL((void*)0);
1237
1238 if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0))
1239 {
1240 return;
1241 }
1242
1243 real_action = gdk_drag_context_get_selected_action (context);
1244
1245 if (real_action == GDK_ACTION_ASK)
1246 {
1247 /* FIXME bugzilla.gnome.org 42485: This belongs in FMDirectoryView, not here. */
1248 /* Check for special case items in selection list */
1249 if (caja_drag_selection_includes_special_link (container->details->dnd_info->drag_info.selection_list))
1250 {
1251 /* We only want to move the trash */
1252 action = GDK_ACTION_MOVE;
1253 }
1254 else
1255 {
1256 action = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK;
1257
1258 if (selection_is_image_file (container->details->dnd_info->drag_info.selection_list))
1259 {
1260 action |= CAJA_DND_ACTION_SET_AS_BACKGROUND;
1261 }
1262 }
1263 real_action = caja_drag_drop_action_ask (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))), action);
1264 }
1265
1266 if (real_action == (GdkDragAction) CAJA_DND_ACTION_SET_AS_BACKGROUND)
1267 {
1268 CajaDragSelectionItem *selected_item;
1269
1270 selected_item = container->details->dnd_info->drag_info.selection_list->data;
1271 eel_background_set_dropped_image (eel_get_widget_background (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container)))))),
1272 real_action, selected_item->uri);
1273 return;
1274 }
1275
1276 if (real_action > 0)
1277 {
1278 eel_canvas_window_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
1279 x + gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))))),
1280 y + gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container))))))),
1281 &world_x, &world_y);
1282
1283 drop_target = caja_icon_container_find_drop_target (container,
1284 context, x, y, &icon_hit, FALSE(0));
1285
1286 local_move_only = FALSE(0);
1287 if (!icon_hit && real_action == GDK_ACTION_MOVE)
1288 {
1289 /* we can just move the icon positions if the move ended up in
1290 * the item's parent container
1291 */
1292 local_move_only = caja_icon_container_selection_items_local
1293 (container, container->details->dnd_info->drag_info.selection_list);
1294 }
1295
1296 if (local_move_only)
1297 {
1298 handle_local_move (container, world_x, world_y);
1299 }
1300 else
1301 {
1302 handle_nonlocal_move (container, real_action, world_x, world_y, drop_target, icon_hit);
1303 }
1304 }
1305
1306 g_free (drop_target);
1307 caja_drag_destroy_selection_list (container->details->dnd_info->drag_info.selection_list);
1308 container->details->dnd_info->drag_info.selection_list = NULL((void*)0);
1309}
1310
1311static void
1312caja_icon_container_get_drop_action (CajaIconContainer *container,
1313 GdkDragContext *context,
1314 int x, int y,
1315 int *action)
1316{
1317 char *drop_target;
1318 gboolean icon_hit;
1319 CajaIcon *icon;
1320 double world_x, world_y;
1321
1322 icon_hit = FALSE(0);
1323 if (!container->details->dnd_info->drag_info.got_drop_data_type)
1324 {
1325 /* drag_data_received_callback didn't get called yet */
1326 return;
1327 }
1328
1329 /* find out if we're over an icon */
1330 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), x, y, &world_x, &world_y);
1331
1332 icon = caja_icon_container_item_at (container, world_x, world_y);
1333
1334 *action = 0;
1335
1336 /* case out on the type of object being dragged */
1337 switch (container->details->dnd_info->drag_info.data_type)
1338 {
1339 case CAJA_ICON_DND_MATE_ICON_LIST:
1340 if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0))
1341 {
1342 return;
1343 }
1344 drop_target = caja_icon_container_find_drop_target (container,
1345 context, x, y, &icon_hit, FALSE(0));
1346 if (!drop_target)
1347 {
1348 return;
1349 }
1350 caja_drag_default_drop_action_for_icons (context, drop_target,
1351 container->details->dnd_info->drag_info.selection_list,
1352 action);
1353 g_free (drop_target);
1354 break;
1355 case CAJA_ICON_DND_URI_LIST:
1356 drop_target = caja_icon_container_find_drop_target (container,
1357 context, x, y, &icon_hit, FALSE(0));
1358 *action = caja_drag_default_drop_action_for_uri_list (context, drop_target);
1359
1360 g_free (drop_target);
1361 break;
1362
1363 /* handle emblems by setting the action if we're over an object */
1364 case CAJA_ICON_DND_KEYWORD:
1365 if (icon != NULL((void*)0))
1366 {
1367 *action = gdk_drag_context_get_suggested_action (context);
1368 }
1369 break;
1370
1371 case CAJA_ICON_DND_NETSCAPE_URL:
1372 *action = caja_drag_default_drop_action_for_netscape_url (context);
1373 break;
1374
1375 case CAJA_ICON_DND_COLOR:
1376 case CAJA_ICON_DND_BGIMAGE:
1377 case CAJA_ICON_DND_RESET_BACKGROUND:
1378 case CAJA_ICON_DND_ROOTWINDOW_DROP:
1379 *action = gdk_drag_context_get_suggested_action (context);
1380 break;
1381
1382 case CAJA_ICON_DND_TEXT:
1383 case CAJA_ICON_DND_XDNDDIRECTSAVE:
1384 case CAJA_ICON_DND_RAW:
1385 *action = GDK_ACTION_COPY;
1386 break;
1387 }
1388}
1389
1390static void
1391set_drop_target (CajaIconContainer *container,
1392 CajaIcon *icon)
1393{
1394 CajaIcon *old_icon;
1395
1396 /* Check if current drop target changed, update icon drop
1397 * higlight if needed.
1398 */
1399 old_icon = container->details->drop_target;
1400 if (icon == old_icon)
1401 {
1402 return;
1403 }
1404
1405 /* Remember the new drop target for the next round. */
1406 container->details->drop_target = icon;
1407 caja_icon_container_update_icon (container, old_icon);
1408 caja_icon_container_update_icon (container, icon);
1409}
1410
1411static void
1412caja_icon_dnd_update_drop_target (CajaIconContainer *container,
1413 GdkDragContext *context,
1414 int x, int y)
1415{
1416 CajaIcon *icon;
1417 double world_x, world_y;
1418
1419 g_assert (CAJA_IS_ICON_CONTAINER (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_39 = 1; else _g_boolean_var_39 = 0
; _g_boolean_var_39; }), 1)) ; else g_assertion_message_expr (
((gchar*) 0), "caja-icon-dnd.c", 1419, ((const char*) (__func__
)), "CAJA_IS_ICON_CONTAINER (container)"); } while (0)
;
1420
1421 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))), x, y, &world_x, &world_y);
1422
1423 /* Find the item we hit with our drop, if any. */
1424 icon = caja_icon_container_item_at (container, world_x, world_y);
1425
1426 /* FIXME bugzilla.gnome.org 42485:
1427 * These "can_accept_items" tests need to be done by
1428 * the icon view, not here. This file is not supposed to know
1429 * that the target is a file.
1430 */
1431
1432 /* Find if target icon accepts our drop. */
1433 if (icon != NULL((void*)0) && (container->details->dnd_info->drag_info.data_type != CAJA_ICON_DND_KEYWORD))
1434 {
1435 CajaFile *file;
1436 char *uri;
1437
1438 uri = caja_icon_container_get_icon_uri (container, icon);
1439 file = caja_file_get_by_uri (uri);
1440 g_free (uri);
1441
1442 if (!caja_drag_can_accept_info (file,
1443 container->details->dnd_info->drag_info.data_type,
1444 container->details->dnd_info->drag_info.selection_list))
1445 {
1446 icon = NULL((void*)0);
1447 }
1448
1449 caja_file_unref (file);
1450 }
1451
1452 set_drop_target (container, icon);
1453}
1454
1455static void
1456caja_icon_container_free_drag_data (CajaIconContainer *container)
1457{
1458 CajaIconDndInfo *dnd_info;
1459
1460 dnd_info = container->details->dnd_info;
1461
1462 dnd_info->drag_info.got_drop_data_type = FALSE(0);
1463
1464 if (dnd_info->shadow != NULL((void*)0))
1465 {
1466 eel_canvas_item_destroy (dnd_info->shadow);
1467 dnd_info->shadow = NULL((void*)0);
1468 }
1469
1470 if (dnd_info->drag_info.selection_data != NULL((void*)0))
1471 {
1472 gtk_selection_data_free (dnd_info->drag_info.selection_data);
1473 dnd_info->drag_info.selection_data = NULL((void*)0);
1474 }
1475
1476 if (dnd_info->drag_info.direct_save_uri != NULL((void*)0))
1477 {
1478 g_free (dnd_info->drag_info.direct_save_uri);
1479 dnd_info->drag_info.direct_save_uri = NULL((void*)0);
1480 }
1481}
1482
1483static void
1484drag_leave_callback (GtkWidget *widget,
1485 GdkDragContext *context,
1486 guint32 time,
1487 gpointer data)
1488{
1489 CajaIconDndInfo *dnd_info;
1490
1491 dnd_info = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->dnd_info;
1492
1493 if (dnd_info->shadow != NULL((void*)0))
1494 eel_canvas_item_hide (dnd_info->shadow);
1495
1496 stop_dnd_highlight (widget);
1497
1498 set_drop_target (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))), NULL((void*)0));
1499 stop_auto_scroll (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))));
1500 caja_icon_container_free_drag_data(CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))));
1501}
1502
1503static void
1504drag_begin_callback (GtkWidget *widget,
1505 GdkDragContext *context,
1506 gpointer data)
1507{
1508 CajaIconContainer *container;
1509 cairo_surface_t *surface;
1510 double x1, y1, x2, y2, winx, winy;
1511 int x_offset, y_offset;
1512 int start_x, start_y;
1513
1514 container = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))));
1515
1516 start_x = container->details->dnd_info->drag_info.start_x +
1517 gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
1518 start_y = container->details->dnd_info->drag_info.start_y +
1519 gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
1520
1521 /* create a pixmap and mask to drag with */
1522 surface = caja_icon_canvas_item_get_drag_surface (container->details->drag_icon->item);
1523
1524 /* compute the image's offset */
1525 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (container->details->drag_icon->item)((((EelCanvasItem*) (void *) ((container->details->drag_icon
->item)))))
,
1526 &x1, &y1, &x2, &y2);
1527 eel_canvas_world_to_window (EEL_CANVAS (container)((((EelCanvas*) (void *) ((container))))),
1528 x1, y1, &winx, &winy);
1529 x_offset = start_x - winx;
1530 y_offset = start_y - winy;
1531
1532 cairo_surface_set_device_offset (surface, -x_offset, -y_offset);
1533 gtk_drag_set_icon_surface (context, surface);
1534 cairo_surface_destroy (surface);
1535}
1536
1537void
1538caja_icon_dnd_begin_drag (CajaIconContainer *container,
1539 GdkDragAction actions,
1540 int button,
1541 GdkEventMotion *event,
1542 int start_x,
1543 int start_y)
1544{
1545 CajaIconDndInfo *dnd_info;
1546
1547 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_40
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_40 = 1; else _g_boolean_var_40 = 0
; _g_boolean_var_40; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1548 g_return_if_fail (event != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_41
; if (event != ((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__)), "event != NULL");
return; } } while (0)
;
1549
1550 dnd_info = container->details->dnd_info;
1551 g_return_if_fail (dnd_info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_42
; if (dnd_info != ((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__)), "dnd_info != NULL"
); return; } } while (0)
;
1552
1553 /* Notice that the event is in bin_window coordinates, because of
1554 the way the canvas handles events.
1555 */
1556 dnd_info->drag_info.start_x = start_x -
1557 gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
1558 dnd_info->drag_info.start_y = start_y -
1559 gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)((((GtkScrollable*) (void *) ((container)))))));
1560
1561 /* start the drag */
1562 gtk_drag_begin_with_coordinates (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))),
1563 dnd_info->drag_info.target_list,
1564 actions,
1565 button,
1566 (GdkEvent *) event,
1567 dnd_info->drag_info.start_x,
1568 dnd_info->drag_info.start_y);
1569}
1570
1571static gboolean
1572drag_highlight_draw (GtkWidget *widget,
1573 cairo_t *cr,
1574 gpointer user_data)
1575{
1576 gint width, height;
1577 GdkWindow *window;
1578 GtkStyleContext *style;
1579
1580 window = gtk_widget_get_window (widget);
1581 width = gdk_window_get_width (window);
1582 height = gdk_window_get_height (window);
1583
1584 style = gtk_widget_get_style_context (widget);
1585
1586 gtk_style_context_save (style);
1587 gtk_style_context_add_class (style, GTK_STYLE_CLASS_DND"dnd");
1588 gtk_style_context_set_state (style, GTK_STATE_FLAG_FOCUSED);
1589
1590 gtk_render_frame (style,
1591 cr,
1592 0, 0, width, height);
1593
1594 gtk_style_context_restore (style);
1595
1596 return FALSE(0);
1597}
1598
1599/* Queue a redraw of the dnd highlight rect */
1600static void
1601dnd_highlight_queue_redraw (GtkWidget *widget)
1602{
1603 CajaIconDndInfo *dnd_info;
1604 int width, height;
1605 GtkAllocation allocation;
1606
1607 dnd_info = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->dnd_info;
1608
1609 if (!dnd_info->highlighted)
1610 {
1611 return;
1612 }
1613
1614 gtk_widget_get_allocation (widget, &allocation);
1615 width = allocation.width;
1616 height = allocation.height;
1617
1618 /* we don't know how wide the shadow is exactly,
1619 * so we expose a 10-pixel wide border
1620 */
1621 gtk_widget_queue_draw_area (widget,
1622 0, 0,
1623 width, 10);
1624 gtk_widget_queue_draw_area (widget,
1625 0, 0,
1626 10, height);
1627 gtk_widget_queue_draw_area (widget,
1628 0, height - 10,
1629 width, 10);
1630 gtk_widget_queue_draw_area (widget,
1631 width - 10, 0,
1632 10, height);
1633}
1634
1635static void
1636start_dnd_highlight (GtkWidget *widget)
1637{
1638 CajaIconDndInfo *dnd_info;
1639 GtkWidget *toplevel;
1640
1641 dnd_info = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->dnd_info;
1642
1643 toplevel = gtk_widget_get_toplevel (widget);
1644 if (toplevel != NULL((void*)0) &&
1645 g_object_get_data (G_OBJECT (toplevel)((((GObject*) (void *) ((toplevel))))), "is_desktop_window"))
1646 {
1647 return;
1648 }
1649
1650 if (!dnd_info->highlighted)
1651 {
1652 dnd_info->highlighted = TRUE(!(0));
1653 g_signal_connect_after (widget, "draw",g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw
))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
1654 G_CALLBACK (drag_highlight_draw),g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw
))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
1655 NULL)g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw
))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
;
1656 dnd_highlight_queue_redraw (widget);
1657 }
1658}
1659
1660static void
1661stop_dnd_highlight (GtkWidget *widget)
1662{
1663 CajaIconDndInfo *dnd_info;
1664
1665 dnd_info = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->dnd_info;
1666
1667 if (dnd_info->highlighted)
1668 {
1669 g_signal_handlers_disconnect_by_func (widget,g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (drag_highlight_draw), (((void*)0)))
1670 drag_highlight_draw,g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (drag_highlight_draw), (((void*)0)))
1671 NULL)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (drag_highlight_draw), (((void*)0)))
;
1672 dnd_highlight_queue_redraw (widget);
1673 dnd_info->highlighted = FALSE(0);
1674 }
1675}
1676
1677static gboolean
1678drag_motion_callback (GtkWidget *widget,
1679 GdkDragContext *context,
1680 int x, int y,
1681 guint32 time)
1682{
1683 int action;
1684
1685 caja_icon_container_ensure_drag_data (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))), context, time);
1686 caja_icon_container_position_shadow (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))), x, y);
1687 caja_icon_dnd_update_drop_target (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))), context, x, y);
1688 set_up_auto_scroll_if_needed (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))));
1689 /* Find out what the drop actions are based on our drag selection and
1690 * the drop target.
1691 */
1692 action = 0;
1693 caja_icon_container_get_drop_action (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))), context, x, y,
1694 &action);
1695 if (action != 0)
1696 {
1697 start_dnd_highlight (widget);
1698 }
1699
1700 gdk_drag_status (context, action, time);
1701
1702 return TRUE(!(0));
1703}
1704
1705static gboolean
1706drag_drop_callback (GtkWidget *widget,
1707 GdkDragContext *context,
1708 int x,
1709 int y,
1710 guint32 time,
1711 gpointer data)
1712{
1713 CajaIconDndInfo *dnd_info;
1714
1715 dnd_info = CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->dnd_info;
1716
1717 /* tell the drag_data_received callback that
1718 the drop occured and that it can actually
1719 process the actions.
1720 make sure it is going to be called at least once.
1721 */
1722 dnd_info->drag_info.drop_occured = TRUE(!(0));
1723
1724 get_data_on_first_target_we_support (widget, context, time, x, y);
1725
1726 return TRUE(!(0));
1727}
1728
1729void
1730caja_icon_dnd_end_drag (CajaIconContainer *container)
1731{
1732 CajaIconDndInfo *dnd_info;
1733
1734 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_43
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_43 = 1; else _g_boolean_var_43 = 0
; _g_boolean_var_43; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1735
1736 dnd_info = container->details->dnd_info;
1737 g_return_if_fail (dnd_info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_44
; if (dnd_info != ((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__)), "dnd_info != NULL"
); return; } } while (0)
;
1738 stop_auto_scroll (container);
1739 /* Do nothing.
1740 * Can that possibly be right?
1741 */
1742}
1743
1744/** this callback is called in 2 cases.
1745 It is called upon drag_motion events to get the actual data
1746 In that case, it just makes sure it gets the data.
1747 It is called upon drop_drop events to execute the actual
1748 actions on the received action. In that case, it actually first makes sure
1749 that we have got the data then processes it.
1750*/
1751
1752static void
1753drag_data_received_callback (GtkWidget *widget,
1754 GdkDragContext *context,
1755 int x,
1756 int y,
1757 GtkSelectionData *data,
1758 guint info,
1759 guint32 time,
1760 gpointer user_data)
1761{
1762 CajaDragInfo *drag_info;
1763 gboolean success;
1764
1765 drag_info = &(CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget)))))->details->dnd_info->drag_info);
1766
1767 drag_info->got_drop_data_type = TRUE(!(0));
1768 drag_info->data_type = info;
1769
1770 switch (info)
1771 {
1772 case CAJA_ICON_DND_MATE_ICON_LIST:
1773 caja_icon_container_dropped_icon_feedback (widget, data, x, y);
1774 break;
1775 case CAJA_ICON_DND_COLOR:
1776 case CAJA_ICON_DND_BGIMAGE:
1777 case CAJA_ICON_DND_KEYWORD:
1778 case CAJA_ICON_DND_URI_LIST:
1779 case CAJA_ICON_DND_TEXT:
1780 case CAJA_ICON_DND_RESET_BACKGROUND:
1781 case CAJA_ICON_DND_XDNDDIRECTSAVE:
1782 case CAJA_ICON_DND_RAW:
1783 /* Save the data so we can do the actual work on drop. */
1784 if (drag_info->selection_data != NULL((void*)0))
1785 {
1786 gtk_selection_data_free (drag_info->selection_data);
1787 }
1788 drag_info->selection_data = gtk_selection_data_copy (data);
1789 break;
1790
1791 /* Netscape keeps sending us the data, even though we accept the first drag */
1792 case CAJA_ICON_DND_NETSCAPE_URL:
1793 if (drag_info->selection_data != NULL((void*)0))
1794 {
1795 gtk_selection_data_free (drag_info->selection_data);
1796 drag_info->selection_data = gtk_selection_data_copy (data);
1797 }
1798 break;
1799 case CAJA_ICON_DND_ROOTWINDOW_DROP:
1800 /* Do nothing, this won't even happen, since we don't want to call get_data twice */
1801 break;
1802 }
1803
1804 /* this is the second use case of this callback.
1805 * we have to do the actual work for the drop.
1806 */
1807 if (drag_info->drop_occured)
1808 {
1809 EelBackground *background;
1810 char *tmp;
1811 const char *tmp_raw;
1812 int length;
1813
1814 success = FALSE(0);
1815 switch (info)
1816 {
1817 case CAJA_ICON_DND_MATE_ICON_LIST:
1818 caja_icon_container_receive_dropped_icons
1819 (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1820 context, x, y);
1821 break;
1822 case CAJA_ICON_DND_COLOR:
1823 receive_dropped_color (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1824 x, y,
1825 gdk_drag_context_get_selected_action (context),
1826 data);
1827 success = TRUE(!(0));
1828 break;
1829 case CAJA_ICON_DND_BGIMAGE:
1830 receive_dropped_tile_image
1831 (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1832 gdk_drag_context_get_selected_action (context),
1833 data);
1834 break;
1835 case CAJA_ICON_DND_KEYWORD:
1836 receive_dropped_keyword
1837 (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1838 (char *) gtk_selection_data_get_data (data), x, y);
1839 break;
1840 case CAJA_ICON_DND_NETSCAPE_URL:
1841 receive_dropped_netscape_url
1842 (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1843 (char *) gtk_selection_data_get_data (data), context, x, y);
1844 success = TRUE(!(0));
1845 break;
1846 case CAJA_ICON_DND_URI_LIST:
1847 receive_dropped_uri_list
1848 (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1849 (char *) gtk_selection_data_get_data (data), context, x, y);
1850 success = TRUE(!(0));
1851 break;
1852 case CAJA_ICON_DND_TEXT:
1853 tmp = gtk_selection_data_get_text (data);
1854 receive_dropped_text
1855 (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1856 (char *) tmp, context, x, y);
1857 success = TRUE(!(0));
1858 g_free (tmp);
1859 break;
1860 case CAJA_ICON_DND_RAW:
1861 length = gtk_selection_data_get_length (data);
1862 tmp_raw = gtk_selection_data_get_data (data);
1863 receive_dropped_raw
1864 (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))),
1865 tmp_raw, length, drag_info->direct_save_uri,
1866 context, x, y);
1867 success = TRUE(!(0));
1868 break;
1869 case CAJA_ICON_DND_RESET_BACKGROUND:
1870 background = eel_get_widget_background (widget);
1871 if (background != NULL((void*)0))
1872 {
1873 eel_background_reset (background);
1874 }
1875 gtk_drag_finish (context, FALSE(0), FALSE(0), time);
1876 break;
1877 case CAJA_ICON_DND_ROOTWINDOW_DROP:
1878 /* Do nothing, everything is done by the sender */
1879 break;
1880 case CAJA_ICON_DND_XDNDDIRECTSAVE:
1881 {
1882 const guchar *selection_data;
1883 gint selection_length;
1884 gint selection_format;
1885
1886 selection_data = gtk_selection_data_get_data (drag_info->selection_data);
1887 selection_length = gtk_selection_data_get_length (drag_info->selection_data);
1888 selection_format = gtk_selection_data_get_format (drag_info->selection_data);
1889
1890 if (selection_format == 8 &&
1891 selection_length == 1 &&
1892 selection_data[0] == 'F')
1893 {
1894 gtk_drag_get_data (widget, context,
1895 gdk_atom_intern (CAJA_ICON_DND_RAW_TYPE"application/octet-stream",
1896 FALSE(0)),
1897 time);
1898 return;
1899 }
1900 else if (selection_format == 8 &&
1901 selection_length == 1 &&
1902 selection_data[0] == 'F' &&
1903 drag_info->direct_save_uri != NULL((void*)0))
1904 {
1905 GdkPoint p;
1906 GFile *location;
1907
1908 location = g_file_new_for_uri (drag_info->direct_save_uri);
1909
1910 caja_file_changes_queue_file_added (location);
1911 p.x = x;
1912 p.y = y;
1913 caja_file_changes_queue_schedule_position_set (
1914 location,
1915 p,
1916 gdk_x11_screen_get_screen_number (
1917 gtk_widget_get_screen (widget)));
1918 g_object_unref (location);
1919 caja_file_changes_consume_changes (TRUE(!(0)));
1920 success = TRUE(!(0));
1921 }
1922 break;
1923 } /* CAJA_ICON_DND_XDNDDIRECTSAVE */
1924 }
1925 gtk_drag_finish (context, success, FALSE(0), time);
1926
1927 caja_icon_container_free_drag_data (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))));
1928
1929 set_drop_target (CAJA_ICON_CONTAINER (widget)((((CajaIconContainer*) (void *) ((widget))))), NULL((void*)0));
1930
1931 /* reinitialise it for the next dnd */
1932 drag_info->drop_occured = FALSE(0);
1933 }
1934
1935}
1936
1937void
1938caja_icon_dnd_init (CajaIconContainer *container)
1939{
1940 GtkTargetList *targets;
1941 int n_elements;
1942
1943 g_return_if_fail (container != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_45
; if (container != ((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__)), "container != NULL"
); return; } } while (0)
;
1944 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_46
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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_46 = 1; else _g_boolean_var_46 = 0
; _g_boolean_var_46; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1945
1946
1947 container->details->dnd_info = g_new0 (CajaIconDndInfo, 1)(CajaIconDndInfo *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (CajaIconDndInfo); 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; }))
;
1948 caja_drag_init (&container->details->dnd_info->drag_info,
1949 drag_types, G_N_ELEMENTS (drag_types)(sizeof (drag_types) / sizeof ((drag_types)[0])), TRUE(!(0)));
1950
1951 /* Set up the widget as a drag destination.
1952 * (But not a source, as drags starting from this widget will be
1953 * implemented by dealing with events manually.)
1954 */
1955 n_elements = G_N_ELEMENTS (drop_types)(sizeof (drop_types) / sizeof ((drop_types)[0]));
1956 if (!caja_icon_container_get_is_desktop (container))
1957 {
1958 /* Don't set up rootwindow drop */
1959 n_elements -= 1;
1960 }
1961 gtk_drag_dest_set (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))),
1962 0,
1963 drop_types, n_elements,
1964 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
1965
1966 targets = gtk_drag_dest_get_target_list (GTK_WIDGET (container)((((GtkWidget*) (void *) ((container))))));
1967 gtk_target_list_add_text_targets (targets, CAJA_ICON_DND_TEXT);
1968
1969
1970 /* Messages for outgoing drag. */
1971 g_signal_connect (container, "drag_begin",g_signal_connect_data ((container), ("drag_begin"), (((GCallback
) (drag_begin_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1972 G_CALLBACK (drag_begin_callback), NULL)g_signal_connect_data ((container), ("drag_begin"), (((GCallback
) (drag_begin_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1973 g_signal_connect (container, "drag_data_get",g_signal_connect_data ((container), ("drag_data_get"), (((GCallback
) (drag_data_get_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1974 G_CALLBACK (drag_data_get_callback), NULL)g_signal_connect_data ((container), ("drag_data_get"), (((GCallback
) (drag_data_get_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1975 g_signal_connect (container, "drag_end",g_signal_connect_data ((container), ("drag_end"), (((GCallback
) (drag_end_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1976 G_CALLBACK (drag_end_callback), NULL)g_signal_connect_data ((container), ("drag_end"), (((GCallback
) (drag_end_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1977
1978 /* Messages for incoming drag. */
1979 g_signal_connect (container, "drag_data_received",g_signal_connect_data ((container), ("drag_data_received"), (
((GCallback) (drag_data_received_callback))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
1980 G_CALLBACK (drag_data_received_callback), NULL)g_signal_connect_data ((container), ("drag_data_received"), (
((GCallback) (drag_data_received_callback))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
;
1981 g_signal_connect (container, "drag_motion",g_signal_connect_data ((container), ("drag_motion"), (((GCallback
) (drag_motion_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1982 G_CALLBACK (drag_motion_callback), NULL)g_signal_connect_data ((container), ("drag_motion"), (((GCallback
) (drag_motion_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1983 g_signal_connect (container, "drag_drop",g_signal_connect_data ((container), ("drag_drop"), (((GCallback
) (drag_drop_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1984 G_CALLBACK (drag_drop_callback), NULL)g_signal_connect_data ((container), ("drag_drop"), (((GCallback
) (drag_drop_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1985 g_signal_connect (container, "drag_leave",g_signal_connect_data ((container), ("drag_leave"), (((GCallback
) (drag_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1986 G_CALLBACK (drag_leave_callback), NULL)g_signal_connect_data ((container), ("drag_leave"), (((GCallback
) (drag_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1987}
1988
1989void
1990caja_icon_dnd_fini (CajaIconContainer *container)
1991{
1992 g_return_if_fail (CAJA_IS_ICON_CONTAINER (container))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_47
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (caja_icon_container_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__)), "CAJA_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1993
1994 if (container->details->dnd_info != NULL((void*)0))
1995 {
1996 stop_auto_scroll (container);
1997
1998 caja_drag_finalize (&container->details->dnd_info->drag_info);
1999 container->details->dnd_info = NULL((void*)0);
2000 }
2001}
diff --git a/2024-07-29-023715-6438-1/report-f9f9ca.html b/2024-07-29-023715-6438-1/report-f9f9ca.html new file mode 100644 index 000000000..fedc264a5 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-f9f9ca.html @@ -0,0 +1,3086 @@ + + + +eel-labeled-image.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:eel/eel-labeled-image.c
Warning:line 1106, column 13
Value stored to 'y_alignment' 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 eel-labeled-image.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 -fdebug-compilation-dir=/rootdir/eel -fcoverage-compilation-dir=/rootdir/eel -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Eel" -I .. -I .. -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/local/share" -D SOURCE_DATADIR="../data" -D MATELOCALEDIR="/usr/local//locale" -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c eel-labeled-image.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* eel-labeled-image.c - A labeled image.
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Ramiro Estrugo <ramiro@eazel.com>
23*/
24
25#include <config.h>
26#include "eel-labeled-image.h"
27
28#include "eel-art-extensions.h"
29#include "eel-art-gtk-extensions.h"
30#include "eel-gtk-container.h"
31#include "eel-gtk-extensions.h"
32#include "eel-accessibility.h"
33#include <gtk/gtk.h>
34#include <gtk/gtk-a11y.h>
35#include <gdk/gdkkeysyms.h>
36#include <atk/atkimage.h>
37
38#define DEFAULT_SPACING0 0
39#define DEFAULT_X_PADDING0 0
40#define DEFAULT_Y_PADDING0 0
41#define DEFAULT_X_ALIGNMENT0.5 0.5
42#define DEFAULT_Y_ALIGNMENT0.5 0.5
43
44/* Signals */
45enum
46{
47 ACTIVATE,
48 LAST_SIGNAL
49};
50
51/* Arguments */
52enum
53{
54 PROP_0,
55 PROP_FILL,
56 PROP_LABEL,
57 PROP_LABEL_POSITION,
58 PROP_PIXBUF,
59 PROP_SHOW_IMAGE,
60 PROP_SHOW_LABEL,
61 PROP_SPACING,
62 PROP_X_ALIGNMENT,
63 PROP_X_PADDING,
64 PROP_Y_ALIGNMENT,
65 PROP_Y_PADDING
66};
67
68/* Detail member struct */
69struct EelLabeledImagePrivate
70{
71 GtkWidget *image;
72 GtkWidget *label;
73 GtkPositionType label_position;
74 gboolean show_label;
75 gboolean show_image;
76 guint spacing;
77 float x_alignment;
78 float y_alignment;
79 int x_padding;
80 int y_padding;
81 int fixed_image_height;
82 gboolean fill;
83};
84
85/* derived types so we can add our accessibility interfaces */
86static GType eel_labeled_image_button_get_type (void);
87static GType eel_labeled_image_check_button_get_type (void);
88static GType eel_labeled_image_radio_button_get_type (void);
89static GType eel_labeled_image_toggle_button_get_type (void);
90
91/* GtkWidgetClass methods */
92static GType eel_labeled_image_accessible_get_type (void);
93
94/* Private EelLabeledImage methods */
95static EelDimensions labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image);
96static EelDimensions labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image);
97static void labeled_image_ensure_label (EelLabeledImage *labeled_image);
98static void labeled_image_ensure_image (EelLabeledImage *labeled_image);
99static EelIRect labeled_image_get_content_bounds (const EelLabeledImage *labeled_image);
100static EelDimensions labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image);
101static void labeled_image_update_alignments (EelLabeledImage *labeled_image);
102static gboolean labeled_image_show_label (const EelLabeledImage *labeled_image);
103static gboolean labeled_image_show_image (const EelLabeledImage *labeled_image);
104
105static guint labeled_image_signals[LAST_SIGNAL] = { 0 };
106
107G_DEFINE_TYPE_WITH_PRIVATE (EelLabeledImage, eel_labeled_image, GTK_TYPE_CONTAINER)static void eel_labeled_image_init (EelLabeledImage *self); static
void eel_labeled_image_class_init (EelLabeledImageClass *klass
); static GType eel_labeled_image_get_type_once (void); static
gpointer eel_labeled_image_parent_class = ((void*)0); static
gint EelLabeledImage_private_offset; static void eel_labeled_image_class_intern_init
(gpointer klass) { eel_labeled_image_parent_class = g_type_class_peek_parent
(klass); if (EelLabeledImage_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EelLabeledImage_private_offset); eel_labeled_image_class_init
((EelLabeledImageClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer eel_labeled_image_get_instance_private
(EelLabeledImage *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EelLabeledImage_private_offset)))); } GType eel_labeled_image_get_type
(void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType eel_labeled_image_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_get_type ()), g_intern_static_string ("EelLabeledImage"
), sizeof (EelLabeledImageClass), (GClassInitFunc)(void (*)(void
)) eel_labeled_image_class_intern_init, sizeof (EelLabeledImage
), (GInstanceInitFunc)(void (*)(void)) eel_labeled_image_init
, (GTypeFlags) 0); { {{ EelLabeledImage_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (EelLabeledImagePrivate)); };} } return
g_define_type_id; }
108
109static void
110eel_labeled_image_init (EelLabeledImage *labeled_image)
111{
112 gtk_widget_set_has_window (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), FALSE(0));
113
114 labeled_image->details = eel_labeled_image_get_instance_private (labeled_image);
115 labeled_image->details->show_label = TRUE(!(0));
116 labeled_image->details->show_image = TRUE(!(0));
117 labeled_image->details->label_position = GTK_POS_BOTTOM;
118 labeled_image->details->spacing = DEFAULT_SPACING0;
119 labeled_image->details->x_padding = DEFAULT_X_PADDING0;
120 labeled_image->details->y_padding = DEFAULT_Y_PADDING0;
121 labeled_image->details->x_alignment = DEFAULT_X_ALIGNMENT0.5;
122 labeled_image->details->y_alignment = DEFAULT_Y_ALIGNMENT0.5;
123 labeled_image->details->fixed_image_height = 0;
124
125 eel_labeled_image_set_fill (labeled_image, FALSE(0));
126}
127
128static void
129eel_labeled_image_destroy (GtkWidget *object)
130{
131 EelLabeledImage *labeled_image;
132
133 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
134
135 if (labeled_image->details->image != NULL((void*)0))
136 {
137 gtk_widget_destroy (labeled_image->details->image);
138 }
139
140 if (labeled_image->details->label != NULL((void*)0))
141 {
142 gtk_widget_destroy (labeled_image->details->label);
143 }
144
145 GTK_WIDGET_CLASS (eel_labeled_image_parent_class)((((GtkWidgetClass*) (void *) ((eel_labeled_image_parent_class
)))))
->destroy (object);
146}
147
148/* GObjectClass methods */
149static void
150eel_labeled_image_set_property (GObject *object,
151 guint property_id,
152 const GValue *value,
153 GParamSpec *pspec)
154{
155 EelLabeledImage *labeled_image;
156
157 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_262
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_262
= 1; else _g_boolean_var_262 = 0; _g_boolean_var_262; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 157, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
158
159 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
160
161 switch (property_id)
162 {
163 case PROP_PIXBUF:
164 eel_labeled_image_set_pixbuf (labeled_image,
165 g_value_get_object (value));
166 break;
167
168 case PROP_LABEL:
169 eel_labeled_image_set_text (labeled_image, g_value_get_string (value));
170 break;
171
172 case PROP_LABEL_POSITION:
173 eel_labeled_image_set_label_position (labeled_image,
174 g_value_get_enum (value));
175 break;
176
177 case PROP_SHOW_LABEL:
178 eel_labeled_image_set_show_label (labeled_image,
179 g_value_get_boolean (value));
180 break;
181
182 case PROP_SHOW_IMAGE:
183 eel_labeled_image_set_show_image (labeled_image,
184 g_value_get_boolean (value));
185 break;
186
187 case PROP_SPACING:
188 eel_labeled_image_set_spacing (labeled_image,
189 g_value_get_uint (value));
190 break;
191
192 case PROP_X_PADDING:
193 eel_labeled_image_set_x_padding (labeled_image,
194 g_value_get_int (value));
195 break;
196
197 case PROP_Y_PADDING:
198 eel_labeled_image_set_y_padding (labeled_image,
199 g_value_get_int (value));
200 break;
201
202 case PROP_X_ALIGNMENT:
203 eel_labeled_image_set_x_alignment (labeled_image,
204 g_value_get_float (value));
205 break;
206
207 case PROP_Y_ALIGNMENT:
208 eel_labeled_image_set_y_alignment (labeled_image,
209 g_value_get_float (value));
210 break;
211
212 case PROP_FILL:
213 eel_labeled_image_set_fill (labeled_image,
214 g_value_get_boolean (value));
215 break;
216 default:
217 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 217
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
218 }
219}
220
221static void
222eel_labeled_image_get_property (GObject *object,
223 guint property_id,
224 GValue *value,
225 GParamSpec *pspec)
226{
227 EelLabeledImage *labeled_image;
228
229 g_assert (EEL_IS_LABELED_IMAGE (object))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_263
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((object)); GType __t = (eel_labeled_image_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_263
= 1; else _g_boolean_var_263 = 0; _g_boolean_var_263; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 229, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (object)"
); } while (0)
;
230
231 labeled_image = EEL_LABELED_IMAGE (object)((((EelLabeledImage*) (void *) ((object)))));
232
233 switch (property_id)
234 {
235 case PROP_LABEL:
236 if (labeled_image->details->label == NULL((void*)0))
237 {
238 g_value_set_string (value, NULL((void*)0));
239 }
240 else
241 {
242 g_value_set_string (value,
243 gtk_label_get_text (GTK_LABEL (((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
244 labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
));
245 }
246 break;
247
248 case PROP_LABEL_POSITION:
249 g_value_set_enum (value, eel_labeled_image_get_label_position (labeled_image));
250 break;
251
252 case PROP_SHOW_LABEL:
253 g_value_set_boolean (value, eel_labeled_image_get_show_label (labeled_image));
254 break;
255
256 case PROP_SHOW_IMAGE:
257 g_value_set_boolean (value, eel_labeled_image_get_show_image (labeled_image));
258 break;
259
260 case PROP_SPACING:
261 g_value_set_uint (value, eel_labeled_image_get_spacing (labeled_image));
262 break;
263
264 case PROP_X_PADDING:
265 g_value_set_int (value, eel_labeled_image_get_x_padding (labeled_image));
266 break;
267
268 case PROP_Y_PADDING:
269 g_value_set_int (value, eel_labeled_image_get_y_padding (labeled_image));
270 break;
271
272 case PROP_X_ALIGNMENT:
273 g_value_set_float (value, eel_labeled_image_get_x_alignment (labeled_image));
274 break;
275
276 case PROP_Y_ALIGNMENT:
277 g_value_set_float (value, eel_labeled_image_get_y_alignment (labeled_image));
278 break;
279
280 case PROP_FILL:
281 g_value_set_boolean (value, eel_labeled_image_get_fill (labeled_image));
282 break;
283
284 default:
285 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 285
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
286 }
287}
288
289/* GtkWidgetClass methods */
290static void
291eel_labeled_image_size_request (GtkWidget *widget,
292 GtkRequisition *requisition)
293{
294 EelLabeledImage *labeled_image;
295 EelDimensions content_dimensions;
296
297 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_264
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 297, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
298 g_assert (requisition != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_265
; if (requisition != ((void*)0)) _g_boolean_var_265 = 1; else
_g_boolean_var_265 = 0; _g_boolean_var_265; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 298, ((const char*) (__func__
)), "requisition != NULL"); } while (0)
;
299
300 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
301
302 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
303
304 requisition->width =
305 MAX (1, content_dimensions.width)(((1) > (content_dimensions.width)) ? (1) : (content_dimensions
.width))
+
306 2 * labeled_image->details->x_padding;
307
308 requisition->height =
309 MAX (1, content_dimensions.height)(((1) > (content_dimensions.height)) ? (1) : (content_dimensions
.height))
+
310 2 * labeled_image->details->y_padding;
311}
312
313static void
314eel_labeled_image_get_preferred_width (GtkWidget *widget,
315 gint *minimum_width,
316 gint *natural_width)
317{
318 GtkRequisition req;
319 eel_labeled_image_size_request (widget, &req);
320 *minimum_width = *natural_width = req.width;
321}
322
323static void
324eel_labeled_image_get_preferred_height (GtkWidget *widget,
325 gint *minimum_height,
326 gint *natural_height)
327{
328 GtkRequisition req;
329 eel_labeled_image_size_request (widget, &req);
330 *minimum_height = *natural_height = req.height;
331}
332
333static void
334eel_labeled_image_size_allocate (GtkWidget *widget,
335 GtkAllocation *allocation)
336{
337 EelLabeledImage *labeled_image;
338 EelIRect image_bounds;
339 EelIRect label_bounds;
340
341 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_266
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_266
= 1; else _g_boolean_var_266 = 0; _g_boolean_var_266; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 341, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
342 g_assert (allocation != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (allocation != ((void*)0)) _g_boolean_var_267 = 1; else _g_boolean_var_267
= 0; _g_boolean_var_267; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 342, ((const char*) (__func__
)), "allocation != NULL"); } while (0)
;
343
344 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
345
346 gtk_widget_set_allocation (widget, allocation);
347
348 label_bounds = eel_labeled_image_get_label_bounds (labeled_image);
349 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
350 labeled_image->details->label,
351 label_bounds);
352
353 image_bounds = eel_labeled_image_get_image_bounds (labeled_image);
354 eel_gtk_container_child_size_allocate (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
355 labeled_image->details->image,
356 image_bounds);
357}
358
359static int
360eel_labeled_image_draw (GtkWidget *widget,
361 cairo_t *cr)
362{
363 EelLabeledImage *labeled_image;
364 EelIRect label_bounds;
365 GtkStyleContext *context;
366
367 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_268
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_268
= 1; else _g_boolean_var_268 = 0; _g_boolean_var_268; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 367, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
368 g_assert (gtk_widget_get_realized (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_269
; if (gtk_widget_get_realized (widget)) _g_boolean_var_269 = 1
; else _g_boolean_var_269 = 0; _g_boolean_var_269; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-labeled-image.c", 368,
((const char*) (__func__)), "gtk_widget_get_realized (widget)"
); } while (0)
;
369
370 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
371
372 context = gtk_widget_get_style_context (widget);
373 gtk_style_context_save (context);
374
375 if (gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_SELECTED ||
376 gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_ACTIVE)
377 {
378 label_bounds = eel_labeled_image_get_label_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
379
380 gtk_widget_get_state_flags (widget);
381 gtk_render_background (context,
382 cr,
383 label_bounds.x0, label_bounds.y0,
384 label_bounds.x1 - label_bounds.x0,
385 label_bounds.y1 - label_bounds.y0);
386
387 gtk_render_frame (context,
388 cr,
389 label_bounds.x0, label_bounds.y0,
390 label_bounds.x1 - label_bounds.x0,
391 label_bounds.y1 - label_bounds.y0);
392 }
393
394 if (labeled_image_show_label (labeled_image))
395 {
396 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
397 labeled_image->details->label,
398 cr);
399 }
400
401 if (labeled_image_show_image (labeled_image))
402 {
403 eel_gtk_container_child_expose_event (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))),
404 labeled_image->details->image,
405 cr);
406 }
407
408 if (gtk_widget_has_focus (widget))
409 {
410 label_bounds = eel_labeled_image_get_image_bounds (EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget))))));
411 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_NORMAL, TRUE(!(0)));
412 gtk_render_focus (context,
413 cr,
414 label_bounds.x0, label_bounds.y0,
415 label_bounds.x1 - label_bounds.x0,
416 label_bounds.y1 - label_bounds.y0);
417 }
418
419 gtk_style_context_restore (context);
420
421 return FALSE(0);
422}
423
424static void
425eel_labeled_image_map (GtkWidget *widget)
426{
427 EelLabeledImage *labeled_image;
428
429 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_270
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_270
= 1; else _g_boolean_var_270 = 0; _g_boolean_var_270; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 429, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
430
431 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
432
433 gtk_widget_set_mapped (widget, TRUE(!(0)));
434
435 if (labeled_image_show_label (labeled_image))
436 {
437 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
438 }
439
440 if (labeled_image_show_image (labeled_image))
441 {
442 eel_gtk_container_child_map (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
443 }
444}
445
446static void
447eel_labeled_image_unmap (GtkWidget *widget)
448{
449 EelLabeledImage *labeled_image;
450
451 g_assert (EEL_IS_LABELED_IMAGE (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_271
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (eel_labeled_image_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_271
= 1; else _g_boolean_var_271 = 0; _g_boolean_var_271; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 451, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (widget)"
); } while (0)
;
452
453 labeled_image = EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
454
455 gtk_widget_set_mapped (widget, FALSE(0));
456
457 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->label);
458 eel_gtk_container_child_unmap (GTK_CONTAINER (widget)((((GtkContainer*) (void *) ((widget))))), labeled_image->details->image);
459}
460
461/* GtkContainerClass methods */
462static void
463eel_labeled_image_add (GtkContainer *container,
464 GtkWidget *child)
465{
466 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_272
= 1; else _g_boolean_var_272 = 0; _g_boolean_var_272; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 466, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
467
468 eel_gtk_container_child_add (container, child);
469}
470
471static void
472eel_labeled_image_remove (GtkContainer *container,
473 GtkWidget *child)
474{
475 EelLabeledImage *labeled_image;
476
477 g_assert (GTK_IS_LABEL (child) || GTK_IS_IMAGE (child))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_273
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child)); GType __t = ((gtk_label_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; })))) || ((
(__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((
child)); GType __t = ((gtk_image_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_273
= 1; else _g_boolean_var_273 = 0; _g_boolean_var_273; }), 1)
) ; else g_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 477, ((const char*) (__func__)), "GTK_IS_LABEL (child) || GTK_IS_IMAGE (child)"
); } while (0)
;
478
479 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));;
480
481 g_assert (child == labeled_image->details->image || child == labeled_image->details->label)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_274
; if (child == labeled_image->details->image || child ==
labeled_image->details->label) _g_boolean_var_274 = 1;
else _g_boolean_var_274 = 0; _g_boolean_var_274; }), 1)) ; else
g_assertion_message_expr ("Eel", "eel-labeled-image.c", 481,
((const char*) (__func__)), "child == labeled_image->details->image || child == labeled_image->details->label"
); } while (0)
;
482
483 eel_gtk_container_child_remove (container, child);
484
485 if (labeled_image->details->image == child)
486 {
487 labeled_image->details->image = NULL((void*)0);
488 }
489
490 if (labeled_image->details->label == child)
491 {
492 labeled_image->details->label = NULL((void*)0);
493 }
494}
495
496static void
497eel_labeled_image_forall (GtkContainer *container,
498 gboolean include_internals,
499 GtkCallback callback,
500 gpointer callback_data)
501{
502 EelLabeledImage *labeled_image;
503
504 g_assert (EEL_IS_LABELED_IMAGE (container))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_275
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (eel_labeled_image_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 504, ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (container)"
); } while (0)
;
505 g_assert (callback != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_276
; if (callback != ((void*)0)) _g_boolean_var_276 = 1; else _g_boolean_var_276
= 0; _g_boolean_var_276; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 505, ((const char*) (__func__
)), "callback != NULL"); } while (0)
;
506
507 labeled_image = EEL_LABELED_IMAGE (container)((((EelLabeledImage*) (void *) ((container)))));
508
509 if (include_internals)
510 {
511 if (labeled_image->details->image != NULL((void*)0))
512 {
513 (* callback) (labeled_image->details->image, callback_data);
514 }
515
516 if (labeled_image->details->label != NULL((void*)0))
517 {
518 (* callback) (labeled_image->details->label, callback_data);
519 }
520 }
521}
522
523/* Class init methods */
524static void
525eel_labeled_image_class_init (EelLabeledImageClass *labeled_image_class)
526{
527 GObjectClass *gobject_class = G_OBJECT_CLASS (labeled_image_class)((((GObjectClass*) (void *) ((labeled_image_class)))));
528 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (labeled_image_class)((((GtkWidgetClass*) (void *) ((labeled_image_class)))));
529 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (labeled_image_class)((((GtkContainerClass*) (void *) ((labeled_image_class)))));
530 GtkBindingSet *binding_set;
531
532 /* GObjectClass */
533 gobject_class->set_property = eel_labeled_image_set_property;
534 gobject_class->get_property = eel_labeled_image_get_property;
535
536 widget_class->destroy = eel_labeled_image_destroy;
537
538
539 /* GtkWidgetClass */
540 widget_class->size_allocate = eel_labeled_image_size_allocate;
541 widget_class->get_preferred_width = eel_labeled_image_get_preferred_width;
542 widget_class->get_preferred_height = eel_labeled_image_get_preferred_height;
543 widget_class->draw = eel_labeled_image_draw;
544
545 widget_class->map = eel_labeled_image_map;
546 widget_class->unmap = eel_labeled_image_unmap;
547
548 gtk_widget_class_set_accessible_type (widget_class, eel_labeled_image_accessible_get_type ());
549
550
551 /* GtkContainerClass */
552 container_class->add = eel_labeled_image_add;
553 container_class->remove = eel_labeled_image_remove;
554 container_class->forall = eel_labeled_image_forall;
555
556 labeled_image_signals[ACTIVATE] =
557 g_signal_new ("activate",
558 G_TYPE_FROM_CLASS (labeled_image_class)(((GTypeClass*) (labeled_image_class))->g_type),
559 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
560 G_STRUCT_OFFSET (EelLabeledImageClass,((glong) __builtin_offsetof(EelLabeledImageClass, activate))
561 activate)((glong) __builtin_offsetof(EelLabeledImageClass, activate)),
562 NULL((void*)0), NULL((void*)0),
563 g_cclosure_marshal_VOID__VOID,
564 G_TYPE_NONE((GType) ((1) << (2))), 0);
565 widget_class->activate_signal = labeled_image_signals[ACTIVATE];
566
567 binding_set = gtk_binding_set_by_class (gobject_class);
568
569 gtk_binding_entry_add_signal (binding_set,
570 GDK_KEY_Return0xff0d, 0,
571 "activate", 0);
572 gtk_binding_entry_add_signal (binding_set,
573 GDK_KEY_KP_Enter0xff8d, 0,
574 "activate", 0);
575 gtk_binding_entry_add_signal (binding_set,
576 GDK_KEY_space0x020, 0,
577 "activate", 0);
578
579
580 /* Properties */
581 g_object_class_install_property (
582 gobject_class,
583 PROP_PIXBUF,
584 g_param_spec_object ("pixbuf", NULL((void*)0), NULL((void*)0),
585 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ()), G_PARAM_READWRITE));
586
587 g_object_class_install_property (
588 gobject_class,
589 PROP_LABEL,
590 g_param_spec_string ("label", NULL((void*)0), NULL((void*)0),
591 "", G_PARAM_READWRITE));
592
593
594 g_object_class_install_property (
595 gobject_class,
596 PROP_LABEL_POSITION,
597 g_param_spec_enum ("label_position", NULL((void*)0), NULL((void*)0),
598 GTK_TYPE_POSITION_TYPE(gtk_position_type_get_type ()),
599 GTK_POS_BOTTOM,
600 G_PARAM_READWRITE));
601
602 g_object_class_install_property (
603 gobject_class,
604 PROP_SHOW_LABEL,
605 g_param_spec_boolean ("show_label", NULL((void*)0), NULL((void*)0),
606 TRUE(!(0)), G_PARAM_READWRITE));
607
608 g_object_class_install_property (
609 gobject_class,
610 PROP_SHOW_IMAGE,
611 g_param_spec_boolean ("show_image", NULL((void*)0), NULL((void*)0),
612 TRUE(!(0)), G_PARAM_READWRITE));
613
614
615 g_object_class_install_property (
616 gobject_class,
617 PROP_SPACING,
618 g_param_spec_uint ("spacing", NULL((void*)0), NULL((void*)0),
619 0,
620 G_MAXINT2147483647,
621 DEFAULT_SPACING0,
622 G_PARAM_READWRITE));
623
624 g_object_class_install_property (
625 gobject_class,
626 PROP_X_PADDING,
627 g_param_spec_int ("x_padding", NULL((void*)0), NULL((void*)0),
628 0,
629 G_MAXINT2147483647,
630 DEFAULT_X_PADDING0,
631 G_PARAM_READWRITE));
632
633 g_object_class_install_property (
634 gobject_class,
635 PROP_Y_PADDING,
636 g_param_spec_int ("y_padding", NULL((void*)0), NULL((void*)0),
637 0,
638 G_MAXINT2147483647,
639 DEFAULT_Y_PADDING0,
640 G_PARAM_READWRITE));
641
642 g_object_class_install_property (
643 gobject_class,
644 PROP_X_ALIGNMENT,
645 g_param_spec_float ("x_alignment", NULL((void*)0), NULL((void*)0),
646 0.0,
647 1.0,
648 DEFAULT_X_ALIGNMENT0.5,
649 G_PARAM_READWRITE));
650
651 g_object_class_install_property (
652 gobject_class,
653 PROP_Y_ALIGNMENT,
654 g_param_spec_float ("y_alignment", NULL((void*)0), NULL((void*)0),
655 0.0,
656 1.0,
657 DEFAULT_Y_ALIGNMENT0.5,
658 G_PARAM_READWRITE));
659
660 g_object_class_install_property (
661 gobject_class,
662 PROP_FILL,
663 g_param_spec_boolean ("fill", NULL((void*)0), NULL((void*)0),
664 FALSE(0),
665 G_PARAM_READWRITE));
666
667}
668
669/* Private EelLabeledImage methods */
670static gboolean
671is_fixed_height (const EelLabeledImage *labeled_image)
672{
673 return labeled_image->details->fixed_image_height > 0;
674}
675
676static EelDimensions
677labeled_image_get_image_dimensions (const EelLabeledImage *labeled_image)
678{
679 EelDimensions image_dimensions;
680 GtkRequisition image_requisition;
681
682 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_277
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_277 = 1; else _g_boolean_var_277 =
0; _g_boolean_var_277; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 682, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
683
684 if (!labeled_image_show_image (labeled_image))
685 {
686 return eel_dimensions_empty;
687 }
688
689 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
690
691 image_dimensions.width = (int) image_requisition.width;
692 image_dimensions.height = (int) image_requisition.height;
693
694 if (is_fixed_height (labeled_image))
695 {
696 image_dimensions.height = labeled_image->details->fixed_image_height;
697 }
698
699 return image_dimensions;
700}
701
702static EelDimensions
703labeled_image_get_label_dimensions (const EelLabeledImage *labeled_image)
704{
705 EelDimensions label_dimensions;
706 GtkRequisition label_requisition;
707
708 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_278
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", "eel-labeled-image.c", 708, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
709
710 if (!labeled_image_show_label (labeled_image))
711 {
712 return eel_dimensions_empty;
713 }
714
715 gtk_widget_get_preferred_size (labeled_image->details->label, &label_requisition, NULL((void*)0));
716
717 label_dimensions.width = (int) label_requisition.width;
718 label_dimensions.height = (int) label_requisition.height;
719
720 return label_dimensions;
721}
722
723static EelIRect
724labeled_image_get_image_bounds_fill (const EelLabeledImage *labeled_image)
725{
726 EelIRect image_bounds;
727 EelDimensions image_dimensions;
728 EelIRect content_bounds;
729 EelIRect bounds;
730
731 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_279
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_279 = 1; else _g_boolean_var_279 =
0; _g_boolean_var_279; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 731, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
732
733 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
734
735 if (eel_dimensions_are_empty (image_dimensions))
736 {
737 return eel_irect_empty;
738 }
739
740 content_bounds = labeled_image_get_content_bounds (labeled_image);
741 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
742
743 if (!labeled_image_show_label (labeled_image))
744 {
745 image_bounds = bounds;
746 }
747 else
748 {
749 switch (labeled_image->details->label_position)
750 {
751 case GTK_POS_LEFT:
752 image_bounds.y0 = bounds.y0;
753 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
754 image_bounds.y1 = bounds.y1;
755 image_bounds.x1 = bounds.x1;
756 break;
757
758 case GTK_POS_RIGHT:
759 image_bounds.y0 = bounds.y0;
760 image_bounds.x0 = bounds.x0;
761 image_bounds.y1 = bounds.y1;
762 image_bounds.x1 = content_bounds.x0 + image_dimensions.width;
763 break;
764
765 case GTK_POS_TOP:
766 image_bounds.x0 = bounds.x0;
767 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
768 image_bounds.x1 = bounds.x1;
769 image_bounds.y1 = bounds.y1;
770 break;
771
772 case GTK_POS_BOTTOM:
773 image_bounds.x0 = bounds.x0;
774 image_bounds.y0 = bounds.y0;
775 image_bounds.x1 = bounds.x1;
776 image_bounds.y1 = content_bounds.y0 + image_dimensions.height;
777 break;
778
779 default:
780 image_bounds.x0 = 0;
781 image_bounds.y0 = 0;
782 image_bounds.x1 = 0;
783 image_bounds.y1 = 0;
784 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 784
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
785 }
786 }
787
788 return image_bounds;
789}
790
791EelIRect
792eel_labeled_image_get_image_bounds (const EelLabeledImage *labeled_image)
793{
794 EelDimensions image_dimensions;
795 EelDimensions label_dimensions;
796 GtkRequisition image_requisition;
797 EelIRect image_bounds;
798 EelIRect content_bounds;
799
800 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_280
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
801
802 if (labeled_image->details->fill)
803 {
804 return labeled_image_get_image_bounds_fill (labeled_image);
805 }
806
807 /* get true real dimensions if we're in fixed height mode */
808 if (is_fixed_height (labeled_image) && labeled_image_show_image (labeled_image))
809 {
810 gtk_widget_get_preferred_size (labeled_image->details->image, &image_requisition, NULL((void*)0));
811 image_dimensions.width = (int) image_requisition.width;
812 image_dimensions.height = (int) image_requisition.height;
813 }
814 else
815 {
816 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
817 }
818
819 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
820
821 if (eel_dimensions_are_empty (image_dimensions))
822 {
823 return eel_irect_empty;
824 }
825
826 content_bounds = labeled_image_get_content_bounds (labeled_image);
827
828 if (!labeled_image_show_label (labeled_image))
829 {
830 image_bounds.x0 =
831 content_bounds.x0 +
832 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
833 image_bounds.y0 =
834 content_bounds.y0 +
835 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
836 }
837 else
838 {
839 switch (labeled_image->details->label_position)
840 {
841 case GTK_POS_LEFT:
842 image_bounds.x0 = content_bounds.x1 - image_dimensions.width;
843 image_bounds.y0 =
844 content_bounds.y0 +
845 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
846 break;
847
848 case GTK_POS_RIGHT:
849 image_bounds.x0 = content_bounds.x0;
850 image_bounds.y0 =
851 content_bounds.y0 +
852 (eel_irect_get_height (content_bounds) - image_dimensions.height) / 2;
853 break;
854
855 case GTK_POS_TOP:
856 image_bounds.x0 =
857 content_bounds.x0 +
858 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
859 image_bounds.y0 = content_bounds.y1 - image_dimensions.height;
860 break;
861
862 case GTK_POS_BOTTOM:
863 image_bounds.x0 =
864 content_bounds.x0 +
865 (eel_irect_get_width (content_bounds) - image_dimensions.width) / 2;
866
867 if (is_fixed_height (labeled_image))
868 {
869 image_bounds.y0 = content_bounds.y0 + eel_irect_get_height (content_bounds)
870 - image_dimensions.height
871 - label_dimensions.height
872 - labeled_image->details->spacing;
873 }
874 else
875 {
876 image_bounds.y0 = content_bounds.y0;
877 }
878
879 break;
880
881 default:
882 image_bounds.x0 = 0;
883 image_bounds.y0 = 0;
884 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 884
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
885 }
886 }
887
888 image_bounds.x1 = image_bounds.x0 + image_dimensions.width;
889 image_bounds.y1 = image_bounds.y0 + image_dimensions.height;
890
891 return image_bounds;
892}
893
894static EelIRect
895labeled_image_get_label_bounds_fill (const EelLabeledImage *labeled_image)
896{
897 EelIRect label_bounds;
898 EelDimensions label_dimensions;
899 EelIRect content_bounds;
900 EelIRect bounds;
901
902 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_281
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_281 = 1; else _g_boolean_var_281 =
0; _g_boolean_var_281; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 902, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
903
904 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
905
906 if (eel_dimensions_are_empty (label_dimensions))
907 {
908 return eel_irect_empty;
909 }
910
911 content_bounds = labeled_image_get_content_bounds (labeled_image);
912 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
913
914 /* Only the label is shown */
915 if (!labeled_image_show_image (labeled_image))
916 {
917 label_bounds = bounds;
918 /* Both label and image are shown */
919 }
920 else
921 {
922 switch (labeled_image->details->label_position)
923 {
924 case GTK_POS_LEFT:
925 label_bounds.y0 = bounds.y0;
926 label_bounds.x0 = bounds.x0;
927 label_bounds.y1 = bounds.y1;
928 label_bounds.x1 = content_bounds.x0 + label_dimensions.width;
929 break;
930
931 case GTK_POS_RIGHT:
932 label_bounds.y0 = bounds.y0;
933 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
934 label_bounds.y1 = bounds.y1;
935 label_bounds.x1 = bounds.x1;
936 break;
937
938 case GTK_POS_TOP:
939 label_bounds.x0 = bounds.x0;
940 label_bounds.y0 = bounds.y0;
941 label_bounds.x1 = bounds.x1;
942 label_bounds.y1 = content_bounds.y0 + label_dimensions.height;
943 break;
944
945 case GTK_POS_BOTTOM:
946 label_bounds.x0 = bounds.x0;
947 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
948 label_bounds.x1 = bounds.x1;
949 label_bounds.y1 = bounds.y1;
950 break;
951
952 default:
953 label_bounds.x0 = 0;
954 label_bounds.y0 = 0;
955 label_bounds.x1 = 0;
956 label_bounds.y1 = 0;
957 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 957
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
958 }
959 }
960
961 return label_bounds;
962}
963
964EelIRect
965eel_labeled_image_get_label_bounds (const EelLabeledImage *labeled_image)
966{
967 EelIRect label_bounds;
968 EelDimensions label_dimensions;
969 EelIRect content_bounds;
970
971 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), eel_irect_empty)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_282 = 1; else _g_boolean_var_282 =
0; _g_boolean_var_282; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (eel_irect_empty); } } while (0)
;
972
973 if (labeled_image->details->fill)
974 {
975 return labeled_image_get_label_bounds_fill (labeled_image);
976 }
977
978 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
979
980 if (eel_dimensions_are_empty (label_dimensions))
981 {
982 return eel_irect_empty;
983 }
984
985 content_bounds = labeled_image_get_content_bounds (labeled_image);
986
987 /* Only the label is shown */
988 if (!labeled_image_show_image (labeled_image))
989 {
990 label_bounds.x0 =
991 content_bounds.x0 +
992 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
993 label_bounds.y0 =
994 content_bounds.y0 +
995 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
996 /* Both label and image are shown */
997 }
998 else
999 {
1000 switch (labeled_image->details->label_position)
1001 {
1002 case GTK_POS_LEFT:
1003 label_bounds.x0 = content_bounds.x0;
1004 label_bounds.y0 =
1005 content_bounds.y0 +
1006 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1007 break;
1008
1009 case GTK_POS_RIGHT:
1010 label_bounds.x0 = content_bounds.x1 - label_dimensions.width;
1011 label_bounds.y0 =
1012 content_bounds.y0 +
1013 (eel_irect_get_height (content_bounds) - label_dimensions.height) / 2;
1014 break;
1015
1016 case GTK_POS_TOP:
1017 label_bounds.x0 =
1018 content_bounds.x0 +
1019 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1020 label_bounds.y0 = content_bounds.y0;
1021 break;
1022
1023 case GTK_POS_BOTTOM:
1024 label_bounds.x0 =
1025 content_bounds.x0 +
1026 (eel_irect_get_width (content_bounds) - label_dimensions.width) / 2;
1027 label_bounds.y0 = content_bounds.y1 - label_dimensions.height;
1028 break;
1029
1030 default:
1031 label_bounds.x0 = 0;
1032 label_bounds.y0 = 0;
1033 g_assert_not_reached ()do { g_assertion_message_expr ("Eel", "eel-labeled-image.c", 1033
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1034 }
1035 }
1036
1037 label_bounds.x1 = label_bounds.x0 + label_dimensions.width;
1038 label_bounds.y1 = label_bounds.y0 + label_dimensions.height;
1039
1040 return label_bounds;
1041}
1042
1043static void
1044labeled_image_update_alignments (EelLabeledImage *labeled_image)
1045{
1046
1047 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_283
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1047, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1048
1049 if (labeled_image->details->label != NULL((void*)0))
1050 {
1051 if (labeled_image->details->fill)
1052 {
1053 float x_alignment;
1054 float y_alignment;
1055
1056 x_alignment = gtk_label_get_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
1057 y_alignment = gtk_label_get_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
1058
1059 /* Only the label is shown */
1060 if (!labeled_image_show_image (labeled_image))
1061 {
1062 x_alignment = 0.5;
1063 y_alignment = 0.5;
1064 /* Both label and image are shown */
1065 }
1066 else
1067 {
1068 switch (labeled_image->details->label_position)
1069 {
1070 case GTK_POS_LEFT:
1071 x_alignment = 1.0;
1072 y_alignment = 0.5;
1073 break;
1074
1075 case GTK_POS_RIGHT:
1076 x_alignment = 0.0;
1077 y_alignment = 0.5;
1078 break;
1079
1080 case GTK_POS_TOP:
1081 x_alignment = 0.5;
1082 y_alignment = 1.0;
1083 break;
1084
1085 case GTK_POS_BOTTOM:
1086 x_alignment = 0.5;
1087 y_alignment = 0.0;
1088 break;
1089 }
1090
1091 }
1092
1093 gtk_label_set_xalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, x_alignment);
1094 gtk_label_set_yalign (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, y_alignment);
1095 }
1096 }
1097
1098 if (labeled_image->details->image != NULL((void*)0))
1099 {
1100 if (labeled_image->details->fill)
1101 {
1102 float x_alignment;
1103 float y_alignment;
1104
1105 x_alignment = gtk_widget_get_halign (labeled_image->details->image);
1106 y_alignment = gtk_widget_get_valign (labeled_image->details->image);
Value stored to 'y_alignment' is never read
1107
1108 /* Only the image is shown */
1109 if (!labeled_image_show_label (labeled_image))
1110 {
1111 x_alignment = 0.5;
1112 y_alignment = 0.5;
1113 /* Both label and image are shown */
1114 }
1115 else
1116 {
1117 switch (labeled_image->details->label_position)
1118 {
1119 case GTK_POS_LEFT:
1120 x_alignment = 0.0;
1121 y_alignment = 0.5;
1122 break;
1123
1124 case GTK_POS_RIGHT:
1125 x_alignment = 1.0;
1126 y_alignment = 0.5;
1127 break;
1128
1129 case GTK_POS_TOP:
1130 x_alignment = 0.5;
1131 y_alignment = 0.0;
1132 break;
1133
1134 case GTK_POS_BOTTOM:
1135 x_alignment = 0.5;
1136 y_alignment = 1.0;
1137 break;
1138 }
1139 }
1140
1141 gtk_widget_set_halign (labeled_image->details->image, x_alignment);
1142 gtk_widget_set_valign (labeled_image->details->image, y_alignment);
1143 }
1144 }
1145}
1146
1147static EelDimensions
1148labeled_image_get_content_dimensions (const EelLabeledImage *labeled_image)
1149{
1150 EelDimensions image_dimensions;
1151 EelDimensions label_dimensions;
1152 EelDimensions content_dimensions;
1153
1154 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_284
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_284 = 1; else _g_boolean_var_284 =
0; _g_boolean_var_284; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1154, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1155
1156 image_dimensions = labeled_image_get_image_dimensions (labeled_image);
1157 label_dimensions = labeled_image_get_label_dimensions (labeled_image);
1158
1159 content_dimensions = eel_dimensions_empty;
1160
1161 /* Both shown */
1162 if (!eel_dimensions_are_empty (image_dimensions) && !eel_dimensions_are_empty (label_dimensions))
1163 {
1164 content_dimensions.width =
1165 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1166 switch (labeled_image->details->label_position)
1167 {
1168 case GTK_POS_LEFT:
1169 case GTK_POS_RIGHT:
1170 content_dimensions.width =
1171 image_dimensions.width + labeled_image->details->spacing + label_dimensions.width;
1172 content_dimensions.height = MAX (image_dimensions.height, label_dimensions.height)(((image_dimensions.height) > (label_dimensions.height)) ?
(image_dimensions.height) : (label_dimensions.height))
;
1173 break;
1174
1175 case GTK_POS_TOP:
1176 case GTK_POS_BOTTOM:
1177 content_dimensions.width = MAX (image_dimensions.width, label_dimensions.width)(((image_dimensions.width) > (label_dimensions.width)) ? (
image_dimensions.width) : (label_dimensions.width))
;
1178 content_dimensions.height =
1179 image_dimensions.height + labeled_image->details->spacing + label_dimensions.height;
1180 break;
1181 }
1182 /* Only image shown */
1183 }
1184 else if (!eel_dimensions_are_empty (image_dimensions))
1185 {
1186 content_dimensions.width = image_dimensions.width;
1187 content_dimensions.height = image_dimensions.height;
1188 /* Only label shown */
1189 }
1190 else
1191 {
1192 content_dimensions.width = label_dimensions.width;
1193 content_dimensions.height = label_dimensions.height;
1194 }
1195
1196 return content_dimensions;
1197}
1198
1199static EelIRect
1200labeled_image_get_content_bounds (const EelLabeledImage *labeled_image)
1201{
1202 EelDimensions content_dimensions;
1203 EelIRect content_bounds;
1204 EelIRect bounds;
1205
1206 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_285
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_285 = 1; else _g_boolean_var_285 =
0; _g_boolean_var_285; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1206, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1207
1208 bounds = eel_gtk_widget_get_bounds (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1209
1210 content_dimensions = labeled_image_get_content_dimensions (labeled_image);
1211 content_bounds = eel_irect_align (bounds,
1212 content_dimensions.width,
1213 content_dimensions.height,
1214 labeled_image->details->x_alignment,
1215 labeled_image->details->y_alignment);
1216
1217 return content_bounds;
1218}
1219
1220static void
1221labeled_image_ensure_label (EelLabeledImage *labeled_image)
1222{
1223 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_286
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1223, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1224
1225 if (labeled_image->details->label != NULL((void*)0))
1226 {
1227 return;
1228 }
1229
1230 labeled_image->details->label = gtk_label_new (NULL((void*)0));
1231 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->label);
1232 gtk_widget_show (labeled_image->details->label);
1233}
1234
1235static void
1236labeled_image_ensure_image (EelLabeledImage *labeled_image)
1237{
1238 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_287
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_287 = 1; else _g_boolean_var_287 =
0; _g_boolean_var_287; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1238, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1239
1240 if (labeled_image->details->image != NULL((void*)0))
1241 {
1242 return;
1243 }
1244
1245 labeled_image->details->image = gtk_image_new ();
1246 gtk_container_add (GTK_CONTAINER (labeled_image)((((GtkContainer*) (void *) ((labeled_image))))), labeled_image->details->image);
1247 gtk_widget_show (labeled_image->details->image);
1248}
1249
1250static gboolean
1251labeled_image_show_image (const EelLabeledImage *labeled_image)
1252{
1253 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_288
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_288 = 1; else _g_boolean_var_288 =
0; _g_boolean_var_288; }), 1)) ; else g_assertion_message_expr
("Eel", "eel-labeled-image.c", 1253, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1254
1255 return labeled_image->details->image != NULL((void*)0) && labeled_image->details->show_image;
1256}
1257
1258static gboolean
1259labeled_image_show_label (const EelLabeledImage *labeled_image)
1260{
1261 g_assert (EEL_IS_LABELED_IMAGE (labeled_image))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_289
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1261, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (labeled_image)"); } while (0)
;
1262
1263 return labeled_image->details->label != NULL((void*)0) && labeled_image->details->show_label;
1264}
1265
1266/**
1267 * eel_labeled_image_new:
1268 * @text: Text to use for label or NULL.
1269 * @pixbuf: Pixbuf to use for image or NULL.
1270 *
1271 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1272 * NULL then the LabeledImage will show a label. If the &pixbuf parameter is not
1273 * NULL then the LabeledImage will show a pixbuf. Either of these can be NULL at
1274 * creation time.
1275 *
1276 * Later in the lifetime of the widget you can invoke methods that affect the
1277 * label and/or the image. If at creation time these were NULL, then they will
1278 * be created as neeeded.
1279 *
1280 * Thus, using this widget in place of EelImage or EelLabel is "free" with
1281 * only the GtkWidget and function call overhead.
1282 *
1283 */
1284GtkWidget*
1285eel_labeled_image_new (const char *text,
1286 GdkPixbuf *pixbuf)
1287{
1288 EelLabeledImage *labeled_image;
1289
1290 labeled_image = EEL_LABELED_IMAGE (gtk_widget_new (eel_labeled_image_get_type (), NULL))((((EelLabeledImage*) (void *) ((gtk_widget_new (eel_labeled_image_get_type
(), ((void*)0)))))))
;
1291
1292 if (text != NULL((void*)0))
1293 {
1294 eel_labeled_image_set_text (labeled_image, text);
1295 }
1296
1297 if (pixbuf != NULL((void*)0))
1298 {
1299 eel_labeled_image_set_pixbuf (labeled_image, pixbuf);
1300 }
1301
1302 labeled_image_update_alignments (labeled_image);
1303
1304 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1305}
1306
1307/**
1308 * eel_labeled_image_new_from_file_name:
1309 * @text: Text to use for label or NULL.
1310 * @file_name: File name of picture to use for pixbuf. Cannot be NULL.
1311 *
1312 * Returns A newly allocated EelLabeledImage. If the &text parameter is not
1313 * NULL then the LabeledImage will show a label.
1314 *
1315 */
1316GtkWidget*
1317eel_labeled_image_new_from_file_name (const char *text,
1318 const char *pixbuf_file_name)
1319{
1320 EelLabeledImage *labeled_image;
1321
1322 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_290
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_290 = 1;
else _g_boolean_var_290 = 0; _g_boolean_var_290; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1323
1324 labeled_image = EEL_LABELED_IMAGE (eel_labeled_image_new (text, NULL))((((EelLabeledImage*) (void *) ((eel_labeled_image_new (text,
((void*)0)))))))
;
1325 eel_labeled_image_set_pixbuf_from_file_name (labeled_image, pixbuf_file_name);
1326 return GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))));
1327}
1328
1329/**
1330 * eel_labeled_image_set_label_position:
1331 * @labeled_image: A EelLabeledImage.
1332 * @label_position: The position of the label with respect to the image.
1333 *
1334 * Set the position of the label with respect to the image as follows:
1335 *
1336 * GTK_POS_LEFT:
1337 * [ <label> <image> ]
1338 *
1339 * GTK_POS_RIGHT:
1340 * [ <image> <label> ]
1341 *
1342 * GTK_POS_TOP:
1343 * [ <label> ]
1344 * [ <image> ]
1345 *
1346 * GTK_POS_BOTTOM:
1347 * [ <image> ]
1348 * [ <label> ]
1349 *
1350 */
1351void
1352eel_labeled_image_set_label_position (EelLabeledImage *labeled_image,
1353 GtkPositionType label_position)
1354{
1355 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_291
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1356 g_return_if_fail (label_position >= GTK_POS_LEFT)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_292
; if (label_position >= GTK_POS_LEFT) _g_boolean_var_292 =
1; else _g_boolean_var_292 = 0; _g_boolean_var_292; }), 1)))
{ } else { g_return_if_fail_warning ("Eel", ((const char*) (
__func__)), "label_position >= GTK_POS_LEFT"); return; } }
while (0)
;
1357 g_return_if_fail (label_position <= GTK_POS_BOTTOM)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_293
; if (label_position <= GTK_POS_BOTTOM) _g_boolean_var_293
= 1; else _g_boolean_var_293 = 0; _g_boolean_var_293; }), 1)
)) { } else { g_return_if_fail_warning ("Eel", ((const char*)
(__func__)), "label_position <= GTK_POS_BOTTOM"); return;
} } while (0)
;
1358
1359 if (labeled_image->details->label_position == label_position)
1360 {
1361 return;
1362 }
1363
1364 labeled_image->details->label_position = label_position;
1365
1366 labeled_image_update_alignments (labeled_image);
1367
1368 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1369}
1370
1371/**
1372 * eel_labeled_image_get_label_postiion:
1373 * @labeled_image: A EelLabeledImage.
1374 *
1375 * Returns an enumeration indicating the position of the label with respect to the image.
1376 */
1377GtkPositionType
1378eel_labeled_image_get_label_position (const EelLabeledImage *labeled_image)
1379{
1380 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_294
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_294 = 1; else _g_boolean_var_294 =
0; _g_boolean_var_294; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1381
1382 return labeled_image->details->label_position;
1383}
1384
1385/**
1386 * eel_labeled_image_set_show_label:
1387 * @labeled_image: A EelLabeledImage.
1388 * @show_image: A boolean value indicating whether the label should be shown.
1389 *
1390 * Update the labeled image to either show or hide the internal label widget.
1391 * This function doesnt have any effect if the LabeledImage doesnt already
1392 * contain an label.
1393 */
1394void
1395eel_labeled_image_set_show_label (EelLabeledImage *labeled_image,
1396 gboolean show_label)
1397{
1398 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_295
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1399
1400 if (labeled_image->details->show_label == show_label)
1401 {
1402 return;
1403 }
1404
1405 labeled_image->details->show_label = show_label;
1406
1407 if (labeled_image->details->label != NULL((void*)0))
1408 {
1409 if (labeled_image->details->show_label)
1410 {
1411 gtk_widget_show (labeled_image->details->label);
1412 }
1413 else
1414 {
1415 gtk_widget_hide (labeled_image->details->label);
1416 }
1417 }
1418
1419 labeled_image_update_alignments (labeled_image);
1420
1421 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1422}
1423
1424/**
1425 * eel_labeled_image_get_show_label:
1426 * @labeled_image: A EelLabeledImage.
1427 *
1428 * Returns a boolean value indicating whether the internal label is shown.
1429 */
1430gboolean
1431eel_labeled_image_get_show_label (const EelLabeledImage *labeled_image)
1432{
1433 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_296
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_296 = 1; else _g_boolean_var_296 =
0; _g_boolean_var_296; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1434
1435 return labeled_image->details->show_label;
1436}
1437
1438/**
1439 * eel_labeled_image_set_show_image:
1440 * @labeled_image: A EelLabeledImage.
1441 * @show_image: A boolean value indicating whether the image should be shown.
1442 *
1443 * Update the labeled image to either show or hide the internal image widget.
1444 * This function doesnt have any effect if the LabeledImage doesnt already
1445 * contain an image.
1446 */
1447void
1448eel_labeled_image_set_show_image (EelLabeledImage *labeled_image,
1449 gboolean show_image)
1450{
1451 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_297
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1452
1453 if (labeled_image->details->show_image == show_image)
1454 {
1455 return;
1456 }
1457
1458 labeled_image->details->show_image = show_image;
1459
1460 if (labeled_image->details->image != NULL((void*)0))
1461 {
1462 if (labeled_image->details->show_image)
1463 {
1464 gtk_widget_show (labeled_image->details->image);
1465 }
1466 else
1467 {
1468 gtk_widget_hide (labeled_image->details->image);
1469 }
1470 }
1471
1472 labeled_image_update_alignments (labeled_image);
1473
1474 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1475}
1476
1477/**
1478 * eel_labeled_image_get_show_image:
1479 * @labeled_image: A EelLabeledImage.
1480 *
1481 * Returns a boolean value indicating whether the internal image is shown.
1482 */
1483gboolean
1484eel_labeled_image_get_show_image (const EelLabeledImage *labeled_image)
1485{
1486 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_298
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_298 = 1; else _g_boolean_var_298 =
0; _g_boolean_var_298; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1487
1488 return labeled_image->details->show_image;
1489}
1490
1491
1492/**
1493 * eel_labeled_image_set_fixed_image_height:
1494 * @labeled_image: A EelLabeledImage.
1495 * @fixed_image_height: The new fixed image height.
1496 *
1497 * Normally, we measure the height of images, but it's sometimes useful
1498 * to use a fixed height for all the images. This routine sets the
1499 * image height to the passed in value
1500 *
1501 */
1502void
1503eel_labeled_image_set_fixed_image_height (EelLabeledImage *labeled_image,
1504 int new_height)
1505{
1506 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_299
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_299 = 1; else _g_boolean_var_299 =
0; _g_boolean_var_299; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1507
1508 if (labeled_image->details->fixed_image_height == new_height)
1509 {
1510 return;
1511 }
1512
1513 labeled_image->details->fixed_image_height = new_height;
1514
1515 labeled_image_update_alignments (labeled_image);
1516
1517 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1518}
1519
1520/**
1521 * eel_labeled_image_set_selected:
1522 * @labeled_image: A EelLabeledImage.
1523 * @selected: A boolean value indicating whether the labeled image
1524 * should be selected.
1525 *
1526 * Selects or deselects the labeled image.
1527 *
1528 */
1529void
1530eel_labeled_image_set_selected (EelLabeledImage *labeled_image,
1531 gboolean selected)
1532{
1533 GtkStateFlags state;
1534 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_300
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_300 = 1; else _g_boolean_var_300 =
0; _g_boolean_var_300; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1535
1536 state = selected ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_NORMAL;
1537
1538 gtk_widget_set_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), state, TRUE(!(0)));
1539 gtk_widget_set_state_flags (labeled_image->details->image, state, TRUE(!(0)));
1540 gtk_widget_set_state_flags (labeled_image->details->label, state, TRUE(!(0)));
1541
1542}
1543
1544/**
1545 * eel_labeled_image_get_selected:
1546 * @labeled_image: A EelLabeledImage.
1547 *
1548 * Returns the selected state of the labeled image.
1549 *
1550 */
1551gboolean
1552eel_labeled_image_get_selected (EelLabeledImage *labeled_image)
1553{
1554 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_301
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return ((0)); } } while (0)
;
1555
1556 return gtk_widget_get_state_flags (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image)))))) == GTK_STATE_FLAG_SELECTED;
1557}
1558
1559/**
1560 * eel_labeled_image_set_spacing:
1561 * @labeled_image: A EelLabeledImage.
1562 * @spacing: The new spacing between label and image.
1563 *
1564 * Set the spacing between label and image. This will only affect
1565 * the geometry of the widget if both a label and image are currently
1566 * visible.
1567 *
1568 */
1569void
1570eel_labeled_image_set_spacing (EelLabeledImage *labeled_image,
1571 guint spacing)
1572{
1573 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_302
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_302 = 1; else _g_boolean_var_302 =
0; _g_boolean_var_302; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1574
1575 if (labeled_image->details->spacing == spacing)
1576 {
1577 return;
1578 }
1579
1580 labeled_image->details->spacing = spacing;
1581
1582 labeled_image_update_alignments (labeled_image);
1583
1584 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1585}
1586
1587/**
1588 * eel_labeled_image_get_spacing:
1589 * @labeled_image: A EelLabeledImage.
1590 *
1591 * Returns: The spacing between the label and image.
1592 */
1593guint
1594eel_labeled_image_get_spacing (const EelLabeledImage *labeled_image)
1595{
1596 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_303
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1597
1598 return labeled_image->details->spacing;
1599}
1600
1601/**
1602 * eel_labeled_image_set_x_padding:
1603 * @labeled_image: A EelLabeledImage.
1604 * @x_padding: The new horizontal padding.
1605 *
1606 * Set horizontal padding for the EelLabeledImage. The padding
1607 * attribute work just like that in GtkMisc.
1608 */
1609void
1610eel_labeled_image_set_x_padding (EelLabeledImage *labeled_image,
1611 int x_padding)
1612{
1613 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_304
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_304 = 1; else _g_boolean_var_304 =
0; _g_boolean_var_304; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1614
1615 x_padding = MAX (0, x_padding)(((0) > (x_padding)) ? (0) : (x_padding));
1616
1617 if (labeled_image->details->x_padding == x_padding)
1618 {
1619 return;
1620 }
1621
1622 labeled_image->details->x_padding = x_padding;
1623 labeled_image_update_alignments (labeled_image);
1624 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1625}
1626
1627/**
1628 * eel_labeled_image_get_x_padding:
1629 * @labeled_image: A EelLabeledImage.
1630 *
1631 * Returns: The horizontal padding for the LabeledImage's content.
1632 */
1633int
1634eel_labeled_image_get_x_padding (const EelLabeledImage *labeled_image)
1635{
1636 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_305
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_305 = 1; else _g_boolean_var_305 =
0; _g_boolean_var_305; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1637
1638 return labeled_image->details->x_padding;
1639}
1640
1641/**
1642 * eel_labeled_image_set_y_padding:
1643 * @labeled_image: A EelLabeledImage.
1644 * @x_padding: The new vertical padding.
1645 *
1646 * Set vertical padding for the EelLabeledImage. The padding
1647 * attribute work just like that in GtkMisc.
1648 */
1649void
1650eel_labeled_image_set_y_padding (EelLabeledImage *labeled_image,
1651 int y_padding)
1652{
1653 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_306
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_306 = 1; else _g_boolean_var_306 =
0; _g_boolean_var_306; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1654
1655 y_padding = MAX (0, y_padding)(((0) > (y_padding)) ? (0) : (y_padding));
1656
1657 if (labeled_image->details->y_padding == y_padding)
1658 {
1659 return;
1660 }
1661
1662 labeled_image->details->y_padding = y_padding;
1663 labeled_image_update_alignments (labeled_image);
1664 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1665}
1666
1667/**
1668 * eel_labeled_image_get_x_padding:
1669 * @labeled_image: A EelLabeledImage.
1670 *
1671 * Returns: The vertical padding for the LabeledImage's content.
1672 */
1673int
1674eel_labeled_image_get_y_padding (const EelLabeledImage *labeled_image)
1675{
1676 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_307
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_307 = 1; else _g_boolean_var_307 =
0; _g_boolean_var_307; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1677
1678 return labeled_image->details->y_padding;
1679}
1680
1681/**
1682 * eel_labeled_image_set_x_alignment:
1683 * @labeled_image: A EelLabeledImage.
1684 * @x_alignment: The new horizontal alignment.
1685 *
1686 * Set horizontal alignment for the EelLabeledImage's content.
1687 * The 'content' is the union of the image and label. The alignment
1688 * attribute work just like that in GtkMisc.
1689 */
1690void
1691eel_labeled_image_set_x_alignment (EelLabeledImage *labeled_image,
1692 float x_alignment)
1693{
1694 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_308
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_308 = 1; else _g_boolean_var_308 =
0; _g_boolean_var_308; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1695
1696 x_alignment = MAX (0, x_alignment)(((0) > (x_alignment)) ? (0) : (x_alignment));
1697 x_alignment = MIN (1.0, x_alignment)(((1.0) < (x_alignment)) ? (1.0) : (x_alignment));
1698
1699 if (labeled_image->details->x_alignment == x_alignment)
1700 {
1701 return;
1702 }
1703
1704 labeled_image->details->x_alignment = x_alignment;
1705 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1706}
1707
1708/**
1709 * eel_labeled_image_get_x_alignment:
1710 * @labeled_image: A EelLabeledImage.
1711 *
1712 * Returns: The horizontal alignment for the LabeledImage's content.
1713 */
1714float
1715eel_labeled_image_get_x_alignment (const EelLabeledImage *labeled_image)
1716{
1717 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_309
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1718
1719 return labeled_image->details->x_alignment;
1720}
1721
1722/**
1723 * eel_labeled_image_set_y_alignment:
1724 * @labeled_image: A EelLabeledImage.
1725 * @y_alignment: The new vertical alignment.
1726 *
1727 * Set vertical alignment for the EelLabeledImage's content.
1728 * The 'content' is the union of the image and label. The alignment
1729 * attribute work just like that in GtkMisc.
1730 */
1731void
1732eel_labeled_image_set_y_alignment (EelLabeledImage *labeled_image,
1733 float y_alignment)
1734{
1735 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_310
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_310 = 1; else _g_boolean_var_310 =
0; _g_boolean_var_310; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1736
1737 y_alignment = MAX (0, y_alignment)(((0) > (y_alignment)) ? (0) : (y_alignment));
1738 y_alignment = MIN (1.0, y_alignment)(((1.0) < (y_alignment)) ? (1.0) : (y_alignment));
1739
1740 if (labeled_image->details->y_alignment == y_alignment)
1741 {
1742 return;
1743 }
1744
1745 labeled_image->details->y_alignment = y_alignment;
1746 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1747}
1748
1749/**
1750 * eel_labeled_image_get_y_alignment:
1751 * @labeled_image: A EelLabeledImage.
1752 *
1753 * Returns: The vertical alignment for the LabeledImage's content.
1754 */
1755float
1756eel_labeled_image_get_y_alignment (const EelLabeledImage *labeled_image)
1757{
1758 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_311
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_311 = 1; else _g_boolean_var_311 =
0; _g_boolean_var_311; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1759
1760 return labeled_image->details->y_alignment;
1761}
1762
1763/**
1764 * eel_labeled_image_set_fill:
1765 * @labeled_image: A EelLabeledImage.
1766 * @fill: A boolean value indicating whether the internal image and label
1767 * widgets should fill all the available allocation.
1768 *
1769 * By default the internal image and label wigets are sized to their natural
1770 * preferred geometry. You can use the 'fill' attribute of LabeledImage
1771 * to have the internal widgets fill as much of the LabeledImage allocation
1772 * as is available.
1773 */
1774void
1775eel_labeled_image_set_fill (EelLabeledImage *labeled_image,
1776 gboolean fill)
1777{
1778 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_312
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_312 = 1; else _g_boolean_var_312 =
0; _g_boolean_var_312; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
1779
1780 if (labeled_image->details->fill == fill)
1781 {
1782 return;
1783 }
1784
1785 labeled_image->details->fill = fill;
1786
1787 labeled_image_update_alignments (labeled_image);
1788
1789 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
1790}
1791
1792/**
1793 * eel_labeled_image_get_fill:
1794 * @labeled_image: A EelLabeledImage.
1795 *
1796 * Retruns a boolean value indicating whether the internal widgets fill
1797 * all the available allocation.
1798 */
1799gboolean
1800eel_labeled_image_get_fill (const EelLabeledImage *labeled_image)
1801{
1802 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_313
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_313 = 1; else _g_boolean_var_313 =
0; _g_boolean_var_313; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (0); } } while (0)
;
1803
1804 return labeled_image->details->fill;
1805}
1806
1807static void
1808eel_labled_set_mnemonic_widget (GtkWidget *image_widget,
1809 GtkWidget *mnemonic_widget)
1810{
1811 EelLabeledImage *image;
1812
1813 g_assert (EEL_IS_LABELED_IMAGE (image_widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_314
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((image_widget)); GType __t = (eel_labeled_image_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_assertion_message_expr
("Eel", "eel-labeled-image.c", 1813, ((const char*) (__func__
)), "EEL_IS_LABELED_IMAGE (image_widget)"); } while (0)
;
1814
1815 image = EEL_LABELED_IMAGE (image_widget)((((EelLabeledImage*) (void *) ((image_widget)))));
1816
1817 if (image->details->label)
1818 gtk_label_set_mnemonic_widget
1819 (GTK_LABEL (image->details->label)((((GtkLabel*) (void *) ((image->details->label))))), mnemonic_widget);
1820}
1821
1822/**
1823 * eel_labeled_image_button_new:
1824 * @text: Text to use for label or NULL.
1825 * @pixbuf: Pixbuf to use for image or NULL.
1826 *
1827 * Create a stock GtkButton with a EelLabeledImage child.
1828 *
1829 */
1830GtkWidget *
1831eel_labeled_image_button_new (const char *text,
1832 GdkPixbuf *pixbuf)
1833{
1834 GtkWidget *button;
1835 GtkWidget *labeled_image;
1836
1837 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1838 labeled_image = eel_labeled_image_new (text, pixbuf);
1839 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1840 eel_labled_set_mnemonic_widget (labeled_image, button);
1841 gtk_widget_show (labeled_image);
1842
1843 return button;
1844}
1845
1846/**
1847 * eel_labeled_image_button_new_from_file_name:
1848 * @text: Text to use for label or NULL.
1849 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1850 *
1851 * Create a stock GtkToggleButton with a EelLabeledImage child.
1852 *
1853 */
1854GtkWidget *
1855eel_labeled_image_button_new_from_file_name (const char *text,
1856 const char *pixbuf_file_name)
1857{
1858 GtkWidget *button;
1859 GtkWidget *labeled_image;
1860
1861 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_315
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_315 = 1;
else _g_boolean_var_315 = 0; _g_boolean_var_315; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1862
1863 button = g_object_new (eel_labeled_image_button_get_type (), NULL((void*)0));
1864 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1865 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), labeled_image);
1866 eel_labled_set_mnemonic_widget (labeled_image, button);
1867 gtk_widget_show (labeled_image);
1868
1869 return button;
1870}
1871
1872/**
1873 * eel_labeled_image_toggle_button_new:
1874 * @text: Text to use for label or NULL.
1875 * @pixbuf: Pixbuf to use for image or NULL.
1876 *
1877 * Create a stock GtkToggleButton with a EelLabeledImage child.
1878 *
1879 */
1880GtkWidget *
1881eel_labeled_image_toggle_button_new (const char *text,
1882 GdkPixbuf *pixbuf)
1883{
1884 GtkWidget *toggle_button;
1885 GtkWidget *labeled_image;
1886
1887 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1888 labeled_image = eel_labeled_image_new (text, pixbuf);
1889 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1890 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1891 gtk_widget_show (labeled_image);
1892
1893 return toggle_button;
1894}
1895
1896/**
1897 * eel_labeled_image_toggle_button_new_from_file_name:
1898 * @text: Text to use for label or NULL.
1899 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1900 *
1901 * Create a stock GtkToggleButton with a EelLabeledImage child.
1902 *
1903 */
1904GtkWidget *
1905eel_labeled_image_toggle_button_new_from_file_name (const char *text,
1906 const char *pixbuf_file_name)
1907{
1908 GtkWidget *toggle_button;
1909 GtkWidget *labeled_image;
1910
1911 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_316
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_316 = 1;
else _g_boolean_var_316 = 0; _g_boolean_var_316; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1912
1913 toggle_button = g_object_new (eel_labeled_image_toggle_button_get_type (), NULL((void*)0));
1914 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1915 gtk_container_add (GTK_CONTAINER (toggle_button)((((GtkContainer*) (void *) ((toggle_button))))), labeled_image);
1916 eel_labled_set_mnemonic_widget (labeled_image, toggle_button);
1917 gtk_widget_show (labeled_image);
1918
1919 return toggle_button;
1920}
1921
1922/**
1923 * eel_labeled_image_toggle_button_new:
1924 * @text: Text to use for label or NULL.
1925 * @pixbuf: Pixbuf to use for image or NULL.
1926 *
1927 * Create a stock GtkToggleButton with a EelLabeledImage child.
1928 *
1929 * Returns: the new radio button.
1930 */
1931GtkWidget *
1932eel_labeled_image_radio_button_new (const char *text,
1933 GdkPixbuf *pixbuf)
1934{
1935 GtkWidget *radio_button;
1936 GtkWidget *labeled_image;
1937
1938 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1939 labeled_image = eel_labeled_image_new (text, pixbuf);
1940 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1941 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1942 gtk_widget_show (labeled_image);
1943
1944 return radio_button;
1945}
1946
1947/**
1948 * eel_labeled_image_radio_button_new_from_file_name:
1949 * @text: Text to use for label or NULL.
1950 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
1951 *
1952 * Create a stock GtkRadioButton with a EelLabeledImage child.
1953 *
1954 * Returns: the new radio button.
1955 */
1956GtkWidget *
1957eel_labeled_image_radio_button_new_from_file_name (const char *text,
1958 const char *pixbuf_file_name)
1959{
1960 GtkWidget *radio_button;
1961 GtkWidget *labeled_image;
1962
1963 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_317
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_317 = 1;
else _g_boolean_var_317 = 0; _g_boolean_var_317; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
1964
1965 radio_button = g_object_new (eel_labeled_image_radio_button_get_type (), NULL((void*)0));
1966 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
1967 gtk_container_add (GTK_CONTAINER (radio_button)((((GtkContainer*) (void *) ((radio_button))))), labeled_image);
1968 eel_labled_set_mnemonic_widget (labeled_image, radio_button);
1969 gtk_widget_show (labeled_image);
1970
1971 return radio_button;
1972}
1973
1974/*
1975 * Workaround some bugs in GtkCheckButton where the widget
1976 * does not redraw properly after leave or focus out events
1977 *
1978 * The workaround is to draw a little bit more than the
1979 * widget itself - 4 pixels worth. For some reason the
1980 * widget does not properly redraw its edges.
1981 */
1982static void
1983button_leave_callback (GtkWidget *widget,
1984 gpointer callback_data)
1985{
1986 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_318
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 1986, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
1987
1988 if (gtk_widget_is_drawable (widget))
1989 {
1990 const int fudge = 4;
1991 EelIRect bounds;
1992
1993 bounds = eel_gtk_widget_get_bounds (widget);
1994
1995 bounds.x0 -= fudge;
1996 bounds.y0 -= fudge;
1997 bounds.x1 += fudge;
1998 bounds.y1 += fudge;
1999
2000 gtk_widget_queue_draw_area (gtk_widget_get_parent (widget),
2001 bounds.x0,
2002 bounds.y0,
2003 eel_irect_get_width (bounds),
2004 eel_irect_get_height (bounds));
2005 }
2006}
2007
2008static gint
2009button_focus_out_event_callback (GtkWidget *widget,
2010 GdkEventFocus *event,
2011 gpointer callback_data)
2012{
2013 g_assert (GTK_IS_WIDGET (widget))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_319
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((gtk_widget_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_assertion_message_expr ("Eel", "eel-labeled-image.c"
, 2013, ((const char*) (__func__)), "GTK_IS_WIDGET (widget)")
; } while (0)
;
2014
2015 button_leave_callback (widget, callback_data);
2016
2017 return FALSE(0);
2018}
2019
2020/**
2021 * eel_labeled_image_check_button_new:
2022 * @text: Text to use for label or NULL.
2023 * @pixbuf: Pixbuf to use for image or NULL.
2024 *
2025 * Create a stock GtkCheckButton with a EelLabeledImage child.
2026 *
2027 */
2028GtkWidget *
2029eel_labeled_image_check_button_new (const char *text,
2030 GdkPixbuf *pixbuf)
2031{
2032 GtkWidget *check_button;
2033 GtkWidget *labeled_image;
2034
2035 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2036 labeled_image = eel_labeled_image_new (text, pixbuf);
2037 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2038 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2039 gtk_widget_show (labeled_image);
2040
2041 /*
2042 * Workaround some bugs in GtkCheckButton where the widget
2043 * does not redraw properly after leave or focus out events
2044 */
2045 g_signal_connect (check_button, "leave",g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
2046 G_CALLBACK (button_leave_callback), NULL)g_signal_connect_data ((check_button), ("leave"), (((GCallback
) (button_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
2047 g_signal_connect (check_button, "focus_out_event",g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
2048 G_CALLBACK (button_focus_out_event_callback), NULL)g_signal_connect_data ((check_button), ("focus_out_event"), (
((GCallback) (button_focus_out_event_callback))), (((void*)0)
), ((void*)0), (GConnectFlags) 0)
;
2049
2050 return check_button;
2051}
2052
2053/**
2054 * eel_labeled_image_check_button_new_from_file_name:
2055 * @text: Text to use for label or NULL.
2056 * @pixbuf_file_name: Name of pixbuf to use for image. Cannot be NULL.
2057 *
2058 * Create a stock GtkCheckButton with a EelLabeledImage child.
2059 *
2060 */
2061GtkWidget *
2062eel_labeled_image_check_button_new_from_file_name (const char *text,
2063 const char *pixbuf_file_name)
2064{
2065 GtkWidget *check_button;
2066 GtkWidget *labeled_image;
2067
2068 g_return_val_if_fail (pixbuf_file_name != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_320
; if (pixbuf_file_name != ((void*)0)) _g_boolean_var_320 = 1;
else _g_boolean_var_320 = 0; _g_boolean_var_320; }), 1))) { }
else { g_return_if_fail_warning ("Eel", ((const char*) (__func__
)), "pixbuf_file_name != NULL"); return (((void*)0)); } } while
(0)
;
2069
2070 check_button = g_object_new (eel_labeled_image_check_button_get_type (), NULL((void*)0));
2071 labeled_image = eel_labeled_image_new_from_file_name (text, pixbuf_file_name);
2072 gtk_container_add (GTK_CONTAINER (check_button)((((GtkContainer*) (void *) ((check_button))))), labeled_image);
2073 eel_labled_set_mnemonic_widget (labeled_image, check_button);
2074 gtk_widget_show (labeled_image);
2075
2076 return check_button;
2077}
2078
2079/*
2080 * The rest of the methods are proxies for those in EelImage and
2081 * EelLabel. We have all these so that we dont have to expose
2082 * our internal widgets at all. Probably more of these will be added
2083 * as they are needed.
2084 */
2085
2086/**
2087 * eel_labeled_image_set_pixbuf:
2088 * @labaled_image: A EelLabeledImage.
2089 * @pixbuf: New pixbuf to use or NULL.
2090 *
2091 * Change the pixbuf displayed by the LabeledImage. Note that the widget display
2092 * is only updated if the show_image attribute is TRUE.
2093 *
2094 * If no internal image widget exists as of yet, a new one will be created.
2095 *
2096 * A NULL &pixbuf will cause the internal image widget (if alive) to be destroyed.
2097 */
2098void
2099eel_labeled_image_set_pixbuf (EelLabeledImage *labeled_image,
2100 GdkPixbuf *pixbuf)
2101{
2102 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_321
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2103
2104 if (pixbuf == NULL((void*)0))
2105 {
2106 if (labeled_image->details->image != NULL((void*)0))
2107 {
2108 gtk_widget_destroy (labeled_image->details->image);
2109 labeled_image->details->image = NULL((void*)0);
2110 }
2111
2112 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2113 }
2114 else
2115 {
2116 labeled_image_ensure_image (labeled_image);
2117 gtk_image_set_from_pixbuf (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf);
2118 }
2119}
2120
2121void
2122eel_labeled_image_set_pixbuf_from_file_name (EelLabeledImage *labeled_image,
2123 const char *pixbuf_file_name)
2124{
2125 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_322
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_322 = 1; else _g_boolean_var_322 =
0; _g_boolean_var_322; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2126
2127 labeled_image_ensure_image (labeled_image);
2128 gtk_image_set_from_file (GTK_IMAGE (labeled_image->details->image)((((GtkImage*) (void *) ((labeled_image->details->image
)))))
, pixbuf_file_name);
2129}
2130
2131/**
2132 * eel_labeled_image_set_text:
2133 * @labaled_image: A EelLabeledImage.
2134 * @text: New text (with mnemnonic) to use or NULL.
2135 *
2136 * Change the text displayed by the LabeledImage. Note that the widget display
2137 * is only updated if the show_label attribute is TRUE.
2138 *
2139 * If no internal label widget exists as of yet, a new one will be created.
2140 *
2141 * A NULL &text will cause the internal label widget (if alive) to be destroyed.
2142 */
2143void
2144eel_labeled_image_set_text (EelLabeledImage *labeled_image,
2145 const char *text)
2146{
2147 g_return_if_fail (EEL_IS_LABELED_IMAGE (labeled_image))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_323
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return; } } while (0)
;
2148
2149 if (text == NULL((void*)0))
2150 {
2151 if (labeled_image->details->label)
2152 {
2153 gtk_widget_destroy (labeled_image->details->label);
2154 labeled_image->details->label = NULL((void*)0);
2155 }
2156
2157 gtk_widget_queue_resize (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))));
2158 }
2159 else
2160 {
2161 labeled_image_ensure_label (labeled_image);
2162 gtk_label_set_text_with_mnemonic
2163 (GTK_LABEL (labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
, text);
2164 }
2165}
2166
2167char *
2168eel_labeled_image_get_text (const EelLabeledImage *labeled_image)
2169{
2170 g_return_val_if_fail (EEL_IS_LABELED_IMAGE (labeled_image), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_324
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((labeled_image)); GType __t = (eel_labeled_image_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_324 = 1; else _g_boolean_var_324 =
0; _g_boolean_var_324; }), 1))) { } else { g_return_if_fail_warning
("Eel", ((const char*) (__func__)), "EEL_IS_LABELED_IMAGE (labeled_image)"
); return (((void*)0)); } } while (0)
;
2171
2172 if (labeled_image->details->label == NULL((void*)0))
2173 {
2174 return NULL((void*)0);
2175 }
2176
2177 return g_strdup (gtk_label_get_text (GTK_LABEL (labeled_image->details->label)))g_strdup_inline (gtk_label_get_text (((((GtkLabel*) (void *) (
(labeled_image->details->label)))))))
;
2178}
2179
2180void
2181eel_labeled_image_set_can_focus (EelLabeledImage *labeled_image,
2182 gboolean can_focus)
2183{
2184 gtk_widget_set_can_focus (GTK_WIDGET (labeled_image)((((GtkWidget*) (void *) ((labeled_image))))), can_focus);
2185}
2186
2187static AtkObjectClass *a11y_parent_class = NULL((void*)0);
2188
2189static void
2190eel_labeled_image_accessible_initialize (AtkObject *accessible,
2191 gpointer widget)
2192{
2193 a11y_parent_class->initialize (accessible, widget);
2194 atk_object_set_role (accessible, ATK_ROLE_IMAGE);
2195
2196}
2197
2198static EelLabeledImage *
2199get_image (gpointer object)
2200{
2201 GtkWidget *widget;
2202
2203 if (!(widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (object)((((GtkAccessible*) (void *) ((object))))))))
2204 {
2205 return NULL((void*)0);
2206 }
2207
2208 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; }))))
)
2209 widget = gtk_bin_get_child (GTK_BIN (widget)((((GtkBin*) (void *) ((widget))))));
2210
2211 return EEL_LABELED_IMAGE (widget)((((EelLabeledImage*) (void *) ((widget)))));
2212}
2213
2214static const gchar* eel_labeled_image_accessible_get_name(AtkObject* accessible)
2215{
2216 EelLabeledImage* labeled_image;
2217
2218 labeled_image = get_image(accessible);
2219
2220 if (labeled_image && labeled_image->details && labeled_image->details->label)
2221 {
2222 return gtk_label_get_text(GTK_LABEL(labeled_image->details->label)((((GtkLabel*) (void *) ((labeled_image->details->label
)))))
);
2223 }
2224
2225 g_warning("no label on '%p'", labeled_image);
2226
2227 return NULL((void*)0);
2228}
2229
2230static void
2231eel_labeled_image_accessible_image_get_size (AtkImage *image,
2232 gint *width,
2233 gint *height)
2234{
2235 EelLabeledImage *labeled_image;
2236 GtkAllocation allocation;
2237
2238 labeled_image = get_image (image);
2239
2240 if (!labeled_image || !labeled_image->details->image)
2241 {
2242 *width = *height = 0;
2243 return;
2244 }
2245
2246 gtk_widget_get_allocation (labeled_image->details->image, &allocation);
2247 *width = allocation.width;
2248 *height = allocation.height;
2249}
2250
2251static void
2252eel_labeled_image_accessible_image_interface_init (AtkImageIface *iface)
2253{
2254 iface->get_image_size = eel_labeled_image_accessible_image_get_size;
2255}
2256
2257typedef struct _EelLabeledImageAccessible EelLabeledImageAccessible;
2258typedef struct _EelLabeledImageAccessibleClass EelLabeledImageAccessibleClass;
2259
2260struct _EelLabeledImageAccessible
2261{
2262 GtkContainerAccessible parent;
2263};
2264
2265struct _EelLabeledImageAccessibleClass
2266{
2267 GtkContainerAccessibleClass parent_class;
2268};
2269
2270G_DEFINE_TYPE_WITH_CODE (EelLabeledImageAccessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2271 eel_labeled_image_accessible,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2272 GTK_TYPE_CONTAINER_ACCESSIBLE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2273 G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE,static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
2274 eel_labeled_image_accessible_image_interface_init))static void eel_labeled_image_accessible_init (EelLabeledImageAccessible
*self); static void eel_labeled_image_accessible_class_init (
EelLabeledImageAccessibleClass *klass); static GType eel_labeled_image_accessible_get_type_once
(void); static gpointer eel_labeled_image_accessible_parent_class
= ((void*)0); static gint EelLabeledImageAccessible_private_offset
; static void eel_labeled_image_accessible_class_intern_init (
gpointer klass) { eel_labeled_image_accessible_parent_class =
g_type_class_peek_parent (klass); if (EelLabeledImageAccessible_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &EelLabeledImageAccessible_private_offset
); eel_labeled_image_accessible_class_init ((EelLabeledImageAccessibleClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
eel_labeled_image_accessible_get_instance_private (EelLabeledImageAccessible
*self) { return (((gpointer) ((guint8*) (self) + (glong) (EelLabeledImageAccessible_private_offset
)))); } GType eel_labeled_image_accessible_get_type (void) { static
GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= eel_labeled_image_accessible_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_pointer ((&static_g_define_type_id
), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType eel_labeled_image_accessible_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_container_accessible_get_type ()), g_intern_static_string
("EelLabeledImageAccessible"), sizeof (EelLabeledImageAccessibleClass
), (GClassInitFunc)(void (*)(void)) eel_labeled_image_accessible_class_intern_init
, sizeof (EelLabeledImageAccessible), (GInstanceInitFunc)(void
(*)(void)) eel_labeled_image_accessible_init, (GTypeFlags) 0
); { {{ const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) eel_labeled_image_accessible_image_interface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (atk_image_get_type ()), &g_implement_interface_info); }
;} } return g_define_type_id; }
;
2275static void
2276eel_labeled_image_accessible_class_init (EelLabeledImageAccessibleClass *klass)
2277{
2278 AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass)((((AtkObjectClass*) (void *) ((klass)))));
2279 a11y_parent_class = g_type_class_peek_parent (klass);
2280
2281 atk_class->get_name = eel_labeled_image_accessible_get_name;
2282 atk_class->initialize = eel_labeled_image_accessible_initialize;
2283}
2284
2285static void
2286eel_labeled_image_accessible_init (EelLabeledImageAccessible *accessible)
2287{
2288}
2289
2290static void
2291eel_labeled_image_button_class_init (GtkWidgetClass *klass)
2292{
2293}
2294
2295static GType
2296eel_labeled_image_button_get_type (void)
2297{
2298 static GType type = 0;
2299
2300 if (!type)
2301 {
2302 GTypeInfo info =
2303 {
2304 sizeof (GtkButtonClass),
2305 (GBaseInitFunc) NULL((void*)0),
2306 (GBaseFinalizeFunc) NULL((void*)0),
2307 (GClassInitFunc) eel_labeled_image_button_class_init,
2308 NULL((void*)0), /* class_finalize */
2309 NULL((void*)0), /* class_data */
2310 sizeof (GtkButton),
2311 0, /* n_preallocs */
2312 (GInstanceInitFunc) NULL((void*)0)
2313 };
2314
2315 type = g_type_register_static
2316 (GTK_TYPE_BUTTON(gtk_button_get_type ()),
2317 "EelLabeledImageButton", &info, 0);
2318 }
2319
2320 return type;
2321}
2322
2323static GType
2324eel_labeled_image_check_button_get_type (void)
2325{
2326 static GType type = 0;
2327
2328 if (!type)
2329 {
2330 GTypeInfo info =
2331 {
2332 sizeof (GtkCheckButtonClass),
2333 (GBaseInitFunc) NULL((void*)0),
2334 (GBaseFinalizeFunc) NULL((void*)0),
2335 (GClassInitFunc) eel_labeled_image_button_class_init,
2336 NULL((void*)0), /* class_finalize */
2337 NULL((void*)0), /* class_data */
2338 sizeof (GtkCheckButton),
2339 0, /* n_preallocs */
2340 (GInstanceInitFunc) NULL((void*)0)
2341 };
2342
2343 type = g_type_register_static
2344 (GTK_TYPE_CHECK_BUTTON(gtk_check_button_get_type ()),
2345 "EelLabeledImageCheckButton", &info, 0);
2346 }
2347
2348 return type;
2349}
2350
2351static GType
2352eel_labeled_image_toggle_button_get_type (void)
2353{
2354 static GType type = 0;
2355
2356 if (!type)
2357 {
2358 GTypeInfo info =
2359 {
2360 sizeof (GtkToggleButtonClass),
2361 (GBaseInitFunc) NULL((void*)0),
2362 (GBaseFinalizeFunc) NULL((void*)0),
2363 (GClassInitFunc) eel_labeled_image_button_class_init,
2364 NULL((void*)0), /* class_finalize */
2365 NULL((void*)0), /* class_data */
2366 sizeof (GtkToggleButton),
2367 0, /* n_preallocs */
2368 (GInstanceInitFunc) NULL((void*)0)
2369 };
2370
2371 type = g_type_register_static
2372 (GTK_TYPE_TOGGLE_BUTTON(gtk_toggle_button_get_type ()),
2373 "EelLabeledImageToggleButton", &info, 0);
2374 }
2375
2376 return type;
2377}
2378
2379
2380static GType
2381eel_labeled_image_radio_button_get_type (void)
2382{
2383 static GType type = 0;
2384
2385 if (!type)
2386 {
2387 GTypeInfo info =
2388 {
2389 sizeof (GtkRadioButtonClass),
2390 (GBaseInitFunc) NULL((void*)0),
2391 (GBaseFinalizeFunc) NULL((void*)0),
2392 (GClassInitFunc) eel_labeled_image_button_class_init,
2393 NULL((void*)0), /* class_finalize */
2394 NULL((void*)0), /* class_data */
2395 sizeof (GtkRadioButton),
2396 0, /* n_preallocs */
2397 (GInstanceInitFunc) NULL((void*)0)
2398 };
2399
2400 type = g_type_register_static
2401 (GTK_TYPE_RADIO_BUTTON(gtk_radio_button_get_type ()),
2402 "EelLabeledImageRadioButton", &info, 0);
2403 }
2404
2405 return type;
2406}
diff --git a/2024-07-29-023715-6438-1/report-fb6164.html b/2024-07-29-023715-6438-1/report-fb6164.html new file mode 100644 index 000000000..866be9fca --- /dev/null +++ b/2024-07-29-023715-6438-1/report-fb6164.html @@ -0,0 +1,1511 @@ + + + +/rootdir/libcaja-extension/tmp-introspect70zjnr57/Caja-2.0.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:libcaja-extension/tmp-introspect70zjnr57/Caja-2.0.c
Warning:line 239, column 11
This statement is never executed
+ +

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 Caja-2.0.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 -fdebug-compilation-dir=/rootdir/libcaja-extension -fcoverage-compilation-dir=/rootdir/libcaja-extension -resource-dir /usr/bin/../lib/clang/18 -D WITH_GZFILEOP -D WITH_GZFILEOP -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/freetype2 -I /usr/include/cairo -I /usr/include/atk-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/gio-unix-2.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /rootdir -I /rootdir -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/freetype2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/libxml2 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/gio-unix-2.0 -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-deprecated-declarations -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c /rootdir/libcaja-extension/tmp-introspect70zjnr57/Caja-2.0.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* This file is generated, do not edit */
2
3#undef GLIB_VERSION_MIN_REQUIRED((((2) << 16 | (80) << 8)))
4#undef GLIB_VERSION_MAX_ALLOWED((((2) << 16 | (80) << 8)))
5
6#include <glib.h>
7#include <string.h>
8#include <stdlib.h>
9
10/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
11 * GObject introspection: Dump introspection data
12 *
13 * Copyright (C) 2008 Colin Walters <walters@verbum.org>
14 *
15 * SPDX-License-Identifier: LGPL-2.1-or-later
16 *
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2 of the License, or (at your option) any later version.
21 *
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with this library; if not, write to the
29 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 * Boston, MA 02111-1307, USA.
31 */
32
33/* This file is both compiled into libgirepository.so, and installed
34 * on the filesystem. But for the dumper, we want to avoid linking
35 * to libgirepository; see
36 * https://bugzilla.gnome.org/show_bug.cgi?id=630342
37 */
38#ifdef G_IREPOSITORY_COMPILATION
39#include "config.h"
40#include "girepository.h"
41#endif
42
43#include <glib.h>
44#include <glib-object.h>
45#include <gmodule.h>
46
47#include <stdlib.h>
48#include <stdio.h>
49#include <string.h>
50
51/* Analogue of g_output_stream_write_all(). */
52static gboolean
53write_all (FILE *out,
54 const void *buffer,
55 gsize count,
56 gsize *bytes_written,
57 GError **error)
58{
59 size_t ret;
60
61 ret = fwrite (buffer, 1, count, out);
62
63 if (bytes_written != NULL((void*)0))
64 *bytes_written = ret;
65
66 if (ret < count)
67 {
68 g_set_error (error, G_FILE_ERRORg_file_error_quark (), G_FILE_ERROR_FAILED,
69 "Failed to write to file");
70 return FALSE(0);
71 }
72
73 return TRUE(!(0));
74}
75
76/* Analogue of g_data_input_stream_read_line(). */
77static char *
78read_line (FILE *input,
79 size_t *len_out)
80{
81 GByteArray *buffer = g_byte_array_new ();
82 const guint8 nul = '\0';
83
84 while (TRUE(!(0)))
85 {
86 size_t ret;
87 guint8 byte;
88
89 ret = fread (&byte, 1, 1, input);
90 if (ret == 0)
91 break;
92
93 if (byte == '\n')
94 break;
95
96 g_byte_array_append (buffer, &byte, 1);
97 }
98
99 g_byte_array_append (buffer, &nul, 1);
100
101 if (len_out != NULL((void*)0))
102 *len_out = buffer->len - 1; /* don’t include terminating nul */
103
104 return (char *) g_byte_array_free (buffer, FALSE(0));
105}
106
107static void
108escaped_printf (FILE *out, const char *fmt, ...) G_GNUC_PRINTF (2, 3)__attribute__((__format__ (__printf__, 2, 3)));
109
110static void
111escaped_printf (FILE *out, const char *fmt, ...)
112{
113 char *str;
114 va_list args;
115 gsize written;
116 GError *error = NULL((void*)0);
117
118 va_start (args, fmt)__builtin_va_start(args, fmt);
119
120 str = g_markup_vprintf_escaped (fmt, args);
121 if (!write_all (out, str, strlen (str), &written, &error))
122 {
123 g_critical ("failed to write to iochannel: %s", error->message);
124 g_clear_error (&error);
125 }
126 g_free (str);
127
128 va_end (args)__builtin_va_end(args);
129}
130
131static void
132goutput_write (FILE *out, const char *str)
133{
134 gsize written;
135 GError *error = NULL((void*)0);
136 if (!write_all (out, str, strlen (str), &written, &error))
137 {
138 g_critical ("failed to write to iochannel: %s", error->message);
139 g_clear_error (&error);
140 }
141}
142
143typedef GType (*GetTypeFunc)(void);
144typedef GQuark (*ErrorQuarkFunc)(void);
145
146static GType
147invoke_get_type (GModule *self, const char *symbol, GError **error)
148{
149 GetTypeFunc sym;
150 GType ret;
151
152 if (!g_module_symbol (self, symbol, (void**)&sym))
153 {
154 g_set_error (error,
155 G_FILE_ERRORg_file_error_quark (),
156 G_FILE_ERROR_FAILED,
157 "Failed to find symbol '%s'", symbol);
158 return G_TYPE_INVALID((GType) ((0) << (2)));
159 }
160
161 ret = sym ();
162 if (ret == G_TYPE_INVALID((GType) ((0) << (2))))
163 {
164 g_set_error (error,
165 G_FILE_ERRORg_file_error_quark (),
166 G_FILE_ERROR_FAILED,
167 "Function '%s' returned G_TYPE_INVALID", symbol);
168 }
169 return ret;
170}
171
172static GQuark
173invoke_error_quark (GModule *self, const char *symbol, GError **error)
174{
175 ErrorQuarkFunc sym;
176
177 if (!g_module_symbol (self, symbol, (void**)&sym))
178 {
179 g_set_error (error,
180 G_FILE_ERRORg_file_error_quark (),
181 G_FILE_ERROR_FAILED,
182 "Failed to find symbol '%s'", symbol);
183 return G_TYPE_INVALID((GType) ((0) << (2)));
184 }
185
186 return sym ();
187}
188
189static char *
190value_transform_to_string (const GValue *value)
191{
192 GValue tmp = G_VALUE_INIT{ 0, { { 0 } } };
193 char *s = NULL((void*)0);
194
195 g_value_init (&tmp, G_TYPE_STRING((GType) ((16) << (2))));
196
197 if (g_value_transform (value, &tmp))
198 {
199 const char *str = g_value_get_string (&tmp);
200
201 if (str != NULL((void*)0))
202 s = g_strescape (str, NULL((void*)0));
203 }
204
205 g_value_unset (&tmp);
206
207 return s;
208}
209
210/* A simpler version of g_strdup_value_contents(), but with stable
211 * output and less complex semantics
212 */
213static char *
214value_to_string (const GValue *value)
215{
216 if (value == NULL((void*)0))
217 return NULL((void*)0);
218
219 if (G_VALUE_HOLDS_STRING (value)(((__extension__ ({ const GValue *__val = (const GValue*) ((value
)); GType __t = (((GType) ((16) << (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
; }))))
)
220 {
221 const char *s = g_value_get_string (value);
222
223 if (s == NULL((void*)0))
224 return g_strdup ("NULL")g_strdup_inline ("NULL");
225
226 return g_strescape (s, NULL((void*)0));
227 }
228 else
229 {
230 GType value_type = G_VALUE_TYPE (value)(((GValue*) (value))->g_type);
231
232 switch (G_TYPE_FUNDAMENTAL (value_type)(g_type_fundamental (value_type)))
233 {
234 case G_TYPE_BOXED((GType) ((18) << (2))):
235 if (g_value_get_boxed (value) == NULL((void*)0))
236 return NULL((void*)0);
237 else
238 return value_transform_to_string (value);
239 break;
This statement is never executed
240
241 case G_TYPE_OBJECT((GType) ((20) << (2))):
242 if (g_value_get_object (value) == NULL((void*)0))
243 return NULL((void*)0);
244 else
245 return value_transform_to_string (value);
246 break;
247
248 case G_TYPE_POINTER((GType) ((17) << (2))):
249 return NULL((void*)0);
250
251 default:
252 return value_transform_to_string (value);
253 }
254 }
255
256 return NULL((void*)0);
257}
258
259static void
260dump_properties (GType type, FILE *out)
261{
262 guint i;
263 guint n_properties = 0;
264 GParamSpec **props;
265
266 if (G_TYPE_FUNDAMENTAL (type)(g_type_fundamental (type)) == G_TYPE_OBJECT((GType) ((20) << (2))))
267 {
268 GObjectClass *klass;
269 klass = g_type_class_ref (type);
270 props = g_object_class_list_properties (klass, &n_properties);
271 }
272 else
273 {
274 void *klass;
275 klass = g_type_default_interface_ref (type);
276 props = g_object_interface_list_properties (klass, &n_properties);
277 }
278
279 for (i = 0; i < n_properties; i++)
280 {
281 GParamSpec *prop;
282
283 prop = props[i];
284 if (prop->owner_type != type)
285 continue;
286
287 const GValue *v = g_param_spec_get_default_value (prop);
288 char *default_value = value_to_string (v);
289
290 if (v != NULL((void*)0) && default_value != NULL((void*)0))
291 {
292 escaped_printf (out, " <property name=\"%s\" type=\"%s\" flags=\"%d\" default-value=\"%s\"/>\n",
293 prop->name,
294 g_type_name (prop->value_type),
295 prop->flags,
296 default_value);
297 }
298 else
299 {
300 escaped_printf (out, " <property name=\"%s\" type=\"%s\" flags=\"%d\"/>\n",
301 prop->name,
302 g_type_name (prop->value_type),
303 prop->flags);
304 }
305
306 g_free (default_value);
307 }
308
309 g_free (props);
310}
311
312static void
313dump_signals (GType type, FILE *out)
314{
315 guint i;
316 guint n_sigs;
317 guint *sig_ids;
318
319 sig_ids = g_signal_list_ids (type, &n_sigs);
320 for (i = 0; i < n_sigs; i++)
321 {
322 guint sigid;
323 GSignalQuery query;
324 guint j;
325
326 sigid = sig_ids[i];
327 g_signal_query (sigid, &query);
328
329 escaped_printf (out, " <signal name=\"%s\" return=\"%s\"",
330 query.signal_name, g_type_name (query.return_type));
331
332 if (query.signal_flags & G_SIGNAL_RUN_FIRST)
333 escaped_printf (out, " when=\"first\"");
334 else if (query.signal_flags & G_SIGNAL_RUN_LAST)
335 escaped_printf (out, " when=\"last\"");
336 else if (query.signal_flags & G_SIGNAL_RUN_CLEANUP)
337 escaped_printf (out, " when=\"cleanup\"");
338 else if (query.signal_flags & G_SIGNAL_MUST_COLLECT)
339 escaped_printf (out, " when=\"must-collect\"");
340 if (query.signal_flags & G_SIGNAL_NO_RECURSE)
341 escaped_printf (out, " no-recurse=\"1\"");
342
343 if (query.signal_flags & G_SIGNAL_DETAILED)
344 escaped_printf (out, " detailed=\"1\"");
345
346 if (query.signal_flags & G_SIGNAL_ACTION)
347 escaped_printf (out, " action=\"1\"");
348
349 if (query.signal_flags & G_SIGNAL_NO_HOOKS)
350 escaped_printf (out, " no-hooks=\"1\"");
351
352 goutput_write (out, ">\n");
353
354 for (j = 0; j < query.n_params; j++)
355 {
356 escaped_printf (out, " <param type=\"%s\"/>\n",
357 g_type_name (query.param_types[j]));
358 }
359 goutput_write (out, " </signal>\n");
360 }
361 g_free (sig_ids);
362}
363
364static void
365dump_object_type (GType type, const char *symbol, FILE *out)
366{
367 guint n_interfaces;
368 guint i;
369 GType *interfaces;
370
371 escaped_printf (out, " <class name=\"%s\" get-type=\"%s\"",
372 g_type_name (type), symbol);
373 if (type != G_TYPE_OBJECT((GType) ((20) << (2))))
374 {
375 GString *parent_str;
376 GType parent;
377 gboolean first = TRUE(!(0));
378
379 parent = g_type_parent (type);
380 parent_str = g_string_new ("");
381 while (parent != G_TYPE_INVALID((GType) ((0) << (2))))
382 {
383 if (first)
384 first = FALSE(0);
385 else
386 g_string_append_c (parent_str, ',')g_string_append_c_inline (parent_str, ',');
387 g_string_append (parent_str, g_type_name (parent))(__builtin_constant_p (g_type_name (parent)) ? __extension__ (
{ const char * const __val = (g_type_name (parent)); g_string_append_len_inline
(parent_str, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_13
; if (__val != ((void*)0)) _g_boolean_var_13 = 1; else _g_boolean_var_13
= 0; _g_boolean_var_13; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
parent_str, g_type_name (parent), (gssize) -1))
;
388 parent = g_type_parent (parent);
389 }
390
391 escaped_printf (out, " parents=\"%s\"", parent_str->str);
392
393 g_string_free (parent_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(parent_str), ((!(0)))) : g_string_free_and_steal (parent_str
)) : (g_string_free) ((parent_str), ((!(0)))))
;
394 }
395
396 if (G_TYPE_IS_ABSTRACT (type)(g_type_test_flags ((type), G_TYPE_FLAG_ABSTRACT)))
397 escaped_printf (out, " abstract=\"1\"");
398
399 if (G_TYPE_IS_FINAL (type)(g_type_test_flags ((type), G_TYPE_FLAG_FINAL)))
400 escaped_printf (out, " final=\"1\"");
401
402 goutput_write (out, ">\n");
403
404 interfaces = g_type_interfaces (type, &n_interfaces);
405 for (i = 0; i < n_interfaces; i++)
406 {
407 GType itype = interfaces[i];
408 escaped_printf (out, " <implements name=\"%s\"/>\n",
409 g_type_name (itype));
410 }
411 g_free (interfaces);
412
413 dump_properties (type, out);
414 dump_signals (type, out);
415 goutput_write (out, " </class>\n");
416}
417
418static void
419dump_interface_type (GType type, const char *symbol, FILE *out)
420{
421 guint n_interfaces;
422 guint i;
423 GType *interfaces;
424
425 escaped_printf (out, " <interface name=\"%s\" get-type=\"%s\">\n",
426 g_type_name (type), symbol);
427
428 interfaces = g_type_interface_prerequisites (type, &n_interfaces);
429 for (i = 0; i < n_interfaces; i++)
430 {
431 GType itype = interfaces[i];
432 if (itype == G_TYPE_OBJECT((GType) ((20) << (2))))
433 {
434 /* Treat this as implicit for now; in theory GInterfaces are
435 * supported on things like GstMiniObject, but right now
436 * the introspection system only supports GObject.
437 * http://bugzilla.gnome.org/show_bug.cgi?id=559706
438 */
439 continue;
440 }
441 escaped_printf (out, " <prerequisite name=\"%s\"/>\n",
442 g_type_name (itype));
443 }
444 g_free (interfaces);
445
446 dump_properties (type, out);
447 dump_signals (type, out);
448 goutput_write (out, " </interface>\n");
449}
450
451static void
452dump_boxed_type (GType type, const char *symbol, FILE *out)
453{
454 escaped_printf (out, " <boxed name=\"%s\" get-type=\"%s\"/>\n",
455 g_type_name (type), symbol);
456}
457
458static void
459dump_flags_type (GType type, const char *symbol, FILE *out)
460{
461 guint i;
462 GFlagsClass *klass;
463
464 klass = g_type_class_ref (type);
465 escaped_printf (out, " <flags name=\"%s\" get-type=\"%s\">\n",
466 g_type_name (type), symbol);
467
468 for (i = 0; i < klass->n_values; i++)
469 {
470 GFlagsValue *value = &(klass->values[i]);
471
472 escaped_printf (out, " <member name=\"%s\" nick=\"%s\" value=\"%u\"/>\n",
473 value->value_name, value->value_nick, value->value);
474 }
475 goutput_write (out, " </flags>\n");
476}
477
478static void
479dump_enum_type (GType type, const char *symbol, FILE *out)
480{
481 guint i;
482 GEnumClass *klass;
483
484 klass = g_type_class_ref (type);
485 escaped_printf (out, " <enum name=\"%s\" get-type=\"%s\">\n",
486 g_type_name (type), symbol);
487
488 for (i = 0; i < klass->n_values; i++)
489 {
490 GEnumValue *value = &(klass->values[i]);
491
492 escaped_printf (out, " <member name=\"%s\" nick=\"%s\" value=\"%d\"/>\n",
493 value->value_name, value->value_nick, value->value);
494 }
495 goutput_write (out, " </enum>");
496}
497
498static void
499dump_fundamental_type (GType type, const char *symbol, FILE *out)
500{
501 guint n_interfaces;
502 guint i;
503 GType *interfaces;
504 GString *parent_str;
505 GType parent;
506 gboolean first = TRUE(!(0));
507
508
509 escaped_printf (out, " <fundamental name=\"%s\" get-type=\"%s\"",
510 g_type_name (type), symbol);
511
512 if (G_TYPE_IS_ABSTRACT (type)(g_type_test_flags ((type), G_TYPE_FLAG_ABSTRACT)))
513 escaped_printf (out, " abstract=\"1\"");
514
515 if (G_TYPE_IS_FINAL (type)(g_type_test_flags ((type), G_TYPE_FLAG_FINAL)))
516 escaped_printf (out, " final=\"1\"");
517
518 if (G_TYPE_IS_INSTANTIATABLE (type)(g_type_test_flags ((type), G_TYPE_FLAG_INSTANTIATABLE)))
519 escaped_printf (out, " instantiatable=\"1\"");
520
521 parent = g_type_parent (type);
522 parent_str = g_string_new ("");
523 while (parent != G_TYPE_INVALID((GType) ((0) << (2))))
524 {
525 if (first)
526 first = FALSE(0);
527 else
528 g_string_append_c (parent_str, ',')g_string_append_c_inline (parent_str, ',');
529 if (!g_type_name (parent))
530 break;
531 g_string_append (parent_str, g_type_name (parent))(__builtin_constant_p (g_type_name (parent)) ? __extension__ (
{ const char * const __val = (g_type_name (parent)); g_string_append_len_inline
(parent_str, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_14
; if (__val != ((void*)0)) _g_boolean_var_14 = 1; else _g_boolean_var_14
= 0; _g_boolean_var_14; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
parent_str, g_type_name (parent), (gssize) -1))
;
532 parent = g_type_parent (parent);
533 }
534
535 if (parent_str->len > 0)
536 escaped_printf (out, " parents=\"%s\"", parent_str->str);
537 g_string_free (parent_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(parent_str), ((!(0)))) : g_string_free_and_steal (parent_str
)) : (g_string_free) ((parent_str), ((!(0)))))
;
538
539 goutput_write (out, ">\n");
540
541 interfaces = g_type_interfaces (type, &n_interfaces);
542 for (i = 0; i < n_interfaces; i++)
543 {
544 GType itype = interfaces[i];
545 escaped_printf (out, " <implements name=\"%s\"/>\n",
546 g_type_name (itype));
547 }
548 g_free (interfaces);
549 goutput_write (out, " </fundamental>\n");
550}
551
552static void
553dump_type (GType type, const char *symbol, FILE *out)
554{
555 /* XXX: We need to ensure that global ancillary structures like
556 * GParamSpecPool are initialized before we use the GType and
557 * GObject reflection API to poke at things like properties and
558 * signals; we cannot rely on GObject being instantiated at this
559 * point.
560 */
561 GObjectClass *gobject_class = g_type_class_ref (G_TYPE_OBJECT((GType) ((20) << (2))));
562
563 switch (g_type_fundamental (type))
564 {
565 case G_TYPE_OBJECT((GType) ((20) << (2))):
566 dump_object_type (type, symbol, out);
567 break;
568 case G_TYPE_INTERFACE((GType) ((2) << (2))):
569 dump_interface_type (type, symbol, out);
570 break;
571 case G_TYPE_BOXED((GType) ((18) << (2))):
572 dump_boxed_type (type, symbol, out);
573 break;
574 case G_TYPE_FLAGS((GType) ((13) << (2))):
575 dump_flags_type (type, symbol, out);
576 break;
577 case G_TYPE_ENUM((GType) ((12) << (2))):
578 dump_enum_type (type, symbol, out);
579 break;
580 case G_TYPE_POINTER((GType) ((17) << (2))):
581 /* GValue, etc. Just skip them. */
582 break;
583 default:
584 dump_fundamental_type (type, symbol, out);
585 break;
586 }
587
588 g_type_class_unref ((GTypeClass *) gobject_class);
589}
590
591static void
592dump_error_quark (GQuark quark, const char *symbol, FILE *out)
593{
594 escaped_printf (out, " <error-quark function=\"%s\" domain=\"%s\"/>\n",
595 symbol, g_quark_to_string (quark));
596}
597
598/**
599 * g_irepository_dump:
600 * @input_filename: (type filename): Input filename (for example `input.txt`)
601 * @output_filename: (type filename): Output filename (for example `output.xml`)
602 * @error: a %GError
603 *
604 * Dump the introspection data from the types specified in @input_filename to
605 * @output_filename.
606 *
607 * The input file should be a
608 * UTF-8 Unix-line-ending text file, with each line containing either
609 * `get-type:` followed by the name of a [type@GObject.Type] `_get_type`
610 * function, or `error-quark:` followed by the name of an error quark function.
611 * No extra whitespace is allowed.
612 *
613 * This function will overwrite the contents of the output file.
614 *
615 * Returns: true on success, false on error
616 * Since: 2.80
617 */
618#ifndef G_IREPOSITORY_COMPILATION
619static gboolean
620dump_irepository (const char *arg,
621 GError **error) G_GNUC_UNUSED__attribute__ ((__unused__));
622static gboolean
623dump_irepository (const char *arg,
624 GError **error)
625#else
626gboolean
627g_irepository_dump (const char *arg,
628 GError **error)
629#endif
630{
631 GHashTable *output_types;
632 FILE *input;
633 FILE *output;
634 GModule *self;
635 gboolean caught_error = FALSE(0);
636
637 char **args = g_strsplit (arg, ",", 2);
638 if (args == NULL((void*)0))
639 return FALSE(0);
640
641 const char *input_filename = args[0];
642 const char *output_filename = args[1];
643
644 self = g_module_open (NULL((void*)0), 0);
645 if (!self)
646 {
647 g_set_error (error,
648 G_FILE_ERRORg_file_error_quark (),
649 G_FILE_ERROR_FAILED,
650 "failed to open self: %s",
651 g_module_error ());
652 g_strfreev (args);
653 return FALSE(0);
654 }
655
656 input = fopen (input_filename, "rb");
657 if (input == NULL((void*)0))
658 {
659 int saved_errno = errno(*__errno_location ());
660 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
661 "Failed to open ‘%s’: %s", input_filename, g_strerror (saved_errno));
662
663 g_module_close (self);
664 g_strfreev (args);
665
666 return FALSE(0);
667 }
668
669 output = fopen (output_filename, "wb");
670 if (output == NULL((void*)0))
671 {
672 int saved_errno = errno(*__errno_location ());
673 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
674 "Failed to open ‘%s’: %s", output_filename, g_strerror (saved_errno));
675
676 fclose (input);
677 g_module_close (self);
678 g_strfreev (args);
679
680 return FALSE(0);
681 }
682
683 goutput_write (output, "<?xml version=\"1.0\"?>\n");
684 goutput_write (output, "<dump>\n");
685
686 output_types = g_hash_table_new (NULL((void*)0), NULL((void*)0));
687
688 while (TRUE(!(0)))
689 {
690 gsize len;
691 char *line = read_line (input, &len);
692 const char *function;
693
694 if (line == NULL((void*)0) || *line == '\0')
695 {
696 g_free (line);
697 break;
698 }
699
700 g_strchomp (line);
701
702 if (strncmp (line, "get-type:", strlen ("get-type:")) == 0)
703 {
704 GType type;
705
706 function = line + strlen ("get-type:");
707
708 type = invoke_get_type (self, function, error);
709
710 if (type == G_TYPE_INVALID((GType) ((0) << (2))))
711 {
712 g_printerr ("Invalid GType function: '%s'\n", function);
713 caught_error = TRUE(!(0));
714 g_free (line);
715 break;
716 }
717
718 if (g_hash_table_lookup (output_types, (gpointer) type))
719 goto next;
720 g_hash_table_insert (output_types, (gpointer) type, (gpointer) type);
721
722 dump_type (type, function, output);
723 }
724 else if (strncmp (line, "error-quark:", strlen ("error-quark:")) == 0)
725 {
726 GQuark quark;
727 function = line + strlen ("error-quark:");
728 quark = invoke_error_quark (self, function, error);
729
730 if (quark == 0)
731 {
732 g_printerr ("Invalid error quark function: '%s'\n", function);
733 caught_error = TRUE(!(0));
734 g_free (line);
735 break;
736 }
737
738 dump_error_quark (quark, function, output);
739 }
740
741
742 next:
743 g_free (line);
744 }
745
746 g_hash_table_destroy (output_types);
747
748 goutput_write (output, "</dump>\n");
749
750 {
751 /* Avoid overwriting an earlier set error */
752 if (fclose (input) != 0 && !caught_error)
753 {
754 int saved_errno = errno(*__errno_location ());
755
756 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
757 "Error closing input file ‘%s’: %s", input_filename,
758 g_strerror (saved_errno));
759 caught_error = TRUE(!(0));
760 }
761
762 if (fclose (output) != 0 && !caught_error)
763 {
764 int saved_errno = errno(*__errno_location ());
765
766 g_set_error (error, G_FILE_ERRORg_file_error_quark (), g_file_error_from_errno (saved_errno),
767 "Error closing output file ‘%s’: %s", output_filename,
768 g_strerror (saved_errno));
769 caught_error = TRUE(!(0));
770 }
771 }
772
773 g_strfreev (args);
774
775 return !caught_error;
776}
777
778
779int
780main(int argc, char **argv)
781{
782 GError *error = NULL((void*)0);
783 const char *introspect_dump_prefix = "--introspect-dump=";
784
785#if !GLIB_CHECK_VERSION(2,35,0)(2 > (2) || (2 == (2) && 80 > (35)) || (2 == (2
) && 80 == (35) && 3 >= (0)))
786 g_type_init ();
787#endif
788
789
790
791 if (argc != 2 || !g_str_has_prefix (argv[1], introspect_dump_prefix)(__builtin_constant_p (introspect_dump_prefix)? __extension__
({ const char * const __str = (argv[1]); const char * const __prefix
= (introspect_dump_prefix); gboolean __result = (0); if (__builtin_expect
(__extension__ ({ int _g_boolean_var_15; if (__str == ((void
*)0) || __prefix == ((void*)0)) _g_boolean_var_15 = 1; else _g_boolean_var_15
= 0; _g_boolean_var_15; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (argv[1], introspect_dump_prefix
) )
)
792 {
793 g_printerr ("Usage: %s --introspect-dump=input,output", argv[0]);
794 exit (1);
795 }
796
797 if (!dump_irepository (argv[1] + strlen(introspect_dump_prefix), &error))
798 {
799 g_printerr ("%s\n", error->message);
800 exit (1);
801 }
802 exit (0);
803}
804extern GType caja_operation_result_get_type(void);
805extern GType caja_column_get_type(void);
806extern GType caja_column_provider_get_type(void);
807extern GType caja_file_info_get_type(void);
808extern GType caja_widget_view_provider_get_type(void);
809extern GType caja_info_provider_get_type(void);
810extern GType caja_location_widget_provider_get_type(void);
811extern GType caja_menu_get_type(void);
812extern GType caja_menu_item_get_type(void);
813extern GType caja_menu_provider_get_type(void);
814extern GType caja_property_page_get_type(void);
815extern GType caja_property_page_provider_get_type(void);
816extern GType caja_configurable_get_type(void);
817G_MODULE_EXPORT__attribute__((visibility("default"))) GType (*GI_GET_TYPE_FUNCS_[])(void) = {
818 caja_operation_result_get_type,
819 caja_column_get_type,
820 caja_column_provider_get_type,
821 caja_file_info_get_type,
822 caja_widget_view_provider_get_type,
823 caja_info_provider_get_type,
824 caja_location_widget_provider_get_type,
825 caja_menu_get_type,
826 caja_menu_item_get_type,
827 caja_menu_provider_get_type,
828 caja_property_page_get_type,
829 caja_property_page_provider_get_type,
830 caja_configurable_get_type
831};
diff --git a/2024-07-29-023715-6438-1/report-fd0643.html b/2024-07-29-023715-6438-1/report-fd0643.html new file mode 100644 index 000000000..2910af518 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-fd0643.html @@ -0,0 +1,2132 @@ + + + +caja-navigation-window.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/caja-navigation-window.c
Warning:line 605, column 5
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 caja-navigation-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 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 -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libcaja-private -I ../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -I /usr/include/exempi-2.0 -D DATADIR="/usr/local/share" -D LIBDIR="/usr/local/lib" -D CAJA_DATADIR="/usr/local/share/caja" -D MATELOCALEDIR="/usr/local/share/locale" -D UIDIR="/usr/local/share/caja/ui" -D CAJA_PIXMAPDIR="/usr/local/share/pixmaps/caja" -D PREFIX="/usr/local" -D SYSCONFDIR="/usr/local/etc" -D VERSION="1.26.4" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c caja-navigation-window.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3/*
4 * Caja
5 *
6 * Copyright (C) 1999, 2000 Red Hat, Inc.
7 * Copyright (C) 1999, 2000, 2001 Eazel, Inc.
8 * Copyright (C) 2003 Ximian, Inc.
9 *
10 * Caja is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * Caja 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 GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this program; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
23 *
24 * Authors: Elliot Lee <sopwith@redhat.com>
25 * John Sullivan <sullivan@eazel.com>
26 *
27 */
28
29/* caja-window.c: Implementation of the main window object */
30
31#include <config.h>
32#include <math.h>
33
34#include <gdk-pixbuf/gdk-pixbuf.h>
35#include <gdk/gdkx.h>
36#include <gtk/gtk.h>
37#include <glib/gi18n.h>
38#ifdef HAVE_X11_XF86KEYSYM_H1
39#include <X11/XF86keysym.h>
40#endif
41#include <sys/time.h>
42
43#include <eel/eel-gtk-extensions.h>
44#include <eel/eel-gtk-macros.h>
45#include <eel/eel-string.h>
46
47#include <libcaja-private/caja-file-utilities.h>
48#include <libcaja-private/caja-file-attributes.h>
49#include <libcaja-private/caja-global-preferences.h>
50#include <libcaja-private/caja-icon-info.h>
51#include <libcaja-private/caja-metadata.h>
52#include <libcaja-private/caja-mime-actions.h>
53#include <libcaja-private/caja-program-choosing.h>
54#include <libcaja-private/caja-sidebar.h>
55#include <libcaja-private/caja-view-factory.h>
56#include <libcaja-private/caja-clipboard.h>
57#include <libcaja-private/caja-module.h>
58#include <libcaja-private/caja-sidebar-provider.h>
59#include <libcaja-private/caja-search-directory.h>
60#include <libcaja-private/caja-signaller.h>
61
62#include "caja-navigation-window.h"
63#include "caja-window-private.h"
64#include "caja-actions.h"
65#include "caja-application.h"
66#include "caja-bookmarks-window.h"
67#include "caja-location-bar.h"
68#include "caja-query-editor.h"
69#include "caja-search-bar.h"
70#include "caja-navigation-window-slot.h"
71#include "caja-notebook.h"
72#include "caja-window-manage-views.h"
73#include "caja-navigation-window-pane.h"
74
75#define MAX_TITLE_LENGTH180 180
76
77#define MENU_PATH_BOOKMARKS_PLACEHOLDER"/MenuBar/Other Menus/Bookmarks/Bookmarks Placeholder" "/MenuBar/Other Menus/Bookmarks/Bookmarks Placeholder"
78
79/* Forward and back buttons on the mouse */
80static gboolean mouse_extra_buttons = TRUE(!(0));
81static int mouse_forward_button = 9;
82static int mouse_back_button = 8;
83
84static void add_sidebar_panels (CajaNavigationWindow *window);
85static void side_panel_image_changed_callback (CajaSidebar *side_panel,
86 gpointer callback_data);
87static void always_use_location_entry_changed (gpointer callback_data);
88static void always_use_browser_changed (gpointer callback_data);
89static void mouse_back_button_changed (gpointer callback_data);
90static void mouse_forward_button_changed (gpointer callback_data);
91static void use_extra_mouse_buttons_changed (gpointer callback_data);
92static CajaWindowSlot *create_extra_pane (CajaNavigationWindow *window);
93
94
95G_DEFINE_TYPE_WITH_PRIVATE (CajaNavigationWindow, caja_navigation_window, CAJA_TYPE_WINDOW)static void caja_navigation_window_init (CajaNavigationWindow
*self); static void caja_navigation_window_class_init (CajaNavigationWindowClass
*klass); static GType caja_navigation_window_get_type_once (
void); static gpointer caja_navigation_window_parent_class = (
(void*)0); static gint CajaNavigationWindow_private_offset; static
void caja_navigation_window_class_intern_init (gpointer klass
) { caja_navigation_window_parent_class = g_type_class_peek_parent
(klass); if (CajaNavigationWindow_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CajaNavigationWindow_private_offset); caja_navigation_window_class_init
((CajaNavigationWindowClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer caja_navigation_window_get_instance_private
(CajaNavigationWindow *self) { return (((gpointer) ((guint8*
) (self) + (glong) (CajaNavigationWindow_private_offset)))); }
GType caja_navigation_window_get_type (void) { static GType 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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= caja_navigation_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_pointer ((&static_g_define_type_id), (
gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType caja_navigation_window_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(caja_window_get_type(), g_intern_static_string ("CajaNavigationWindow"
), sizeof (CajaNavigationWindowClass), (GClassInitFunc)(void (
*)(void)) caja_navigation_window_class_intern_init, sizeof (CajaNavigationWindow
), (GInstanceInitFunc)(void (*)(void)) caja_navigation_window_init
, (GTypeFlags) 0); { {{ CajaNavigationWindow_private_offset =
g_type_add_instance_private (g_define_type_id, sizeof (CajaNavigationWindowPrivate
)); };} } return g_define_type_id; }
96#define parent_classcaja_navigation_window_parent_class caja_navigation_window_parent_class
97
98static const struct
99{
100 unsigned int keyval;
101 const char *action;
102} extra_navigation_window_keybindings [] =
103{
104#ifdef HAVE_X11_XF86KEYSYM_H1
105 { XF86XK_Back0x1008ff26, CAJA_ACTION_BACK"Back" },
106 { XF86XK_Forward0x1008ff27, CAJA_ACTION_FORWARD"Forward" }
107#endif
108};
109
110static void
111caja_navigation_window_init (CajaNavigationWindow *window)
112{
113 GtkUIManager *ui_manager;
114 GtkWidget *toolbar;
115 CajaWindow *win;
116 CajaNavigationWindowPane *pane;
117 GtkWidget *hpaned;
118 GtkWidget *vbox;
119
120 win = CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))));
121
122 window->details = caja_navigation_window_get_instance_private (window);
123
124 GtkStyleContext *context;
125
126 context = gtk_widget_get_style_context (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
127 gtk_style_context_add_class (context, "caja-navigation-window");
128
129 pane = caja_navigation_window_pane_new (win);
130 win->details->panes = g_list_prepend (win->details->panes, pane);
131
132 window->details->header_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
133 gtk_size_group_set_ignore_hidden (window->details->header_size_group, FALSE(0));
134
135 window->details->content_paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
136 gtk_widget_set_hexpand (window->details->content_paned, TRUE(!(0)));
137 gtk_widget_set_vexpand (window->details->content_paned, TRUE(!(0)));
138 gtk_grid_attach (GTK_GRID (CAJA_WINDOW (window)->details->grid)((((GtkGrid*) (void *) ((((((CajaWindow*) (void *) ((window))
)))->details->grid)))))
,
139 window->details->content_paned,
140 0, 3, 1, 1);
141 gtk_widget_show (window->details->content_paned);
142
143 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
144 gtk_paned_pack2 (GTK_PANED (window->details->content_paned)((((GtkPaned*) (void *) ((window->details->content_paned
)))))
, vbox,
145 TRUE(!(0)), FALSE(0));
146 gtk_widget_show (vbox);
147
148 hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
149 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), hpaned, TRUE(!(0)), TRUE(!(0)), 0);
150 gtk_widget_show (hpaned);
151 window->details->split_view_hpane = hpaned;
152
153 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), win->details->statusbar, FALSE(0), FALSE(0), 0);
154 gtk_widget_show (win->details->statusbar);
155
156 caja_navigation_window_pane_setup (pane);
157
158 gtk_paned_pack1 (GTK_PANED(hpaned)((((GtkPaned*) (void *) ((hpaned))))), pane->widget, TRUE(!(0)), FALSE(0));
159 gtk_widget_show (pane->widget);
160
161 /* this has to be done after the location bar has been set up,
162 * but before menu stuff is being called */
163 caja_window_set_active_pane (win, CAJA_WINDOW_PANE (pane)((((CajaWindowPane*) (void *) ((pane))))));
164
165 caja_navigation_window_initialize_actions (window);
166
167 caja_navigation_window_initialize_menus (window);
168
169 ui_manager = caja_window_get_ui_manager (CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window))))));
170 toolbar = gtk_ui_manager_get_widget (ui_manager, "/Toolbar");
171 gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), GTK_STYLE_CLASS_PRIMARY_TOOLBAR"primary-toolbar");
172 window->details->toolbar = toolbar;
173 gtk_widget_set_hexpand (toolbar, TRUE(!(0)));
174 gtk_grid_attach (GTK_GRID (CAJA_WINDOW (window)->details->grid)((((GtkGrid*) (void *) ((((((CajaWindow*) (void *) ((window))
)))->details->grid)))))
,
175 toolbar,
176 0, 1, 1, 1);
177 gtk_widget_show (toolbar);
178
179 caja_navigation_window_initialize_toolbars (window);
180
181 /* Set initial sensitivity of some buttons & menu items
182 * now that they're all created.
183 */
184 caja_navigation_window_allow_back (window, FALSE(0));
185 caja_navigation_window_allow_forward (window, FALSE(0));
186
187 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "always-use-location-entry"
), (((GCallback) (always_use_location_entry_changed))), (window
), ((void*)0), G_CONNECT_SWAPPED)
188 "changed::" CAJA_PREFERENCES_ALWAYS_USE_LOCATION_ENTRY,g_signal_connect_data ((caja_preferences), ("changed::" "always-use-location-entry"
), (((GCallback) (always_use_location_entry_changed))), (window
), ((void*)0), G_CONNECT_SWAPPED)
189 G_CALLBACK(always_use_location_entry_changed),g_signal_connect_data ((caja_preferences), ("changed::" "always-use-location-entry"
), (((GCallback) (always_use_location_entry_changed))), (window
), ((void*)0), G_CONNECT_SWAPPED)
190 window)g_signal_connect_data ((caja_preferences), ("changed::" "always-use-location-entry"
), (((GCallback) (always_use_location_entry_changed))), (window
), ((void*)0), G_CONNECT_SWAPPED)
;
191
192 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "always-use-browser"
), (((GCallback) (always_use_browser_changed))), (window), ((
void*)0), G_CONNECT_SWAPPED)
193 "changed::" CAJA_PREFERENCES_ALWAYS_USE_BROWSER,g_signal_connect_data ((caja_preferences), ("changed::" "always-use-browser"
), (((GCallback) (always_use_browser_changed))), (window), ((
void*)0), G_CONNECT_SWAPPED)
194 G_CALLBACK(always_use_browser_changed),g_signal_connect_data ((caja_preferences), ("changed::" "always-use-browser"
), (((GCallback) (always_use_browser_changed))), (window), ((
void*)0), G_CONNECT_SWAPPED)
195 window)g_signal_connect_data ((caja_preferences), ("changed::" "always-use-browser"
), (((GCallback) (always_use_browser_changed))), (window), ((
void*)0), G_CONNECT_SWAPPED)
;
196}
197
198static void
199always_use_location_entry_changed (gpointer callback_data)
200{
201 CajaNavigationWindow *window;
202 GList *walk;
203 gboolean use_entry;
204
205 window = CAJA_NAVIGATION_WINDOW (callback_data)((((CajaNavigationWindow*) (void *) ((callback_data)))));
206
207 use_entry = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_LOCATION_ENTRY"always-use-location-entry");
208
209 for (walk = CAJA_WINDOW(window)((((CajaWindow*) (void *) ((window)))))->details->panes; walk; walk = walk->next)
210 {
211 caja_navigation_window_pane_always_use_location_entry (walk->data, use_entry);
212 }
213}
214
215static void
216always_use_browser_changed (gpointer callback_data)
217{
218 CajaNavigationWindow *window;
219
220 window = CAJA_NAVIGATION_WINDOW (callback_data)((((CajaNavigationWindow*) (void *) ((callback_data)))));
221
222 caja_navigation_window_update_spatial_menu_item (window);
223}
224
225/* Sanity check: highest mouse button value I could find was 14. 5 is our
226 * lower threshold (well-documented to be the one of the button events for the
227 * scrollwheel), so it's hardcoded in the functions below. However, if you have
228 * a button that registers higher and want to map it, file a bug and
229 * we'll move the bar. Makes you wonder why the X guys don't have
230 * defined values for these like the XKB stuff, huh?
231 */
232#define UPPER_MOUSE_LIMIT14 14
233
234static void
235mouse_back_button_changed (gpointer callback_data)
236{
237 int new_back_button;
238
239 new_back_button = g_settings_get_int (caja_preferences, CAJA_PREFERENCES_MOUSE_BACK_BUTTON"mouse-back-button");
240
241 /* Bounds checking */
242 if (new_back_button < 6 || new_back_button > UPPER_MOUSE_LIMIT14)
243 return;
244
245 mouse_back_button = new_back_button;
246}
247
248static void
249mouse_forward_button_changed (gpointer callback_data)
250{
251 int new_forward_button;
252
253 new_forward_button = g_settings_get_int (caja_preferences, CAJA_PREFERENCES_MOUSE_FORWARD_BUTTON"mouse-forward-button");
254
255 /* Bounds checking */
256 if (new_forward_button < 6 || new_forward_button > UPPER_MOUSE_LIMIT14)
257 return;
258
259 mouse_forward_button = new_forward_button;
260}
261
262static void
263use_extra_mouse_buttons_changed (gpointer callback_data)
264{
265 mouse_extra_buttons = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS"mouse-use-extra-buttons");
266}
267
268void
269caja_navigation_window_unset_focus_widget (CajaNavigationWindow *window)
270{
271 if (window->details->last_focus_widget != NULL((void*)0))
272 {
273 g_object_remove_weak_pointer (G_OBJECT (window->details->last_focus_widget)((((GObject*) (void *) ((window->details->last_focus_widget
)))))
,
274 (gpointer *) &window->details->last_focus_widget);
275 window->details->last_focus_widget = NULL((void*)0);
276 }
277}
278
279gboolean
280caja_navigation_window_is_in_temporary_navigation_bar (GtkWidget *widget,
281 CajaNavigationWindow *window)
282{
283 GList *walk;
284 gboolean is_in_any = FALSE(0);
285
286 for (walk = CAJA_WINDOW(window)((((CajaWindow*) (void *) ((window)))))->details->panes; walk; walk = walk->next)
287 {
288 CajaNavigationWindowPane *pane = walk->data;
289 if(gtk_widget_get_ancestor (widget, CAJA_TYPE_LOCATION_BARcaja_location_bar_get_type()) != NULL((void*)0) &&
290 pane->temporary_navigation_bar)
291 is_in_any = TRUE(!(0));
292 }
293 return is_in_any;
294}
295
296gboolean
297caja_navigation_window_is_in_temporary_search_bar (GtkWidget *widget,
298 CajaNavigationWindow *window)
299{
300 GList *walk;
301 gboolean is_in_any = FALSE(0);
302
303 for (walk = CAJA_WINDOW(window)((((CajaWindow*) (void *) ((window)))))->details->panes; walk; walk = walk->next)
304 {
305 CajaNavigationWindowPane *pane = walk->data;
306 if(gtk_widget_get_ancestor (widget, CAJA_TYPE_SEARCH_BARcaja_search_bar_get_type()) != NULL((void*)0) &&
307 pane->temporary_search_bar)
308 is_in_any = TRUE(!(0));
309 }
310 return is_in_any;
311}
312
313static void
314remember_focus_widget (CajaNavigationWindow *window)
315{
316 CajaNavigationWindow *navigation_window;
317 GtkWidget *focus_widget;
318
319 navigation_window = CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window)))));
320
321 focus_widget = gtk_window_get_focus (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
322 if (focus_widget != NULL((void*)0) &&
323 !caja_navigation_window_is_in_temporary_navigation_bar (focus_widget, navigation_window) &&
324 !caja_navigation_window_is_in_temporary_search_bar (focus_widget, navigation_window))
325 {
326 caja_navigation_window_unset_focus_widget (navigation_window);
327
328 navigation_window->details->last_focus_widget = focus_widget;
329 g_object_add_weak_pointer (G_OBJECT (focus_widget)((((GObject*) (void *) ((focus_widget))))),
330 (gpointer *) &(CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window)))))->details->last_focus_widget));
331 }
332}
333
334void
335caja_navigation_window_restore_focus_widget (CajaNavigationWindow *window)
336{
337 if (window->details->last_focus_widget != NULL((void*)0))
338 {
339 if (CAJA_IS_VIEW (window->details->last_focus_widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->last_focus_widget)); GType __t = ((caja_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; }))))
)
340 {
341 caja_view_grab_focus (CAJA_VIEW (window->details->last_focus_widget)((((CajaView*) (void *) ((window->details->last_focus_widget
)))))
);
342 }
343 else
344 {
345 gtk_widget_grab_focus (window->details->last_focus_widget);
346 }
347
348 caja_navigation_window_unset_focus_widget (window);
349 }
350}
351
352static void
353side_pane_close_requested_callback (GtkWidget *widget,
354 gpointer user_data)
355{
356 CajaNavigationWindow *window;
357
358 window = CAJA_NAVIGATION_WINDOW (user_data)((((CajaNavigationWindow*) (void *) ((user_data)))));
359
360 caja_navigation_window_hide_sidebar (window);
361}
362
363static void
364side_pane_size_allocate_callback (GtkWidget *widget,
365 GtkAllocation *allocation,
366 gpointer user_data)
367{
368 CajaNavigationWindow *window;
369 gint scale;
370
371 window = CAJA_NAVIGATION_WINDOW (user_data)((((CajaNavigationWindow*) (void *) ((user_data)))));
372 scale = gtk_widget_get_scale_factor (widget);
373
374 allocation->width = allocation->width / scale;
375 if (allocation->width != window->details->side_pane_width)
376 {
377 window->details->side_pane_width = allocation->width;
378 g_settings_set_int (caja_window_state,
379 CAJA_WINDOW_STATE_SIDEBAR_WIDTH"sidebar-width",
380 allocation->width <= 1 ? 0 : allocation->width);
381 }
382}
383
384static void
385setup_side_pane_width (CajaNavigationWindow *window)
386{
387 gint scale;
388
389 g_return_if_fail (window->sidebar != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (window->sidebar != ((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__)), "window->sidebar != NULL"); return; } } while
(0)
;
390
391 scale = gtk_widget_get_scale_factor (GTK_WIDGET (window->sidebar)((((GtkWidget*) (void *) ((window->sidebar))))));
392 window->details->side_pane_width =
393 g_settings_get_int (caja_window_state,
394 CAJA_WINDOW_STATE_SIDEBAR_WIDTH"sidebar-width") * scale;
395
396 gtk_paned_set_position (GTK_PANED (window->details->content_paned)((((GtkPaned*) (void *) ((window->details->content_paned
)))))
,
397 window->details->side_pane_width);
398}
399
400static void
401set_current_side_panel (CajaNavigationWindow *window,
402 CajaSidebar *panel)
403{
404 if (window->details->current_side_panel)
405 {
406 caja_sidebar_is_visible_changed (window->details->current_side_panel,
407 FALSE(0));
408 eel_remove_weak_pointer (&window->details->current_side_panel);
409 }
410
411 if (panel != NULL((void*)0))
412 {
413 caja_sidebar_is_visible_changed (panel, TRUE(!(0)));
414 }
415 window->details->current_side_panel = panel;
416 eel_add_weak_pointer (&window->details->current_side_panel);
417}
418
419static void
420side_pane_switch_page_callback (CajaSidePane *side_pane,
421 GtkWidget *widget,
422 CajaNavigationWindow *window)
423{
424 const char *id;
425 CajaSidebar *sidebar;
426
427 sidebar = CAJA_SIDEBAR (widget)((((CajaSidebar*) (void *) ((widget)))));
428
429 if (sidebar == NULL((void*)0))
430 {
431 return;
432 }
433
434 set_current_side_panel (window, sidebar);
435
436 id = caja_sidebar_get_sidebar_id (sidebar);
437 g_settings_set_string (caja_window_state, CAJA_WINDOW_STATE_SIDE_PANE_VIEW"side-pane-view", id);
438}
439
440static void
441caja_navigation_window_set_up_sidebar (CajaNavigationWindow *window)
442{
443 GtkWidget *title;
444
445 window->sidebar = caja_side_pane_new ();
446
447 title = caja_side_pane_get_title (window->sidebar);
448 gtk_size_group_add_widget (window->details->header_size_group,
449 title);
450
451 gtk_paned_pack1 (GTK_PANED (window->details->content_paned)((((GtkPaned*) (void *) ((window->details->content_paned
)))))
,
452 GTK_WIDGET (window->sidebar)((((GtkWidget*) (void *) ((window->sidebar))))),
453 FALSE(0), FALSE(0));
454
455 setup_side_pane_width (window);
456 g_signal_connect (window->sidebar,g_signal_connect_data ((window->sidebar), ("size_allocate"
), (((GCallback) (side_pane_size_allocate_callback))), (window
), ((void*)0), (GConnectFlags) 0)
457 "size_allocate",g_signal_connect_data ((window->sidebar), ("size_allocate"
), (((GCallback) (side_pane_size_allocate_callback))), (window
), ((void*)0), (GConnectFlags) 0)
458 G_CALLBACK (side_pane_size_allocate_callback),g_signal_connect_data ((window->sidebar), ("size_allocate"
), (((GCallback) (side_pane_size_allocate_callback))), (window
), ((void*)0), (GConnectFlags) 0)
459 window)g_signal_connect_data ((window->sidebar), ("size_allocate"
), (((GCallback) (side_pane_size_allocate_callback))), (window
), ((void*)0), (GConnectFlags) 0)
;
460
461 add_sidebar_panels (window);
462
463 g_signal_connect (window->sidebar,g_signal_connect_data ((window->sidebar), ("close_requested"
), (((GCallback) (side_pane_close_requested_callback))), (window
), ((void*)0), (GConnectFlags) 0)
464 "close_requested",g_signal_connect_data ((window->sidebar), ("close_requested"
), (((GCallback) (side_pane_close_requested_callback))), (window
), ((void*)0), (GConnectFlags) 0)
465 G_CALLBACK (side_pane_close_requested_callback),g_signal_connect_data ((window->sidebar), ("close_requested"
), (((GCallback) (side_pane_close_requested_callback))), (window
), ((void*)0), (GConnectFlags) 0)
466 window)g_signal_connect_data ((window->sidebar), ("close_requested"
), (((GCallback) (side_pane_close_requested_callback))), (window
), ((void*)0), (GConnectFlags) 0)
;
467
468 g_signal_connect (window->sidebar,g_signal_connect_data ((window->sidebar), ("switch_page"),
(((GCallback) (side_pane_switch_page_callback))), (window), (
(void*)0), (GConnectFlags) 0)
469 "switch_page",g_signal_connect_data ((window->sidebar), ("switch_page"),
(((GCallback) (side_pane_switch_page_callback))), (window), (
(void*)0), (GConnectFlags) 0)
470 G_CALLBACK (side_pane_switch_page_callback),g_signal_connect_data ((window->sidebar), ("switch_page"),
(((GCallback) (side_pane_switch_page_callback))), (window), (
(void*)0), (GConnectFlags) 0)
471 window)g_signal_connect_data ((window->sidebar), ("switch_page"),
(((GCallback) (side_pane_switch_page_callback))), (window), (
(void*)0), (GConnectFlags) 0)
;
472
473 gtk_widget_show (GTK_WIDGET (window->sidebar)((((GtkWidget*) (void *) ((window->sidebar))))));
474}
475
476static void
477caja_navigation_window_tear_down_sidebar (CajaNavigationWindow *window)
478{
479 GList *node, *next;
480 CajaSidebar *sidebar_panel = NULL((void*)0);
481
482 g_signal_handlers_disconnect_by_func (window->sidebar,g_signal_handlers_disconnect_matched ((window->sidebar), (
GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)
, 0, 0, ((void*)0), (side_pane_switch_page_callback), (window
))
483 side_pane_switch_page_callback,g_signal_handlers_disconnect_matched ((window->sidebar), (
GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)
, 0, 0, ((void*)0), (side_pane_switch_page_callback), (window
))
484 window)g_signal_handlers_disconnect_matched ((window->sidebar), (
GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)
, 0, 0, ((void*)0), (side_pane_switch_page_callback), (window
))
;
485
486 for (node = window->sidebar_panels; node != NULL((void*)0); node = next)
487 {
488 next = node->next;
489
490 sidebar_panel = CAJA_SIDEBAR (node->data)((((CajaSidebar*) (void *) ((node->data)))));
491
492 caja_navigation_window_remove_sidebar_panel (window,
493 sidebar_panel);
494 }
495
496 gtk_widget_destroy (GTK_WIDGET (window->sidebar)((((GtkWidget*) (void *) ((window->sidebar))))));
497 window->sidebar = NULL((void*)0);
498}
499
500static gboolean
501caja_navigation_window_state_event (GtkWidget *widget,
502 GdkEventWindowState *event)
503{
504 if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
505 {
506 g_settings_set_boolean (caja_window_state, CAJA_WINDOW_STATE_MAXIMIZED"maximized",
507 event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED);
508 }
509
510 if (GTK_WIDGET_CLASS (parent_class)((((GtkWidgetClass*) (void *) ((caja_navigation_window_parent_class
)))))
->window_state_event != NULL((void*)0))
511 {
512 return GTK_WIDGET_CLASS (parent_class)((((GtkWidgetClass*) (void *) ((caja_navigation_window_parent_class
)))))
->window_state_event (widget, event);
513 }
514
515 return FALSE(0);
516}
517
518static gboolean
519caja_navigation_window_key_press_event (GtkWidget *widget,
520 GdkEventKey *event)
521{
522 CajaNavigationWindow *window;
523 int i;
524
525 window = CAJA_NAVIGATION_WINDOW (widget)((((CajaNavigationWindow*) (void *) ((widget)))));
526
527 if (event->state & GDK_CONTROL_MASK)
528 {
529 GSettings *settings = g_settings_new ("org.mate.caja.preferences");
530 gboolean handled = FALSE(0);
531
532 if (g_settings_get_boolean (settings, "ctrl-tab-switch-tabs"))
533 {
534 CajaWindow *cajawin;
535 CajaWindowSlot *slot;
536 CajaNavigationWindowPane *pane;
537 CajaNotebook *cajanotebook;
538 GtkNotebook *notebook;
539 int pages;
540 int page_num;
541
542 cajawin = CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))));
543 slot = caja_window_get_active_slot (cajawin);
544 pane = CAJA_NAVIGATION_WINDOW_PANE (slot->pane)((((CajaNavigationWindowPane*) (void *) ((slot->pane)))));
545 cajanotebook = CAJA_NOTEBOOK (pane->notebook)((((CajaNotebook*) (void *) ((pane->notebook)))));
546 notebook = GTK_NOTEBOOK (cajanotebook)((((GtkNotebook*) (void *) ((cajanotebook)))));
547 pages = gtk_notebook_get_n_pages (notebook);
548 page_num = gtk_notebook_get_current_page (notebook);
549
550 if (event->keyval == GDK_KEY_ISO_Left_Tab0xfe20)
551 {
552 if (page_num != 0)
553 gtk_notebook_prev_page (notebook);
554 else
555 gtk_notebook_set_current_page (notebook, (pages - 1));
556 handled = TRUE(!(0));
557 }
558 if (event->keyval == GDK_KEY_Tab0xff09)
559 {
560 if (page_num != (pages -1))
561 gtk_notebook_next_page (notebook);
562 else
563 gtk_notebook_set_current_page (notebook, 0);
564 handled = TRUE(!(0));
565 }
566 }
567 g_object_unref (settings);
568
569 if (handled)
570 return TRUE(!(0));
571 }
572
573 for (i = 0; i < G_N_ELEMENTS (extra_navigation_window_keybindings)(sizeof (extra_navigation_window_keybindings) / sizeof ((extra_navigation_window_keybindings
)[0]))
; i++)
574 {
575 if (extra_navigation_window_keybindings[i].keyval == event->keyval)
576 {
577 GtkAction *action;
578
579 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
580 action = gtk_action_group_get_action (window->details->navigation_action_group,
581 extra_navigation_window_keybindings[i].action);
582
583 g_assert (action != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (action != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-navigation-window.c", 583, ((const char
*) (__func__)), "action != NULL"); } while (0)
;
584 if (gtk_action_is_sensitive (action))
585 {
586 gtk_action_activate (action);
587 return TRUE(!(0));
588 }
589 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
590
591 break;
592 }
593 }
594
595 return GTK_WIDGET_CLASS (caja_navigation_window_parent_class)((((GtkWidgetClass*) (void *) ((caja_navigation_window_parent_class
)))))
->key_press_event (widget, event);
596}
597
598static gboolean
599caja_navigation_window_button_press_event (GtkWidget *widget,
600 GdkEventButton *event)
601{
602 CajaNavigationWindow *window;
603 gboolean handled;
604
605 handled = FALSE(0);
Value stored to 'handled' is never read
606 window = CAJA_NAVIGATION_WINDOW (widget)((((CajaNavigationWindow*) (void *) ((widget)))));
607
608 if (mouse_extra_buttons && (event->button == mouse_back_button))
609 {
610 caja_navigation_window_go_back (window);
611 handled = TRUE(!(0));
612 }
613 else if (mouse_extra_buttons && (event->button == mouse_forward_button))
614 {
615 caja_navigation_window_go_forward (window);
616 handled = TRUE(!(0));
617 }
618 else if (GTK_WIDGET_CLASS (caja_navigation_window_parent_class)((((GtkWidgetClass*) (void *) ((caja_navigation_window_parent_class
)))))
->button_press_event)
619 {
620 handled = GTK_WIDGET_CLASS (caja_navigation_window_parent_class)((((GtkWidgetClass*) (void *) ((caja_navigation_window_parent_class
)))))
->button_press_event (widget, event);
621 }
622 else
623 {
624 handled = FALSE(0);
625 }
626 return handled;
627}
628
629static void
630caja_navigation_window_destroy (GtkWidget *object)
631{
632 CajaNavigationWindow *window;
633
634 window = CAJA_NAVIGATION_WINDOW (object)((((CajaNavigationWindow*) (void *) ((object)))));
635
636 caja_navigation_window_unset_focus_widget (window);
637
638 window->sidebar = NULL((void*)0);
639 g_list_foreach (window->sidebar_panels, (GFunc)g_object_unref, NULL((void*)0));
640 g_list_free (window->sidebar_panels);
641 window->sidebar_panels = NULL((void*)0);
642
643 window->details->content_paned = NULL((void*)0);
644 window->details->split_view_hpane = NULL((void*)0);
645
646 GTK_WIDGET_CLASS (parent_class)((((GtkWidgetClass*) (void *) ((caja_navigation_window_parent_class
)))))
->destroy (object);
647}
648
649static void
650caja_navigation_window_finalize (GObject *object)
651{
652 CajaNavigationWindow *window;
653
654 window = CAJA_NAVIGATION_WINDOW (object)((((CajaNavigationWindow*) (void *) ((object)))));
655
656 caja_navigation_window_remove_go_menu_callback (window);
657
658 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (always_use_browser_changed), (window))
659 always_use_browser_changed,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (always_use_browser_changed), (window))
660 window)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (always_use_browser_changed), (window))
;
661 g_signal_handlers_disconnect_by_func (caja_preferences,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (always_use_location_entry_changed), (window))
662 always_use_location_entry_changed,g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (always_use_location_entry_changed), (window))
663 window)g_signal_handlers_disconnect_matched ((caja_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (always_use_location_entry_changed), (window))
;
664
665 G_OBJECT_CLASS (parent_class)((((GObjectClass*) (void *) ((caja_navigation_window_parent_class
)))))
->finalize (object);
666}
667
668/*
669 * Main API
670 */
671
672void
673caja_navigation_window_add_sidebar_panel (CajaNavigationWindow *window,
674 CajaSidebar *sidebar_panel)
675{
676 const char *sidebar_id;
677 char *label;
678 char *tooltip;
679 char *default_id;
680 GdkPixbuf *icon;
681
682 g_return_if_fail (CAJA_IS_NAVIGATION_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_navigation_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_25 = 1; else _g_boolean_var_25 = 0
; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_NAVIGATION_WINDOW (window)"
); return; } } while (0)
;
683 g_return_if_fail (CAJA_IS_SIDEBAR (sidebar_panel))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((sidebar_panel)); GType __t = ((caja_sidebar_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_26 = 1; else _g_boolean_var_26 = 0
; _g_boolean_var_26; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_SIDEBAR (sidebar_panel)"
); return; } } while (0)
;
684 g_return_if_fail (CAJA_IS_SIDE_PANE (window->sidebar))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window->sidebar)); GType __t = (caja_side_pane_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_27 = 1; else _g_boolean_var_27 = 0
; _g_boolean_var_27; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_SIDE_PANE (window->sidebar)"
); return; } } while (0)
;
685 g_return_if_fail (g_list_find (window->sidebar_panels, sidebar_panel) == NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_28
; if (g_list_find (window->sidebar_panels, sidebar_panel) ==
((void*)0)) _g_boolean_var_28 = 1; else _g_boolean_var_28 = 0
; _g_boolean_var_28; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "g_list_find (window->sidebar_panels, sidebar_panel) == NULL"
); return; } } while (0)
;
686
687 label = caja_sidebar_get_tab_label (sidebar_panel);
688 tooltip = caja_sidebar_get_tab_tooltip (sidebar_panel);
689 caja_side_pane_add_panel (window->sidebar,
690 GTK_WIDGET (sidebar_panel)((((GtkWidget*) (void *) ((sidebar_panel))))),
691 label,
692 tooltip);
693 g_free (tooltip);
694 g_free (label);
695
696 icon = caja_sidebar_get_tab_icon (sidebar_panel);
697 caja_side_pane_set_panel_image (CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window)))))->sidebar,
698 GTK_WIDGET (sidebar_panel)((((GtkWidget*) (void *) ((sidebar_panel))))),
699 icon);
700 if (icon)
701 {
702 g_object_unref (icon);
703 }
704
705 g_signal_connect (sidebar_panel, "tab_icon_changed",g_signal_connect_data ((sidebar_panel), ("tab_icon_changed"),
((GCallback)side_panel_image_changed_callback), (window), ((
void*)0), (GConnectFlags) 0)
706 (GCallback)side_panel_image_changed_callback, window)g_signal_connect_data ((sidebar_panel), ("tab_icon_changed"),
((GCallback)side_panel_image_changed_callback), (window), ((
void*)0), (GConnectFlags) 0)
;
707
708 window->sidebar_panels = g_list_prepend (window->sidebar_panels,
709 g_object_ref (sidebar_panel)((__typeof__ (sidebar_panel)) (g_object_ref) (sidebar_panel)));
710
711 /* Show if default */
712 sidebar_id = caja_sidebar_get_sidebar_id (sidebar_panel);
713 default_id = g_settings_get_string (caja_window_state, CAJA_WINDOW_STATE_SIDE_PANE_VIEW"side-pane-view");
714 if (sidebar_id && default_id && !strcmp (sidebar_id, default_id))
715 {
716 caja_side_pane_show_panel (window->sidebar,
717 GTK_WIDGET (sidebar_panel)((((GtkWidget*) (void *) ((sidebar_panel))))));
718 }
719 g_free (default_id);
720}
721
722void
723caja_navigation_window_remove_sidebar_panel (CajaNavigationWindow *window,
724 CajaSidebar *sidebar_panel)
725{
726 g_return_if_fail (CAJA_IS_NAVIGATION_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_29
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_navigation_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_29 = 1; else _g_boolean_var_29 = 0
; _g_boolean_var_29; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_NAVIGATION_WINDOW (window)"
); return; } } while (0)
;
727 g_return_if_fail (CAJA_IS_SIDEBAR (sidebar_panel))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_30
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((sidebar_panel)); GType __t = ((caja_sidebar_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_30 = 1; else _g_boolean_var_30 = 0
; _g_boolean_var_30; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_SIDEBAR (sidebar_panel)"
); return; } } while (0)
;
728
729 if (g_list_find (window->sidebar_panels, sidebar_panel) == NULL((void*)0))
730 {
731 return;
732 }
733
734 g_signal_handlers_disconnect_by_func (sidebar_panel, side_panel_image_changed_callback, window)g_signal_handlers_disconnect_matched ((sidebar_panel), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (side_panel_image_changed_callback), (window))
;
735
736 caja_side_pane_remove_panel (window->sidebar,
737 GTK_WIDGET (sidebar_panel)((((GtkWidget*) (void *) ((sidebar_panel))))));
738 window->sidebar_panels = g_list_remove (window->sidebar_panels, sidebar_panel);
739 g_object_unref (sidebar_panel);
740}
741
742void
743caja_navigation_window_go_back (CajaNavigationWindow *window)
744{
745 caja_navigation_window_back_or_forward (window, TRUE(!(0)), 0, FALSE(0));
746}
747
748void
749caja_navigation_window_go_forward (CajaNavigationWindow *window)
750{
751 caja_navigation_window_back_or_forward (window, FALSE(0), 0, FALSE(0));
752}
753
754void
755caja_navigation_window_allow_back (CajaNavigationWindow *window, gboolean allow)
756{
757 GtkAction *action;
758
759 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
760 action = gtk_action_group_get_action (window->details->navigation_action_group,
761 CAJA_ACTION_BACK"Back");
762
763 gtk_action_set_sensitive (action, allow);
764 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
765}
766
767void
768caja_navigation_window_allow_forward (CajaNavigationWindow *window, gboolean allow)
769{
770 GtkAction *action;
771
772 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
773 action = gtk_action_group_get_action (window->details->navigation_action_group,
774 CAJA_ACTION_FORWARD"Forward");
775
776 gtk_action_set_sensitive (action, allow);
777 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
778}
779
780static void
781real_sync_title (CajaWindow *window,
782 CajaWindowSlot *slot)
783{
784 CajaNavigationWindowPane *pane;
785 CajaNotebook *notebook;
786
787 EEL_CALL_PARENT (CAJA_WINDOW_CLASS,do { if (((((CajaWindowClass*) (void *) ((caja_navigation_window_parent_class
)))))->sync_title != ((void*)0)) { (* ((((CajaWindowClass*
) (void *) ((caja_navigation_window_parent_class)))))->sync_title
) (window, slot); } } while (0)
788 sync_title, (window, slot))do { if (((((CajaWindowClass*) (void *) ((caja_navigation_window_parent_class
)))))->sync_title != ((void*)0)) { (* ((((CajaWindowClass*
) (void *) ((caja_navigation_window_parent_class)))))->sync_title
) (window, slot); } } while (0)
;
789
790 if (slot == window->details->active_pane->active_slot)
791 {
792 char *window_title;
793
794 /* if spatial mode is default, we keep "File Browser" in the window title
795 * to recognize browser windows. Otherwise, we default to the directory name.
796 */
797 if (!g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_BROWSER"always-use-browser"))
798 {
799 char *full_title;
800
801 full_title = g_strdup_printf (_("%s - File Browser")dcgettext (((void*)0), "%s - File Browser", 5), slot->title);
802 window_title = eel_str_middle_truncate (full_title, MAX_TITLE_LENGTH180);
803 g_free (full_title);
804 }
805 else
806 {
807 window_title = eel_str_middle_truncate (slot->title, MAX_TITLE_LENGTH180);
808 }
809
810 gtk_window_set_title (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), window_title);
811 g_free (window_title);
812 }
813
814 pane = CAJA_NAVIGATION_WINDOW_PANE (slot->pane)((((CajaNavigationWindowPane*) (void *) ((slot->pane)))));
815 notebook = CAJA_NOTEBOOK (pane->notebook)((((CajaNotebook*) (void *) ((pane->notebook)))));
816 caja_notebook_sync_tab_label (notebook, slot);
817}
818
819static CajaIconInfo *
820real_get_icon (CajaWindow *window,
821 CajaWindowSlot *slot)
822{
823 return caja_file_get_icon (slot->viewed_file,
824 48, gtk_widget_get_scale_factor (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))),
825 CAJA_FILE_ICON_FLAGS_IGNORE_VISITING |
826 CAJA_FILE_ICON_FLAGS_USE_MOUNT_ICON);
827}
828
829static void
830real_sync_allow_stop (CajaWindow *window,
831 CajaWindowSlot *slot)
832{
833 CajaNavigationWindow *navigation_window;
834 CajaNotebook *notebook;
835
836 navigation_window = CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window)))));
837 caja_navigation_window_set_spinner_active (navigation_window, slot->allow_stop);
838
839 notebook = CAJA_NOTEBOOK (CAJA_NAVIGATION_WINDOW_PANE (slot->pane)->notebook)((((CajaNotebook*) (void *) ((((((CajaNavigationWindowPane*) (
void *) ((slot->pane)))))->notebook)))))
;
840 caja_notebook_sync_loading (notebook, slot);
841}
842
843static void
844real_prompt_for_location (CajaWindow *window, const char *initial)
845{
846 CajaNavigationWindowPane *pane;
847
848 remember_focus_widget (CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window))))));
849
850 pane = CAJA_NAVIGATION_WINDOW_PANE (window->details->active_pane)((((CajaNavigationWindowPane*) (void *) ((window->details->
active_pane)))))
;
851
852 caja_navigation_window_pane_show_location_bar_temporarily (pane);
853 caja_navigation_window_pane_show_navigation_bar_temporarily (pane);
854
855 if (initial)
856 {
857 caja_location_bar_set_location (CAJA_LOCATION_BAR (pane->navigation_bar)((((CajaLocationBar*) (void *) ((pane->navigation_bar))))),
858 initial);
859 }
860}
861
862void
863caja_navigation_window_show_search (CajaNavigationWindow *window)
864{
865 CajaNavigationWindowPane *pane;
866
867 pane = CAJA_NAVIGATION_WINDOW_PANE (CAJA_WINDOW (window)->details->active_pane)((((CajaNavigationWindowPane*) (void *) ((((((CajaWindow*) (void
*) ((window)))))->details->active_pane)))))
;
868 if (!caja_navigation_window_pane_search_bar_showing (pane))
869 {
870 remember_focus_widget (window);
871
872 caja_navigation_window_pane_show_location_bar_temporarily (pane);
873 caja_navigation_window_pane_set_bar_mode (pane, CAJA_BAR_SEARCH);
874 pane->temporary_search_bar = TRUE(!(0));
875 caja_search_bar_clear (CAJA_SEARCH_BAR (pane->search_bar)((((CajaSearchBar*) (void *) ((pane->search_bar))))));
876 }
877
878 caja_search_bar_grab_focus (CAJA_SEARCH_BAR (pane->search_bar)((((CajaSearchBar*) (void *) ((pane->search_bar))))));
879}
880
881void
882caja_navigation_window_hide_search (CajaNavigationWindow *window)
883{
884 CajaNavigationWindowPane *pane = CAJA_NAVIGATION_WINDOW_PANE (CAJA_WINDOW (window)->details->active_pane)((((CajaNavigationWindowPane*) (void *) ((((((CajaWindow*) (void
*) ((window)))))->details->active_pane)))))
;
885 if (caja_navigation_window_pane_search_bar_showing (pane))
886 {
887 if (caja_navigation_window_pane_hide_temporary_bars (pane))
888 {
889 caja_navigation_window_restore_focus_widget (window);
890 }
891 }
892}
893
894/* This updates the UI state of the search button, but does not
895 in itself trigger a search action */
896void
897caja_navigation_window_set_search_button (CajaNavigationWindow *window,
898 gboolean state)
899{
900 GtkAction *action;
901
902 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
903 action = gtk_action_group_get_action (window->details->navigation_action_group,
904 "Search");
905
906 /* Block callback so we don't activate the action and thus focus the
907 search entry */
908 g_object_set_data (G_OBJECT (action)((((GObject*) (void *) ((action))))), "blocked", GINT_TO_POINTER (1)((gpointer) (glong) (1)));
909 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), state);
910 g_object_set_data (G_OBJECT (action)((((GObject*) (void *) ((action))))), "blocked", NULL((void*)0));
911 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
912}
913
914static void
915side_panel_image_changed_callback (CajaSidebar *side_panel,
916 gpointer callback_data)
917{
918 CajaWindow *window;
919 GdkPixbuf *icon;
920
921 window = CAJA_WINDOW (callback_data)((((CajaWindow*) (void *) ((callback_data)))));
922
923 icon = caja_sidebar_get_tab_icon (side_panel);
924 caja_side_pane_set_panel_image (CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window)))))->sidebar,
925 GTK_WIDGET (side_panel)((((GtkWidget*) (void *) ((side_panel))))),
926 icon);
927 if (icon != NULL((void*)0))
928 {
929 g_object_unref (icon);
930 }
931}
932
933/**
934 * add_sidebar_panels:
935 * @window: A CajaNavigationWindow
936 *
937 * Adds all sidebars available
938 *
939 */
940static void
941add_sidebar_panels (CajaNavigationWindow *window)
942{
943 GtkWidget *current;
944 GList *providers;
945 GList *p;
946 CajaSidebar *sidebar_panel = NULL((void*)0);
947
948 g_assert (CAJA_IS_NAVIGATION_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_navigation_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_assertion_message_expr (
((gchar*) 0), "caja-navigation-window.c", 948, ((const char*)
(__func__)), "CAJA_IS_NAVIGATION_WINDOW (window)"); } while (
0)
;
949
950 if (window->sidebar == NULL((void*)0))
951 {
952 return;
953 }
954
955 providers = caja_module_get_extensions_for_type (CAJA_TYPE_SIDEBAR_PROVIDER(caja_sidebar_provider_get_type ()));
956
957 for (p = providers; p != NULL((void*)0); p = p->next)
958 {
959 CajaSidebarProvider *provider;
960
961 provider = CAJA_SIDEBAR_PROVIDER (p->data)((((CajaSidebarProvider*) (void *) ((p->data)))));
962
963 sidebar_panel = caja_sidebar_provider_create (provider,
964 CAJA_WINDOW_INFO (window)((((CajaWindowInfo*) (void *) ((window))))));
965 caja_navigation_window_add_sidebar_panel (window,
966 sidebar_panel);
967
968 g_object_unref (sidebar_panel);
969 }
970
971 caja_module_extension_list_free (providers);
972
973 current = caja_side_pane_get_current_panel (window->sidebar);
974 set_current_side_panel
975 (window,
976 CAJA_SIDEBAR (current)((((CajaSidebar*) (void *) ((current))))));
977}
978
979gboolean
980caja_navigation_window_toolbar_showing (CajaNavigationWindow *window)
981{
982 if (window->details->toolbar != NULL((void*)0))
983 {
984 return gtk_widget_get_visible (window->details->toolbar);
985 }
986 /* If we're not visible yet we haven't changed visibility, so its TRUE */
987 return TRUE(!(0));
988}
989
990void
991caja_navigation_window_hide_status_bar (CajaNavigationWindow *window)
992{
993 gtk_widget_hide (CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->statusbar);
994
995 caja_navigation_window_update_show_hide_menu_items (window);
996
997 g_settings_set_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_STATUS_BAR"start-with-status-bar", FALSE(0));
998}
999
1000void
1001caja_navigation_window_show_status_bar (CajaNavigationWindow *window)
1002{
1003 gtk_widget_show (CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->statusbar);
1004
1005 caja_navigation_window_update_show_hide_menu_items (window);
1006
1007 g_settings_set_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_STATUS_BAR"start-with-status-bar", TRUE(!(0)));
1008}
1009
1010gboolean
1011caja_navigation_window_status_bar_showing (CajaNavigationWindow *window)
1012{
1013 if (CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->statusbar != NULL((void*)0))
1014 {
1015 return gtk_widget_get_visible (CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->statusbar);
1016 }
1017 /* If we're not visible yet we haven't changed visibility, so its TRUE */
1018 return TRUE(!(0));
1019}
1020
1021
1022void
1023caja_navigation_window_hide_toolbar (CajaNavigationWindow *window)
1024{
1025 gtk_widget_hide (window->details->toolbar);
1026 caja_navigation_window_update_show_hide_menu_items (window);
1027 g_settings_set_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_TOOLBAR"start-with-toolbar", FALSE(0));
1028}
1029
1030void
1031caja_navigation_window_show_toolbar (CajaNavigationWindow *window)
1032{
1033 gtk_widget_show (window->details->toolbar);
1034 caja_navigation_window_update_show_hide_menu_items (window);
1035 g_settings_set_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_TOOLBAR"start-with-toolbar", TRUE(!(0)));
1036}
1037
1038void
1039caja_navigation_window_hide_sidebar (CajaNavigationWindow *window)
1040{
1041 if (window->sidebar == NULL((void*)0))
1042 {
1043 return;
1044 }
1045
1046 caja_navigation_window_tear_down_sidebar (window);
1047 caja_navigation_window_update_show_hide_menu_items (window);
1048
1049 g_settings_set_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_SIDEBAR"start-with-sidebar", FALSE(0));
1050}
1051
1052void
1053caja_navigation_window_show_sidebar (CajaNavigationWindow *window)
1054{
1055 if (window->sidebar != NULL((void*)0))
1056 {
1057 return;
1058 }
1059
1060 caja_navigation_window_set_up_sidebar (window);
1061 caja_navigation_window_update_show_hide_menu_items (window);
1062 g_settings_set_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_SIDEBAR"start-with-sidebar", TRUE(!(0)));
1063}
1064
1065gboolean
1066caja_navigation_window_sidebar_showing (CajaNavigationWindow *window)
1067{
1068 g_return_val_if_fail (CAJA_IS_NAVIGATION_WINDOW (window), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_navigation_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_32 = 1; else _g_boolean_var_32 = 0
; _g_boolean_var_32; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "CAJA_IS_NAVIGATION_WINDOW (window)"
); return ((0)); } } while (0)
;
1069
1070 return (window->sidebar != NULL((void*)0))
1071 && gtk_widget_get_visible (gtk_paned_get_child1 (GTK_PANED (window->details->content_paned)((((GtkPaned*) (void *) ((window->details->content_paned
)))))
));
1072}
1073
1074/**
1075 * caja_navigation_window_get_base_page_index:
1076 * @window: Window to get index from
1077 *
1078 * Returns the index of the base page in the history list.
1079 * Base page is not the currently displayed page, but the page
1080 * that acts as the base from which the back and forward commands
1081 * navigate from.
1082 */
1083gint
1084caja_navigation_window_get_base_page_index (CajaNavigationWindow *window)
1085{
1086 CajaNavigationWindowSlot *slot;
1087 gint forward_count;
1088
1089 slot = CAJA_NAVIGATION_WINDOW_SLOT (CAJA_WINDOW (window)->details->active_pane->active_slot)((((CajaNavigationWindowSlot*) (void *) ((((((CajaWindow*) (void
*) ((window)))))->details->active_pane->active_slot
)))))
;
1090
1091 forward_count = g_list_length (slot->forward_list);
1092
1093 /* If forward is empty, the base it at the top of the list */
1094 if (forward_count == 0)
1095 {
1096 return 0;
1097 }
1098
1099 /* The forward count indicate the relative postion of the base page
1100 * in the history list
1101 */
1102 return forward_count;
1103}
1104
1105/**
1106 * caja_navigation_window_show:
1107 * @widget: a #GtkWidget.
1108 *
1109 * Call parent and then show/hide window items
1110 * base on user prefs.
1111 */
1112static void
1113caja_navigation_window_show (GtkWidget *widget)
1114{
1115 CajaNavigationWindow *window;
1116 gboolean show_location_bar;
1117 gboolean always_use_location_entry;
1118 GList *walk;
1119
1120 window = CAJA_NAVIGATION_WINDOW (widget)((((CajaNavigationWindow*) (void *) ((widget)))));
1121
1122 /* Initially show or hide views based on preferences; once the window is displayed
1123 * these can be controlled on a per-window basis from View menu items.
1124 */
1125
1126 if (g_settings_get_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_TOOLBAR"start-with-toolbar"))
1127 {
1128 caja_navigation_window_show_toolbar (window);
1129 }
1130 else
1131 {
1132 caja_navigation_window_hide_toolbar (window);
1133 }
1134
1135 show_location_bar = g_settings_get_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_LOCATION_BAR"start-with-location-bar");
1136 always_use_location_entry = g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_ALWAYS_USE_LOCATION_ENTRY"always-use-location-entry");
1137 for (walk = CAJA_WINDOW(window)((((CajaWindow*) (void *) ((window)))))->details->panes; walk; walk = walk->next)
1138 {
1139 CajaNavigationWindowPane *pane = walk->data;
1140 if (show_location_bar)
1141 {
1142 caja_navigation_window_pane_show_location_bar (pane, FALSE(0));
1143 }
1144 else
1145 {
1146 caja_navigation_window_pane_hide_location_bar (pane, FALSE(0));
1147 }
1148
1149 if (always_use_location_entry)
1150 {
1151 caja_navigation_window_pane_set_bar_mode (pane, CAJA_BAR_NAVIGATION);
1152 }
1153 else
1154 {
1155 caja_navigation_window_pane_set_bar_mode (pane, CAJA_BAR_PATH);
1156 }
1157 }
1158
1159 if (g_settings_get_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_SIDEBAR"start-with-sidebar"))
1160 {
1161 caja_navigation_window_show_sidebar (window);
1162 }
1163 else
1164 {
1165 caja_navigation_window_hide_sidebar (window);
1166 }
1167
1168 if (g_settings_get_boolean (caja_window_state, CAJA_WINDOW_STATE_START_WITH_STATUS_BAR"start-with-status-bar"))
1169 {
1170 caja_navigation_window_show_status_bar (window);
1171 }
1172 else
1173 {
1174 caja_navigation_window_hide_status_bar (window);
1175 }
1176
1177 GTK_WIDGET_CLASS (parent_class)((((GtkWidgetClass*) (void *) ((caja_navigation_window_parent_class
)))))
->show (widget);
1178}
1179
1180static void
1181caja_navigation_window_save_geometry (CajaNavigationWindow *window)
1182{
1183 gboolean is_maximized;
1184
1185 g_assert (CAJA_IS_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (caja_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_33
= 1; else _g_boolean_var_33 = 0; _g_boolean_var_33; }), 1)) ;
else g_assertion_message_expr (((gchar*) 0), "caja-navigation-window.c"
, 1185, ((const char*) (__func__)), "CAJA_IS_WINDOW (window)"
); } while (0)
;
1186
1187 if (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))))
1188 {
1189 char *geometry_string;
1190
1191 geometry_string = eel_gtk_window_get_geometry_string (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1192 is_maximized = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))))
1193 & GDK_WINDOW_STATE_MAXIMIZED;
1194
1195 if (!is_maximized)
1196 {
1197 g_settings_set_string (caja_window_state,
1198 CAJA_WINDOW_STATE_GEOMETRY"geometry",
1199 geometry_string);
1200 }
1201 g_free (geometry_string);
1202
1203 g_settings_set_boolean (caja_window_state,
1204 CAJA_WINDOW_STATE_MAXIMIZED"maximized",
1205 is_maximized);
1206 }
1207}
1208
1209static void
1210real_window_close (CajaWindow *window)
1211{
1212 caja_navigation_window_save_geometry (CAJA_NAVIGATION_WINDOW (window)((((CajaNavigationWindow*) (void *) ((window))))));
1213}
1214
1215static void
1216real_get_min_size (CajaWindow *window,
1217 guint *min_width, guint *min_height)
1218{
1219 if (min_width)
1220 {
1221 *min_width = CAJA_NAVIGATION_WINDOW_MIN_WIDTH200;
1222 }
1223 if (min_height)
1224 {
1225 *min_height = CAJA_NAVIGATION_WINDOW_MIN_HEIGHT200;
1226 }
1227}
1228
1229static void
1230real_get_default_size (CajaWindow *window,
1231 guint *default_width, guint *default_height)
1232{
1233 if (default_width)
1234 {
1235 *default_width = CAJA_NAVIGATION_WINDOW_DEFAULT_WIDTH800;
1236 }
1237
1238 if (default_height)
1239 {
1240 *default_height = CAJA_NAVIGATION_WINDOW_DEFAULT_HEIGHT550;
1241 }
1242}
1243
1244static CajaWindowSlot *
1245real_open_slot (CajaWindowPane *pane,
1246 CajaWindowOpenSlotFlags flags)
1247{
1248 CajaWindowSlot *slot;
1249
1250 slot = (CajaWindowSlot *) g_object_new (CAJA_TYPE_NAVIGATION_WINDOW_SLOT(caja_navigation_window_slot_get_type()), NULL((void*)0));
1251 slot->pane = pane;
1252
1253 caja_navigation_window_pane_add_slot_in_tab (CAJA_NAVIGATION_WINDOW_PANE (pane)((((CajaNavigationWindowPane*) (void *) ((pane))))), slot, flags);
1254 gtk_widget_show (slot->content_box);
1255
1256 return slot;
1257}
1258
1259static void
1260real_close_slot (CajaWindowPane *pane,
1261 CajaWindowSlot *slot)
1262{
1263 int page_num;
1264 GtkNotebook *notebook;
1265
1266 notebook = GTK_NOTEBOOK (CAJA_NAVIGATION_WINDOW_PANE (pane)->notebook)((((GtkNotebook*) (void *) ((((((CajaNavigationWindowPane*) (
void *) ((pane)))))->notebook)))))
;
1267
1268 page_num = gtk_notebook_page_num (notebook, slot->content_box);
1269 g_assert (page_num >= 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if (page_num >= 0) _g_boolean_var_34 = 1; else _g_boolean_var_34
= 0; _g_boolean_var_34; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "caja-navigation-window.c", 1269, ((const char
*) (__func__)), "page_num >= 0"); } while (0)
;
1270
1271 caja_navigation_window_pane_remove_page (CAJA_NAVIGATION_WINDOW_PANE (pane)((((CajaNavigationWindowPane*) (void *) ((pane))))), page_num);
1272
1273 gtk_notebook_set_show_tabs (notebook,
1274 gtk_notebook_get_n_pages (notebook) > 1);
1275
1276 EEL_CALL_PARENT (CAJA_WINDOW_CLASS,do { if (((((CajaWindowClass*) (void *) ((caja_navigation_window_parent_class
)))))->close_slot != ((void*)0)) { (* ((((CajaWindowClass*
) (void *) ((caja_navigation_window_parent_class)))))->close_slot
) (pane, slot); } } while (0)
1277 close_slot, (pane, slot))do { if (((((CajaWindowClass*) (void *) ((caja_navigation_window_parent_class
)))))->close_slot != ((void*)0)) { (* ((((CajaWindowClass*
) (void *) ((caja_navigation_window_parent_class)))))->close_slot
) (pane, slot); } } while (0)
;
1278}
1279
1280static void
1281caja_navigation_window_class_init (CajaNavigationWindowClass *class)
1282{
1283 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->window_type = CAJA_WINDOW_NAVIGATION;
1284 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->bookmarks_placeholder = MENU_PATH_BOOKMARKS_PLACEHOLDER"/MenuBar/Other Menus/Bookmarks/Bookmarks Placeholder";
1285
1286 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = caja_navigation_window_finalize;
1287
1288 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->destroy = caja_navigation_window_destroy;
1289 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->show = caja_navigation_window_show;
1290 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->window_state_event = caja_navigation_window_state_event;
1291 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->key_press_event = caja_navigation_window_key_press_event;
1292 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->button_press_event = caja_navigation_window_button_press_event;
1293 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->sync_allow_stop = real_sync_allow_stop;
1294 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->prompt_for_location = real_prompt_for_location;
1295 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->sync_title = real_sync_title;
1296 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->get_icon = real_get_icon;
1297 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->get_min_size = real_get_min_size;
1298 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->get_default_size = real_get_default_size;
1299 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->close = real_window_close;
1300
1301 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->open_slot = real_open_slot;
1302 CAJA_WINDOW_CLASS (class)((((CajaWindowClass*) (void *) ((class)))))->close_slot = real_close_slot;
1303
1304 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "mouse-back-button"
), (((GCallback) (mouse_back_button_changed))), (((void*)0)),
((void*)0), G_CONNECT_SWAPPED)
1305 "changed::" CAJA_PREFERENCES_MOUSE_BACK_BUTTON,g_signal_connect_data ((caja_preferences), ("changed::" "mouse-back-button"
), (((GCallback) (mouse_back_button_changed))), (((void*)0)),
((void*)0), G_CONNECT_SWAPPED)
1306 G_CALLBACK(mouse_back_button_changed),g_signal_connect_data ((caja_preferences), ("changed::" "mouse-back-button"
), (((GCallback) (mouse_back_button_changed))), (((void*)0)),
((void*)0), G_CONNECT_SWAPPED)
1307 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "mouse-back-button"
), (((GCallback) (mouse_back_button_changed))), (((void*)0)),
((void*)0), G_CONNECT_SWAPPED)
;
1308
1309 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "mouse-forward-button"
), (((GCallback) (mouse_forward_button_changed))), (((void*)0
)), ((void*)0), G_CONNECT_SWAPPED)
1310 "changed::" CAJA_PREFERENCES_MOUSE_FORWARD_BUTTON,g_signal_connect_data ((caja_preferences), ("changed::" "mouse-forward-button"
), (((GCallback) (mouse_forward_button_changed))), (((void*)0
)), ((void*)0), G_CONNECT_SWAPPED)
1311 G_CALLBACK(mouse_forward_button_changed),g_signal_connect_data ((caja_preferences), ("changed::" "mouse-forward-button"
), (((GCallback) (mouse_forward_button_changed))), (((void*)0
)), ((void*)0), G_CONNECT_SWAPPED)
1312 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "mouse-forward-button"
), (((GCallback) (mouse_forward_button_changed))), (((void*)0
)), ((void*)0), G_CONNECT_SWAPPED)
;
1313
1314 g_signal_connect_swapped (caja_preferences,g_signal_connect_data ((caja_preferences), ("changed::" "mouse-use-extra-buttons"
), (((GCallback) (use_extra_mouse_buttons_changed))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
1315 "changed::" CAJA_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS,g_signal_connect_data ((caja_preferences), ("changed::" "mouse-use-extra-buttons"
), (((GCallback) (use_extra_mouse_buttons_changed))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
1316 G_CALLBACK(use_extra_mouse_buttons_changed),g_signal_connect_data ((caja_preferences), ("changed::" "mouse-use-extra-buttons"
), (((GCallback) (use_extra_mouse_buttons_changed))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
1317 NULL)g_signal_connect_data ((caja_preferences), ("changed::" "mouse-use-extra-buttons"
), (((GCallback) (use_extra_mouse_buttons_changed))), (((void
*)0)), ((void*)0), G_CONNECT_SWAPPED)
;
1318}
1319
1320static CajaWindowSlot *
1321create_extra_pane (CajaNavigationWindow *window)
1322{
1323 CajaWindow *win;
1324 CajaNavigationWindowPane *pane;
1325 CajaWindowSlot *slot;
1326 GtkPaned *paned;
1327
1328 win = CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))));
1329
1330 /* New pane */
1331 pane = caja_navigation_window_pane_new (win);
1332 win->details->panes = g_list_append (win->details->panes, pane);
1333
1334 caja_navigation_window_pane_setup (pane);
1335
1336 paned = GTK_PANED (window->details->split_view_hpane)((((GtkPaned*) (void *) ((window->details->split_view_hpane
)))))
;
1337 if (gtk_paned_get_child1 (paned) == NULL((void*)0))
1338 {
1339 gtk_paned_pack1 (paned, pane->widget, TRUE(!(0)), FALSE(0));
1340 }
1341 else
1342 {
1343 gtk_paned_pack2 (paned, pane->widget, TRUE(!(0)), FALSE(0));
1344 }
1345
1346 /* slot */
1347 slot = caja_window_open_slot (CAJA_WINDOW_PANE (pane)((((CajaWindowPane*) (void *) ((pane))))),
1348 CAJA_WINDOW_OPEN_SLOT_APPEND);
1349 CAJA_WINDOW_PANE (pane)((((CajaWindowPane*) (void *) ((pane)))))->active_slot = slot;
1350
1351 return slot;
1352}
1353
1354void
1355caja_navigation_window_split_view_on (CajaNavigationWindow *window)
1356{
1357 CajaWindow *win;
1358 CajaNavigationWindowPane *pane;
1359 CajaWindowSlot *slot, *old_active_slot;
1360 GFile *location;
1361 GtkAction *action;
1362
1363 win = CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))));
1364
1365 old_active_slot = caja_window_get_active_slot (win);
1366 slot = create_extra_pane (window);
1367 pane = CAJA_NAVIGATION_WINDOW_PANE (slot->pane)((((CajaNavigationWindowPane*) (void *) ((slot->pane)))));
1368
1369 location = NULL((void*)0);
1370 if (old_active_slot != NULL((void*)0))
1371 {
1372 location = caja_window_slot_get_location (old_active_slot);
1373 if (location != NULL((void*)0))
1374 {
1375 if (g_file_has_uri_scheme (location, "x-caja-search"))
1376 {
1377 g_object_unref (location);
1378 location = NULL((void*)0);
1379 }
1380 }
1381 }
1382 if (location == NULL((void*)0))
1383 {
1384 location = g_file_new_for_path (g_get_home_dir ());
1385 }
1386
1387 caja_window_slot_go_to (slot, location, FALSE)caja_window_slot_open_location_full(slot, location, CAJA_WINDOW_OPEN_ACCORDING_TO_MODE
, ((0) ? CAJA_WINDOW_OPEN_FLAG_NEW_TAB : 0), ((void*)0), ((void
*)0), ((void*)0))
;
1388 g_object_unref (location);
1389
1390 G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push + clang diagnostic ignored "-Wdeprecated-declarations"
+
;
1391 action = gtk_action_group_get_action (CAJA_NAVIGATION_WINDOW (CAJA_WINDOW_PANE (pane)->window)((((CajaNavigationWindow*) (void *) ((((((CajaWindowPane*) (void
*) ((pane)))))->window)))))
->details->navigation_action_group,
1392 CAJA_ACTION_SHOW_HIDE_LOCATION_BAR"Show Hide Location Bar");
1393 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action)))))))
1394 {
1395 caja_navigation_window_pane_show_location_bar (pane, TRUE(!(0)));
1396 }
1397 else
1398 {
1399 caja_navigation_window_pane_hide_location_bar (pane, TRUE(!(0)));
1400 }
1401 G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop +;
1402}
1403
1404void
1405caja_navigation_window_split_view_off (CajaNavigationWindow *window)
1406{
1407 CajaWindow *win;
1408 GList *l, *next;
1409 CajaWindowPane *active_pane;
1410 CajaWindowPane *pane = NULL((void*)0);
1411
1412 win = CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))));
1413
1414 g_return_if_fail (win)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if (win) _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__)), "win"); return; }
} while (0)
;
1415
1416 active_pane = win->details->active_pane;
1417
1418 /* delete all panes except the first (main) pane */
1419 for (l = win->details->panes; l != NULL((void*)0); l = next)
1420 {
1421 next = l->next;
1422 pane = l->data;
1423 if (pane != active_pane)
1424 {
1425 caja_window_close_pane (pane);
1426 }
1427 }
1428
1429 caja_navigation_window_update_show_hide_menu_items (window);
1430 caja_navigation_window_update_split_view_actions_sensitivity (window);
1431}
1432
1433gboolean
1434caja_navigation_window_split_view_showing (CajaNavigationWindow *window)
1435{
1436 return g_list_length (CAJA_WINDOW (window)((((CajaWindow*) (void *) ((window)))))->details->panes) > 1;
1437}
diff --git a/2024-07-29-023715-6438-1/report-fd4851.html b/2024-07-29-023715-6438-1/report-fd4851.html new file mode 100644 index 000000000..4d6980c14 --- /dev/null +++ b/2024-07-29-023715-6438-1/report-fd4851.html @@ -0,0 +1,6536 @@ + + + +fm-properties-window.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:src/file-manager/fm-properties-window.c
Warning:line 2237, column 2
Value stored to 'file_status' 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 fm-properties-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 -fdebug-compilation-dir=/rootdir/src/file-manager -fcoverage-compilation-dir=/rootdir/src/file-manager -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I ../../mate-submodules -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/freetype2 -I /usr/include/harfbuzz -I /usr/include/startup-notification-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/gail-3.0 -I /usr/include/atk-1.0 -I /usr/include/libxml2 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/dconf -D WITH_GZFILEOP -D CAJA_DATADIR="/usr/local/share/caja" -D DATADIR="/usr/local/share" -D ICONDIR="/usr/local/share/icons" -D PIXMAPDIR="/usr/local/share/pixmaps" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D PIC -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2024-07-29-023715-6438-1 -x c fm-properties-window.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* fm-properties-window.c - window that lets user modify file properties
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Mate Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Mate Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <string.h>
27#include <cairo.h>
28
29#include <gtk/gtk.h>
30#include <gdk/gdkkeysyms.h>
31#include <glib/gi18n.h>
32#include <sys/stat.h>
33
34#include <eel/eel-accessibility.h>
35#include <eel/eel-gdk-pixbuf-extensions.h>
36#include <eel/eel-glib-extensions.h>
37#include <eel/eel-mate-extensions.h>
38#include <eel/eel-gtk-extensions.h>
39#include <eel/eel-labeled-image.h>
40#include <eel/eel-stock-dialogs.h>
41#include <eel/eel-vfs-extensions.h>
42#include <eel/eel-wrap-table.h>
43
44#include <libcaja-extension/caja-property-page-provider.h>
45
46#include <libcaja-private/caja-mime-application-chooser.h>
47#include <libcaja-private/caja-entry.h>
48#include <libcaja-private/caja-extensions.h>
49#include <libcaja-private/caja-file-attributes.h>
50#include <libcaja-private/caja-file-operations.h>
51#include <libcaja-private/caja-desktop-icon-file.h>
52#include <libcaja-private/caja-global-preferences.h>
53#include <libcaja-private/caja-emblem-utils.h>
54#include <libcaja-private/caja-link.h>
55#include <libcaja-private/caja-metadata.h>
56#include <libcaja-private/caja-module.h>
57#include <libcaja-private/caja-mime-actions.h>
58
59#include "fm-properties-window.h"
60#include "fm-ditem-page.h"
61#include "fm-error-reporting.h"
62
63#if HAVE_SYS_VFS_H1
64#include <sys/vfs.h>
65#elif HAVE_SYS_MOUNT_H1
66#if HAVE_SYS_PARAM_H1
67#include <sys/param.h>
68#endif
69#include <sys/mount.h>
70#endif
71
72#define USED_FILL_R0.988235294 0.988235294
73#define USED_FILL_G0.91372549 0.91372549
74#define USED_FILL_B0.309803922 0.309803922
75
76#define FREE_FILL_R0.447058824 0.447058824
77#define FREE_FILL_G0.623529412 0.623529412
78#define FREE_FILL_B0.811764706 0.811764706
79
80#define PREVIEW_IMAGE_WIDTH96 96
81
82#define ROW_PAD6 6
83
84static GHashTable *windows;
85static GHashTable *pending_lists;
86
87struct _FMPropertiesWindowPrivate {
88 GList *original_files;
89 GList *target_files;
90
91 GtkNotebook *notebook;
92
93 GtkGrid *basic_grid;
94
95 GtkWidget *icon_button;
96 GtkWidget *icon_image;
97 GtkWidget *icon_chooser;
98
99 GtkLabel *name_label;
100 GtkWidget *name_field;
101 unsigned int name_row;
102 char *pending_name;
103
104 GtkLabel *directory_contents_title_field;
105 GtkLabel *directory_contents_value_field;
106 guint update_directory_contents_timeout_id;
107 guint update_files_timeout_id;
108
109 GList *emblem_buttons;
110 GHashTable *initial_emblems;
111
112 CajaFile *group_change_file;
113 char *group_change_group;
114 unsigned int group_change_timeout;
115 CajaFile *owner_change_file;
116 char *owner_change_owner;
117 unsigned int owner_change_timeout;
118
119 GList *permission_buttons;
120 GList *permission_combos;
121 GHashTable *initial_permissions;
122 gboolean has_recursive_apply;
123
124 GList *value_fields;
125
126 GList *mime_list;
127
128 gboolean deep_count_finished;
129
130 guint total_count;
131 goffset total_size;
132 goffset total_size_on_disk;
133
134 guint long_operation_underway;
135
136 GList *changed_files;
137
138 guint64 volume_capacity;
139 guint64 volume_free;
140
141 GdkRGBA used_color;
142 GdkRGBA free_color;
143 GdkRGBA used_stroke_color;
144 GdkRGBA free_stroke_color;
145};
146
147typedef enum {
148 PERMISSIONS_CHECKBOXES_READ,
149 PERMISSIONS_CHECKBOXES_WRITE,
150 PERMISSIONS_CHECKBOXES_EXECUTE
151} CheckboxType;
152
153enum {
154 TITLE_COLUMN,
155 VALUE_COLUMN,
156 COLUMN_COUNT
157};
158
159typedef struct {
160 GList *original_files;
161 GList *target_files;
162 GtkWidget *parent_widget;
163 char *pending_key;
164 GHashTable *pending_files;
165} StartupData;
166
167/* drag and drop definitions */
168
169enum {
170 TARGET_URI_LIST,
171 TARGET_MATE_URI_LIST,
172 TARGET_RESET_BACKGROUND
173};
174
175static const GtkTargetEntry target_table[] = {
176 { "text/uri-list", 0, TARGET_URI_LIST },
177 { "x-special/mate-icon-list", 0, TARGET_MATE_URI_LIST },
178 { "x-special/mate-reset-background", 0, TARGET_RESET_BACKGROUND }
179};
180
181#define DIRECTORY_CONTENTS_UPDATE_INTERVAL200 200 /* milliseconds */
182#define FILES_UPDATE_INTERVAL200 200 /* milliseconds */
183#define STANDARD_EMBLEM_HEIGHT52 52
184#define EMBLEM_LABEL_SPACING2 2
185
186/*
187 * A timeout before changes through the user/group combo box will be applied.
188 * When quickly changing owner/groups (i.e. by keyboard or scroll wheel),
189 * this ensures that the GUI doesn't end up unresponsive.
190 *
191 * Both combos react on changes by scheduling a new change and unscheduling
192 * or cancelling old pending changes.
193 */
194#define CHOWN_CHGRP_TIMEOUT300 300 /* milliseconds */
195
196static void directory_contents_value_field_update (FMPropertiesWindow *window);
197static void file_changed_callback (CajaFile *file,
198 gpointer user_data);
199static void permission_button_update (FMPropertiesWindow *window,
200 GtkToggleButton *button);
201static void permission_combo_update (FMPropertiesWindow *window,
202 GtkComboBox *combo);
203static void value_field_update (FMPropertiesWindow *window,
204 GtkLabel *field);
205static void properties_window_update (FMPropertiesWindow *window,
206 GList *files);
207static void is_directory_ready_callback (CajaFile *file,
208 gpointer data);
209static void cancel_group_change_callback (FMPropertiesWindow *window);
210static void cancel_owner_change_callback (FMPropertiesWindow *window);
211static void parent_widget_destroyed_callback (GtkWidget *widget,
212 gpointer callback_data);
213static void select_image_button_callback (GtkWidget *widget,
214 FMPropertiesWindow *properties_window);
215static void set_icon (const char *icon_path,
216 FMPropertiesWindow *properties_window);
217static void remove_pending (StartupData *data,
218 gboolean cancel_call_when_ready,
219 gboolean cancel_timed_wait,
220 gboolean cancel_destroy_handler);
221static void append_extension_pages (FMPropertiesWindow *window);
222
223static gboolean name_field_focus_out (CajaEntry *name_field,
224 GdkEventFocus *event,
225 gpointer callback_data);
226static void name_field_activate (CajaEntry *name_field,
227 gpointer callback_data);
228static GtkLabel *attach_ellipsizing_value_label (GtkGrid *grid,
229 GtkWidget *sibling,
230
231 const char *initial_text);
232
233static GtkWidget* create_pie_widget (FMPropertiesWindow *window);
234
235G_DEFINE_TYPE_WITH_PRIVATE (FMPropertiesWindow, fm_properties_window, GTK_TYPE_DIALOG)static void fm_properties_window_init (FMPropertiesWindow *self
); static void fm_properties_window_class_init (FMPropertiesWindowClass
*klass); static GType fm_properties_window_get_type_once (void
); static gpointer fm_properties_window_parent_class = ((void
*)0); static gint FMPropertiesWindow_private_offset; static void
fm_properties_window_class_intern_init (gpointer klass) { fm_properties_window_parent_class
= g_type_class_peek_parent (klass); if (FMPropertiesWindow_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &FMPropertiesWindow_private_offset
); fm_properties_window_class_init ((FMPropertiesWindowClass*
) klass); } __attribute__ ((__unused__)) static inline gpointer
fm_properties_window_get_instance_private (FMPropertiesWindow
*self) { return (((gpointer) ((guint8*) (self) + (glong) (FMPropertiesWindow_private_offset
)))); } GType fm_properties_window_get_type (void) { static GType
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_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= fm_properties_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_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType fm_properties_window_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_dialog_get_type ()), g_intern_static_string ("FMPropertiesWindow"
), sizeof (FMPropertiesWindowClass), (GClassInitFunc)(void (*
)(void)) fm_properties_window_class_intern_init, sizeof (FMPropertiesWindow
), (GInstanceInitFunc)(void (*)(void)) fm_properties_window_init
, (GTypeFlags) 0); { {{ FMPropertiesWindow_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (FMPropertiesWindowPrivate)); };} }
return g_define_type_id; }
;
236
237static gboolean
238is_multi_file_window (FMPropertiesWindow *window)
239{
240 GList *l;
241 int count;
242
243 count = 0;
244
245 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
246 if (!caja_file_is_gone (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
247 count++;
248 if (count > 1) {
249 return TRUE(!(0));
250 }
251 }
252 }
253
254 return FALSE(0);
255}
256
257static int
258get_not_gone_original_file_count (FMPropertiesWindow *window)
259{
260 GList *l;
261 int count;
262
263 count = 0;
264
265 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
266 if (!caja_file_is_gone (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
267 count++;
268 }
269 }
270
271 return count;
272}
273
274static CajaFile *
275get_original_file (FMPropertiesWindow *window)
276{
277 g_return_val_if_fail (!is_multi_file_window (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (!is_multi_file_window (window)) _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__)), "!is_multi_file_window (window)"); return (((void
*)0)); } } while (0)
;
278
279 if (window->details->original_files == NULL((void*)0)) {
280 return NULL((void*)0);
281 }
282
283 return CAJA_FILE (window->details->original_files->data)((((CajaFile*) (void *) ((window->details->original_files
->data)))))
;
284}
285
286static CajaFile *
287get_target_file_for_original_file (CajaFile *file)
288{
289 CajaFile *target_file;
290
291 target_file = NULL((void*)0);
292 if (CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
) {
293 CajaDesktopLink *link;
294
295 link = caja_desktop_icon_file_get_link (CAJA_DESKTOP_ICON_FILE (file)((((CajaDesktopIconFile*) (void *) ((file))))));
296
297 if (link != NULL((void*)0)) {
298 GFile *location;
299
300 /* map to linked URI for these types of links */
301 location = caja_desktop_link_get_activation_location (link);
302
303 if (location) {
304 target_file = caja_file_get (location);
305 g_object_unref (location);
306 }
307
308 g_object_unref (link);
309 }
310 } else {
311 char *uri_to_display;
312
313 uri_to_display = caja_file_get_activation_uri (file);
314
315 if (uri_to_display != NULL((void*)0)) {
316 target_file = caja_file_get_by_uri (uri_to_display);
317 g_free (uri_to_display);
318 }
319 }
320
321 if (target_file != NULL((void*)0)) {
322 return target_file;
323 }
324
325 /* Ref passed-in file here since we've decided to use it. */
326 caja_file_ref (file);
327 return file;
328}
329
330static CajaFile *
331get_target_file (FMPropertiesWindow *window)
332{
333 return CAJA_FILE (window->details->target_files->data)((((CajaFile*) (void *) ((window->details->target_files
->data)))))
;
334}
335
336static void
337add_prompt (GtkWidget *vbox, const char *prompt_text, gboolean pack_at_start)
338{
339 GtkWidget *prompt;
340
341 prompt = gtk_label_new (prompt_text);
342 gtk_label_set_justify (GTK_LABEL (prompt)((((GtkLabel*) (void *) ((prompt))))), GTK_JUSTIFY_LEFT);
343 gtk_label_set_line_wrap (GTK_LABEL (prompt)((((GtkLabel*) (void *) ((prompt))))), TRUE(!(0)));
344 gtk_widget_show (prompt);
345 if (pack_at_start) {
346 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), prompt, FALSE(0), FALSE(0), 0);
347 } else {
348 gtk_box_pack_end (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), prompt, FALSE(0), FALSE(0), 0);
349 }
350}
351
352static void
353add_prompt_and_separator (GtkWidget *vbox, const char *prompt_text)
354{
355 GtkWidget *separator_line;
356
357 add_prompt (vbox, prompt_text, FALSE(0));
358
359 separator_line = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
360
361 gtk_widget_show (separator_line);
362 gtk_box_pack_end (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), separator_line, TRUE(!(0)), TRUE(!(0)), 2*ROW_PAD6);
363}
364
365static void
366get_image_for_properties_window (FMPropertiesWindow *window,
367 char **icon_name,
368 GdkPixbuf **icon_pixbuf)
369{
370 CajaIconInfo *icon, *new_icon;
371 GList *l;
372 gint icon_scale;
373
374 icon = NULL((void*)0);
375 icon_scale = gtk_widget_get_scale_factor (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
);
376
377 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
378 CajaFile *file;
379
380 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
381
382 if (!icon) {
383 icon = caja_file_get_icon (file, CAJA_ICON_SIZE_STANDARD48, icon_scale,
384 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS |
385 CAJA_FILE_ICON_FLAGS_IGNORE_VISITING);
386 } else {
387 new_icon = caja_file_get_icon (file, CAJA_ICON_SIZE_STANDARD48, icon_scale,
388 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS |
389 CAJA_FILE_ICON_FLAGS_IGNORE_VISITING);
390 if (!new_icon || new_icon != icon) {
391 g_object_unref (icon);
392 g_object_unref (new_icon);
393 icon = NULL((void*)0);
394 break;
395 }
396 g_object_unref (new_icon);
397 }
398 }
399
400 if (!icon) {
401 icon = caja_icon_info_lookup_from_name ("text-x-generic",
402 CAJA_ICON_SIZE_STANDARD48,
403 icon_scale);
404 }
405
406 if (icon_name != NULL((void*)0)) {
407 *icon_name = g_strdup (caja_icon_info_get_used_name (icon))g_strdup_inline (caja_icon_info_get_used_name (icon));
408 }
409
410 if (icon_pixbuf != NULL((void*)0)) {
411 *icon_pixbuf = caja_icon_info_get_pixbuf_at_size (icon, CAJA_ICON_SIZE_STANDARD48);
412 }
413
414 g_object_unref (icon);
415}
416
417
418static void
419update_properties_window_icon (FMPropertiesWindow *window)
420{
421 GdkPixbuf *pixbuf;
422 cairo_surface_t *surface;
423 char *name;
424
425 get_image_for_properties_window (window, &name, &pixbuf);
426
427 if (name != NULL((void*)0)) {
428 gtk_window_set_icon_name (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), name);
429 } else {
430 gtk_window_set_icon (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), pixbuf);
431 }
432
433 surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, gtk_widget_get_scale_factor (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))),
434 gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))));
435 gtk_image_set_from_surface (GTK_IMAGE (window->details->icon_image)((((GtkImage*) (void *) ((window->details->icon_image))
)))
, surface);
436
437 g_free (name);
438 g_object_unref (pixbuf);
439 cairo_surface_destroy (surface);
440}
441
442/* utility to test if a uri refers to a local image */
443static gboolean
444uri_is_local_image (const char *uri)
445{
446 GdkPixbuf *pixbuf;
447 char *image_path;
448
449 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
450 if (image_path == NULL((void*)0)) {
451 return FALSE(0);
452 }
453
454 pixbuf = gdk_pixbuf_new_from_file (image_path, NULL((void*)0));
455 g_free (image_path);
456
457 if (pixbuf == NULL((void*)0)) {
458 return FALSE(0);
459 }
460 g_object_unref (pixbuf);
461 return TRUE(!(0));
462}
463
464
465static void
466reset_icon (FMPropertiesWindow *properties_window)
467{
468 GList *l;
469
470 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
471 CajaFile *file;
472
473 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
474
475 caja_file_set_metadata (file,
476 CAJA_METADATA_KEY_ICON_SCALE"icon-scale",
477 NULL((void*)0), NULL((void*)0));
478 caja_file_set_metadata (file,
479 CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon",
480 NULL((void*)0), NULL((void*)0));
481 }
482}
483
484
485static void
486fm_properties_window_drag_data_received (GtkWidget *widget, GdkDragContext *context,
487 int x, int y,
488 GtkSelectionData *selection_data,
489 guint info, guint time)
490{
491 char **uris;
492 gboolean exactly_one;
493 GtkImage *image;
494 GtkWindow *window;
495
496 image = GTK_IMAGE (widget)((((GtkImage*) (void *) ((widget)))));
497 window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (image)))((((GtkWindow*) (void *) ((gtk_widget_get_toplevel (((((GtkWidget
*) (void *) ((image)))))))))))
;
498
499 if (info == TARGET_RESET_BACKGROUND) {
500 reset_icon (FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) ((window))))));
501
502 return;
503 }
504
505 uris = g_strsplit (gtk_selection_data_get_data (selection_data), "\r\n", 0);
506 exactly_one = uris[0] != NULL((void*)0) && (uris[1] == NULL((void*)0) || uris[1][0] == '\0');
507
508
509 if (!exactly_one) {
510 eel_show_error_dialog
511 (_("You cannot assign more than one custom icon at a time!")dcgettext (((void*)0), "You cannot assign more than one custom icon at a time!"
, 5)
,
512 _("Please drag just one image to set a custom icon.")dcgettext (((void*)0), "Please drag just one image to set a custom icon."
, 5)
,
513 window);
514 } else {
515 if (uri_is_local_image (uris[0])) {
516 set_icon (uris[0], FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) ((window))))));
517 } else {
518 GFile *f;
519
520 f = g_file_new_for_uri (uris[0]);
521 if (!g_file_is_native (f)) {
522 eel_show_error_dialog
523 (_("The file that you dropped is not local.")dcgettext (((void*)0), "The file that you dropped is not local."
, 5)
,
524 _("You can only use local images as custom icons.")dcgettext (((void*)0), "You can only use local images as custom icons."
, 5)
,
525 window);
526
527 } else {
528 eel_show_error_dialog
529 (_("The file that you dropped is not an image.")dcgettext (((void*)0), "The file that you dropped is not an image."
, 5)
,
530 _("You can only use local images as custom icons.")dcgettext (((void*)0), "You can only use local images as custom icons."
, 5)
,
531 window);
532 }
533 g_object_unref (f);
534 }
535 }
536 g_strfreev (uris);
537}
538
539static GtkWidget *
540create_image_widget (FMPropertiesWindow *window,
541 gboolean is_customizable)
542{
543 GtkWidget *button;
544 GtkWidget *image;
545
546 image = gtk_image_new ();
547 window->details->icon_image = image;
548
549 update_properties_window_icon (window);
550 gtk_widget_show (image);
551
552 button = NULL((void*)0);
553 if (is_customizable) {
554 button = gtk_button_new ();
555 gtk_container_add (GTK_CONTAINER (button)((((GtkContainer*) (void *) ((button))))), image);
556
557 /* prepare the image to receive dropped objects to assign custom images */
558 gtk_drag_dest_set (GTK_WIDGET (image)((((GtkWidget*) (void *) ((image))))),
559 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
560 target_table, G_N_ELEMENTS (target_table)(sizeof (target_table) / sizeof ((target_table)[0])),
561 GDK_ACTION_COPY | GDK_ACTION_MOVE);
562
563 g_signal_connect (image, "drag_data_received",g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
564 G_CALLBACK (fm_properties_window_drag_data_received), NULL)g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
;
565 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
566 G_CALLBACK (select_image_button_callback), window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
567 }
568
569 window->details->icon_button = button;
570
571 return button != NULL((void*)0) ? button : image;
572}
573
574static void
575set_name_field (FMPropertiesWindow *window,
576 const gchar *original_name,
577 const gchar *name)
578{
579 gboolean new_widget;
580 gboolean use_label;
581
582 /* There are four cases here:
583 * 1) Changing the text of a label
584 * 2) Changing the text of an entry
585 * 3) Creating label (potentially replacing entry)
586 * 4) Creating entry (potentially replacing label)
587 */
588 use_label = is_multi_file_window (window) || !caja_file_can_rename (get_original_file (window));
589 new_widget = !window->details->name_field || (use_label ? CAJA_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (caja_entry_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; }))))
: GTK_IS_LABEL (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = ((gtk_label_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; }))))
);
590
591 if (new_widget) {
592 if (window->details->name_field) {
593 gtk_widget_destroy (window->details->name_field);
594 }
595
596 if (use_label) {
597 window->details->name_field = GTK_WIDGET((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
598 (attach_ellipsizing_value_label (window->details->basic_grid,((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
599 GTK_WIDGET (window->details->name_label),((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
600 name))((((GtkWidget*) (void *) ((attach_ellipsizing_value_label (window
->details->basic_grid, ((((GtkWidget*) (void *) ((window
->details->name_label))))), name))))))
;
601
602 } else {
603 window->details->name_field = caja_entry_new ();
604 gtk_entry_set_text (GTK_ENTRY (window->details->name_field)((((GtkEntry*) (void *) ((window->details->name_field))
)))
, name);
605 gtk_widget_show (window->details->name_field);
606 gtk_grid_attach_next_to (window->details->basic_grid, window->details->name_field,
607 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
,
608 GTK_POS_RIGHT, 1, 1);
609
610 gtk_label_set_mnemonic_widget (GTK_LABEL (window->details->name_label)((((GtkLabel*) (void *) ((window->details->name_label))
)))
, window->details->name_field);
611
612 g_signal_connect_object (window->details->name_field, "focus_out_event",
613 G_CALLBACK (name_field_focus_out)((GCallback) (name_field_focus_out)), window, 0);
614 g_signal_connect_object (window->details->name_field, "activate",
615 G_CALLBACK (name_field_activate)((GCallback) (name_field_activate)), window, 0);
616 }
617
618 gtk_widget_show (window->details->name_field);
619 }
620 /* Only replace text if the file's name has changed. */
621 else if (original_name == NULL((void*)0) || strcmp (original_name, name) != 0) {
622
623 if (use_label) {
624 gtk_label_set_text (GTK_LABEL (window->details->name_field)((((GtkLabel*) (void *) ((window->details->name_field))
)))
, name);
625 } else {
626 /* Only reset the text if it's different from what is
627 * currently showing. This causes minimal ripples (e.g.
628 * selection change).
629 */
630 gchar *displayed_name = gtk_editable_get_chars (GTK_EDITABLE (window->details->name_field)((((GtkEditable*) (void *) ((window->details->name_field
)))))
, 0, -1);
631 if (strcmp (displayed_name, name) != 0) {
632 gtk_entry_set_text (GTK_ENTRY (window->details->name_field)((((GtkEntry*) (void *) ((window->details->name_field))
)))
, name);
633 }
634 g_free (displayed_name);
635 }
636 }
637}
638
639static void
640update_name_field (FMPropertiesWindow *window)
641{
642 CajaFile *file;
643
644 gtk_label_set_text_with_mnemonic (window->details->name_label,
645 ngettext ("_Name:", "_Names:",dcngettext (((void*)0), "_Name:", "_Names:", get_not_gone_original_file_count
(window), 5)
646 get_not_gone_original_file_count (window))dcngettext (((void*)0), "_Name:", "_Names:", get_not_gone_original_file_count
(window), 5)
);
647
648 if (is_multi_file_window (window)) {
649 /* Multifile property dialog, show all names */
650 GString *str;
651 char *name;
652 gboolean first;
653 GList *l;
654
655 str = g_string_new ("");
656
657 first = TRUE(!(0));
658
659 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
660 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
661
662 if (!caja_file_is_gone (file)) {
663 if (!first) {
664 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_102; if (__val != ((void
*)0)) _g_boolean_var_102 = 1; else _g_boolean_var_102 = 0; _g_boolean_var_102
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
665 }
666 first = FALSE(0);
667
668 name = caja_file_get_display_name (file);
669 g_string_append (str, name)(__builtin_constant_p (name) ? __extension__ ({ const char * const
__val = (name); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_103; if (__val != ((void
*)0)) _g_boolean_var_103 = 1; else _g_boolean_var_103 = 0; _g_boolean_var_103
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, name, (gssize) -1
))
;
670 g_free (name);
671 }
672 }
673 set_name_field (window, NULL((void*)0), str->str);
674 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
675 } else {
676 const char *original_name = NULL((void*)0);
677 char *current_name;
678
679 file = get_original_file (window);
680
681 if (file == NULL((void*)0) || caja_file_is_gone (file)) {
682 current_name = g_strdup ("")g_strdup_inline ("");
683 } else {
684 current_name = caja_file_get_display_name (file);
685 }
686
687 /* If the file name has changed since the original name was stored,
688 * update the text in the text field, possibly (deliberately) clobbering
689 * an edit in progress. If the name hasn't changed (but some other
690 * aspect of the file might have), then don't clobber changes.
691 */
692 if (window->details->name_field) {
693 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
, "original_name");
694 }
695
696 set_name_field (window, original_name, current_name);
697
698 if (original_name == NULL((void*)0) ||
699 g_strcmp0 (original_name, current_name) != 0) {
700 g_object_set_data_full (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
,
701 "original_name",
702 current_name,
703 g_free);
704 } else {
705 g_free (current_name);
706 }
707 }
708}
709
710static void
711name_field_restore_original_name (CajaEntry *name_field)
712{
713 const char *original_name;
714 char *displayed_name;
715
716 original_name = (const char *) g_object_get_data (G_OBJECT (name_field)((((GObject*) (void *) ((name_field))))),
717 "original_name");
718
719 if (!original_name) {
720 return;
721 }
722
723 displayed_name = gtk_editable_get_chars (GTK_EDITABLE (name_field)((((GtkEditable*) (void *) ((name_field))))), 0, -1);
724
725 if (strcmp (original_name, displayed_name) != 0) {
726 gtk_entry_set_text (GTK_ENTRY (name_field)((((GtkEntry*) (void *) ((name_field))))), original_name);
727 }
728 caja_entry_select_all (name_field);
729
730 g_free (displayed_name);
731}
732
733static void
734rename_callback (CajaFile *file, GFile *res_loc, GError *error, gpointer callback_data)
735{
736 FMPropertiesWindow *window;
737
738 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
739
740 /* Complain to user if rename failed. */
741 if (error != NULL((void*)0)) {
742 fm_report_error_renaming_file (file,
743 window->details->pending_name,
744 error,
745 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
746 if (window->details->name_field != NULL((void*)0)) {
747 name_field_restore_original_name (CAJA_ENTRY (window->details->name_field)((((CajaEntry*) (void *) ((window->details->name_field)
))))
);
748 }
749 }
750
751 g_object_unref (window);
752}
753
754static void
755set_pending_name (FMPropertiesWindow *window, const char *name)
756{
757 g_free (window->details->pending_name);
758 window->details->pending_name = g_strdup (name)g_strdup_inline (name);
759}
760
761static void
762name_field_done_editing (CajaEntry *name_field, FMPropertiesWindow *window)
763{
764 CajaFile *file;
765 char *new_name;
766
767 g_return_if_fail (CAJA_IS_ENTRY (name_field))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (caja_entry_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__)), "CAJA_IS_ENTRY (name_field)"); return; }
} while (0)
;
768
769 /* Don't apply if the dialog has more than one file */
770 if (is_multi_file_window (window)) {
771 return;
772 }
773
774 file = get_original_file (window);
775
776 /* This gets called when the window is closed, which might be
777 * caused by the file having been deleted.
778 */
779 if (file == NULL((void*)0) || caja_file_is_gone (file)) {
780 return;
781 }
782
783 new_name = gtk_editable_get_chars (GTK_EDITABLE (name_field)((((GtkEditable*) (void *) ((name_field))))), 0, -1);
784
785 /* Special case: silently revert text if new text is empty. */
786 if (strlen (new_name) == 0) {
787 name_field_restore_original_name (CAJA_ENTRY (name_field)((((CajaEntry*) (void *) ((name_field))))));
788 } else {
789 const char *original_name;
790
791 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) ((window->details->name_field)))
))
,
792 "original_name");
793 /* Don't rename if not changed since we read the display name.
794 This is needed so that we don't save the display name to the
795 file when nothing is changed */
796 if (strcmp (new_name, original_name) != 0) {
797 set_pending_name (window, new_name);
798 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
799 caja_file_rename (file, new_name,
800 rename_callback, window);
801 }
802 }
803
804 g_free (new_name);
805}
806
807static gboolean
808name_field_focus_out (CajaEntry *name_field,
809 GdkEventFocus *event,
810 gpointer callback_data)
811{
812 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_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_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 812, ((const char*)
(__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"); } while
(0)
;
813
814 if (gtk_widget_get_sensitive (GTK_WIDGET (name_field)((((GtkWidget*) (void *) ((name_field))))))) {
815 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data))))));
816 }
817
818 return FALSE(0);
819}
820
821static void
822name_field_activate (CajaEntry *name_field, gpointer callback_data)
823{
824 g_assert (CAJA_IS_ENTRY (name_field))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (caja_entry_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 824, ((const char*) (__func__)), "CAJA_IS_ENTRY (name_field)"
); } while (0)
;
825 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_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_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 825, ((const char*)
(__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"); } while
(0)
;
826
827 /* Accept changes. */
828 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data))))));
829
830 caja_entry_select_all_at_idle (name_field);
831}
832
833static gboolean
834file_has_keyword (CajaFile *file, const char *keyword)
835{
836 GList *keywords, *word;
837
838 keywords = caja_file_get_keywords (file);
839 word = g_list_find_custom (keywords, keyword, (GCompareFunc) strcmp);
840 g_list_free_full (keywords, g_free);
841
842 return (word != NULL((void*)0));
843}
844
845static void
846get_initial_emblem_state (FMPropertiesWindow *window,
847 const char *name,
848 GList **on,
849 GList **off)
850{
851 GList *l;
852
853 *on = NULL((void*)0);
854 *off = NULL((void*)0);
855
856 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
857 GList *initial_emblems;
858
859 initial_emblems = g_hash_table_lookup (window->details->initial_emblems,
860 l->data);
861
862 if (g_list_find_custom (initial_emblems, name, (GCompareFunc) strcmp)) {
863 *on = g_list_prepend (*on, l->data);
864 } else {
865 *off = g_list_prepend (*off, l->data);
866 }
867 }
868}
869
870static void
871emblem_button_toggled (GtkToggleButton *button,
872 FMPropertiesWindow *window)
873{
874 GList *l;
875 GList *keywords;
876 GList *word;
877 char *name;
878 GList *files_on;
879 GList *files_off;
880
881 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name");
882
883 files_on = NULL((void*)0);
884 files_off = NULL((void*)0);
885 if (gtk_toggle_button_get_active (button)
886 && !gtk_toggle_button_get_inconsistent (button)) {
887 /* Go to the initial state unless the initial state was
888 consistent */
889 get_initial_emblem_state (window, name,
890 &files_on, &files_off);
891
892 if (!(files_on && files_off)) {
893 g_list_free (files_on);
894 g_list_free (files_off);
895 files_on = g_list_copy (window->details->original_files);
896 files_off = NULL((void*)0);
897 }
898 } else if (gtk_toggle_button_get_inconsistent (button)
899 && !gtk_toggle_button_get_active (button)) {
900 files_on = g_list_copy (window->details->original_files);
901 files_off = NULL((void*)0);
902 } else {
903 files_off = g_list_copy (window->details->original_files);
904 files_on = NULL((void*)0);
905 }
906
907 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
908 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
909 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
910
911 gtk_toggle_button_set_active (button, files_on != NULL((void*)0));
912 gtk_toggle_button_set_inconsistent (button, files_on && files_off);
913
914 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
915 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
916 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
917
918 for (l = files_on; l != NULL((void*)0); l = l->next) {
919 CajaFile *file;
920
921 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
922
923 keywords = caja_file_get_keywords (file);
924
925 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
926 if (!word) {
927 keywords = g_list_prepend (keywords, g_strdup (name)g_strdup_inline (name));
928 }
929 caja_file_set_keywords (file, keywords);
930 g_list_free_full (keywords, g_free);
931 }
932
933 for (l = files_off; l != NULL((void*)0); l = l->next) {
934 CajaFile *file;
935
936 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
937
938 keywords = caja_file_get_keywords (file);
939
940 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
941 if (word) {
942 keywords = g_list_remove_link (keywords, word);
943 g_list_free_full (word, g_free);
944 }
945 caja_file_set_keywords (file, keywords);
946 g_list_free_full (keywords, g_free);
947 }
948
949 g_list_free (files_on);
950 g_list_free (files_off);
951}
952
953static void
954emblem_button_update (FMPropertiesWindow *window,
955 GtkToggleButton *button)
956{
957 GList *l;
958 char *name;
959 gboolean all_set;
960 gboolean all_unset;
961
962 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name");
963
964 all_set = TRUE(!(0));
965 all_unset = TRUE(!(0));
966 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
967 gboolean has_keyword;
968 CajaFile *file;
969
970 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
971
972 has_keyword = file_has_keyword (file, name);
973
974 if (has_keyword) {
975 all_unset = FALSE(0);
976 } else {
977 all_set = FALSE(0);
978 }
979 }
980
981 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
982 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
983 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
984
985 gtk_toggle_button_set_active (button, !all_unset);
986 gtk_toggle_button_set_inconsistent (button, !all_unset && !all_set);
987
988 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
989 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
990 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
991
992}
993
994static void
995update_properties_window_title (FMPropertiesWindow *window)
996{
997 char *title;
998
999 g_return_if_fail (GTK_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((gtk_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__)), "GTK_IS_WINDOW (window)"); return; } } while
(0)
;
1000
1001 title = g_strdup_printf (_("Properties")dcgettext (((void*)0), "Properties", 5));
1002
1003 if (!is_multi_file_window (window)) {
1004 CajaFile *file;
1005
1006 file = get_original_file (window);
1007
1008 if (file != NULL((void*)0)) {
1009 char *name;
1010
1011 g_free (title);
1012 name = caja_file_get_display_name (file);
1013 title = g_strdup_printf (_("%s Properties")dcgettext (((void*)0), "%s Properties", 5), name);
1014 g_free (name);
1015 }
1016 }
1017
1018 gtk_window_set_title (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), title);
1019
1020 g_free (title);
1021}
1022
1023static void
1024clear_extension_pages (FMPropertiesWindow *window)
1025{
1026 int i;
1027 int num_pages;
1028 GtkWidget *page = NULL((void*)0);
1029
1030 num_pages = gtk_notebook_get_n_pages
1031 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
);
1032
1033 for (i = 0; i < num_pages; i++) {
1034 page = gtk_notebook_get_nth_page
1035 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
, i);
1036
1037 if (g_object_get_data (G_OBJECT (page)((((GObject*) (void *) ((page))))), "is-extension-page")) {
1038 gtk_notebook_remove_page
1039 (GTK_NOTEBOOK (window->details->notebook)((((GtkNotebook*) (void *) ((window->details->notebook)
))))
, i);
1040 num_pages--;
1041 i--;
1042 }
1043 }
1044}
1045
1046static void
1047refresh_extension_pages (FMPropertiesWindow *window)
1048{
1049 clear_extension_pages (window);
1050 append_extension_pages (window);
1051}
1052
1053static void
1054remove_from_dialog (FMPropertiesWindow *window,
1055 CajaFile *file)
1056{
1057 int index;
1058 GList *original_link;
1059 GList *target_link;
1060 CajaFile *original_file;
1061 CajaFile *target_file;
1062
1063 index = g_list_index (window->details->target_files, file);
1064 if (index == -1) {
1065 index = g_list_index (window->details->original_files, file);
1066 g_return_if_fail (index != -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if (index != -1) _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__)), "index != -1"); return
; } } while (0)
;
1067 }
1068
1069 original_link = g_list_nth (window->details->original_files, index);
1070 target_link = g_list_nth (window->details->target_files, index);
1071
1072 g_return_if_fail (original_link && target_link)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if (original_link && target_link) _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__)), "original_link && target_link");
return; } } while (0)
;
1073
1074 original_file = CAJA_FILE (original_link->data)((((CajaFile*) (void *) ((original_link->data)))));
1075 target_file = CAJA_FILE (target_link->data)((((CajaFile*) (void *) ((target_link->data)))));
1076
1077 window->details->original_files = g_list_remove_link (window->details->original_files, original_link);
1078 g_list_free (original_link);
1079
1080 window->details->target_files = g_list_remove_link (window->details->target_files, target_link);
1081 g_list_free (target_link);
1082
1083 g_hash_table_remove (window->details->initial_emblems, original_file);
1084 g_hash_table_remove (window->details->initial_permissions, target_file);
1085
1086 g_signal_handlers_disconnect_by_func (original_file,g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1087 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1088 window)g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1089 g_signal_handlers_disconnect_by_func (target_file,g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1090 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1091 window)g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1092
1093 caja_file_monitor_remove (original_file, &window->details->original_files);
1094 caja_file_monitor_remove (target_file, &window->details->target_files);
1095
1096 caja_file_unref (original_file);
1097 caja_file_unref (target_file);
1098
1099}
1100
1101static gboolean
1102mime_list_equal (GList *a, GList *b)
1103{
1104 while (a && b) {
1105 if (strcmp (a->data, b->data)) {
1106 return FALSE(0);
1107 }
1108 a = a->next;
1109 b = b->next;
1110 }
1111
1112 return (a == b);
1113}
1114
1115static GList *
1116get_mime_list (FMPropertiesWindow *window)
1117{
1118 GList *ret;
1119 GList *l;
1120
1121 ret = NULL((void*)0);
1122 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
1123 ret = g_list_append (ret, caja_file_get_mime_type (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))))));
1124 }
1125 ret = g_list_reverse (ret);
1126 return ret;
1127}
1128
1129static void
1130properties_window_update (FMPropertiesWindow *window,
1131 GList *files)
1132{
1133 GList *l;
1134 GList *mime_list;
1135 GList *tmp;
1136 CajaFile *changed_file = NULL((void*)0);
1137 gboolean dirty_original = FALSE(0);
1138 gboolean dirty_target = FALSE(0);
1139
1140 if (files == NULL((void*)0)) {
1141 dirty_original = TRUE(!(0));
1142 dirty_target = TRUE(!(0));
1143 }
1144
1145 for (tmp = files; tmp != NULL((void*)0); tmp = tmp->next) {
1146 changed_file = CAJA_FILE (tmp->data)((((CajaFile*) (void *) ((tmp->data)))));
1147
1148 if (changed_file && caja_file_is_gone (changed_file)) {
1149 /* Remove the file from the property dialog */
1150 remove_from_dialog (window, changed_file);
1151 changed_file = NULL((void*)0);
1152
1153 if (window->details->original_files == NULL((void*)0)) {
1154 return;
1155 }
1156 }
1157 if (changed_file == NULL((void*)0) ||
1158 g_list_find (window->details->original_files, changed_file)) {
1159 dirty_original = TRUE(!(0));
1160 }
1161 if (changed_file == NULL((void*)0) ||
1162 g_list_find (window->details->target_files, changed_file)) {
1163 dirty_target = TRUE(!(0));
1164 }
1165
1166 }
1167
1168 if (dirty_original) {
1169 update_properties_window_title (window);
1170 update_properties_window_icon (window);
1171 update_name_field (window);
1172
1173 for (l = window->details->emblem_buttons; l != NULL((void*)0); l = l->next) {
1174 emblem_button_update (window, GTK_TOGGLE_BUTTON (l->data)((((GtkToggleButton*) (void *) ((l->data))))));
1175 }
1176
1177 /* If any of the value fields start to depend on the original
1178 * value, value_field_updates should be added here */
1179 }
1180
1181 if (dirty_target) {
1182 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
1183 permission_button_update (window, GTK_TOGGLE_BUTTON (l->data)((((GtkToggleButton*) (void *) ((l->data))))));
1184 }
1185
1186 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
1187 permission_combo_update (window, GTK_COMBO_BOX (l->data)((((GtkComboBox*) (void *) ((l->data))))));
1188 }
1189
1190 for (l = window->details->value_fields; l != NULL((void*)0); l = l->next) {
1191 value_field_update (window, GTK_LABEL (l->data)((((GtkLabel*) (void *) ((l->data))))));
1192 }
1193 }
1194
1195 mime_list = get_mime_list (window);
1196
1197 if (!window->details->mime_list) {
1198 window->details->mime_list = mime_list;
1199 } else {
1200 if (!mime_list_equal (window->details->mime_list, mime_list)) {
1201 refresh_extension_pages (window);
1202 }
1203
1204 g_list_free_full (window->details->mime_list, g_free);
1205 window->details->mime_list = mime_list;
1206 }
1207}
1208
1209static gboolean
1210update_files_callback (gpointer data)
1211{
1212 FMPropertiesWindow *window;
1213
1214 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
1215
1216 window->details->update_files_timeout_id = 0;
1217
1218 properties_window_update (window, window->details->changed_files);
1219
1220 if (window->details->original_files == NULL((void*)0)) {
1221 /* Close the window if no files are left */
1222 gtk_widget_destroy (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
1223 } else {
1224 caja_file_list_free (window->details->changed_files);
1225 window->details->changed_files = NULL((void*)0);
1226 }
1227
1228 return FALSE(0);
1229 }
1230
1231static void
1232schedule_files_update (FMPropertiesWindow *window)
1233 {
1234 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1234, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1235
1236 if (window->details->update_files_timeout_id == 0) {
1237 window->details->update_files_timeout_id
1238 = g_timeout_add (FILES_UPDATE_INTERVAL200,
1239 update_files_callback,
1240 window);
1241 }
1242 }
1243
1244static gboolean
1245file_list_attributes_identical (GList *file_list, const char *attribute_name)
1246{
1247 gboolean identical;
1248 char *first_attr;
1249 GList *l;
1250
1251 first_attr = NULL((void*)0);
1252 identical = TRUE(!(0));
1253
1254 for (l = file_list; l != NULL((void*)0); l = l->next) {
1255 CajaFile *file;
1256
1257 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1258
1259 if (caja_file_is_gone (file)) {
1260 continue;
1261 }
1262
1263 if (first_attr == NULL((void*)0)) {
1264 first_attr = caja_file_get_string_attribute_with_default (file, attribute_name);
1265 } else {
1266 char *attr;
1267 attr = caja_file_get_string_attribute_with_default (file, attribute_name);
1268 if (strcmp (attr, first_attr)) {
1269 identical = FALSE(0);
1270 g_free (attr);
1271 break;
1272 }
1273 g_free (attr);
1274 }
1275 }
1276
1277 g_free (first_attr);
1278 return identical;
1279}
1280
1281static char *
1282file_list_get_string_attribute (GList *file_list,
1283 const char *attribute_name,
1284 const char *inconsistent_value)
1285{
1286 if (file_list_attributes_identical (file_list, attribute_name)) {
1287 GList *l;
1288
1289 for (l = file_list; l != NULL((void*)0); l = l->next) {
1290 CajaFile *file;
1291
1292 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
1293 if (!caja_file_is_gone (file)) {
1294 return caja_file_get_string_attribute_with_default
1295 (file,
1296 attribute_name);
1297 }
1298 }
1299 return g_strdup (_("unknown"))g_strdup_inline (dcgettext (((void*)0), "unknown", 5));
1300 } else {
1301 return g_strdup (inconsistent_value)g_strdup_inline (inconsistent_value);
1302 }
1303}
1304
1305
1306static gboolean
1307file_list_all_directories (GList *file_list)
1308{
1309 GList *l;
1310 for (l = file_list; l != NULL((void*)0); l = l->next) {
1311 if (!caja_file_is_directory (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))))) {
1312 return FALSE(0);
1313 }
1314 }
1315 return TRUE(!(0));
1316}
1317
1318static void
1319value_field_update_internal (GtkLabel *label,
1320 GList *file_list)
1321{
1322 const char *attribute_name;
1323 char *attribute_value;
1324 char *inconsistent_string;
1325
1326 g_assert (GTK_IS_LABEL (label))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((gtk_label_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1326, ((const char*) (__func__)), "GTK_IS_LABEL (label)"); }
while (0)
;
1327
1328 attribute_name = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) ((label))))), "file_attribute");
1329 inconsistent_string = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) ((label))))), "inconsistent_string");
1330 attribute_value = file_list_get_string_attribute (file_list,
1331 attribute_name,
1332 inconsistent_string);
1333 if (!strcmp (attribute_name, "type") && strcmp (attribute_value, inconsistent_string)) {
1334 char *mime_type;
1335
1336 mime_type = file_list_get_string_attribute (file_list,
1337 "mime_type",
1338 inconsistent_string);
1339 if (strcmp (mime_type, inconsistent_string)) {
1340 char *tmp;
1341
1342 tmp = attribute_value;
1343 attribute_value = g_strdup_printf (C_("MIME type description (MIME type)", "%s (%s)")g_dpgettext (((void*)0), "MIME type description (MIME type)" "\004"
"%s (%s)", strlen ("MIME type description (MIME type)") + 1)
, attribute_value, mime_type);
1344 g_free (tmp);
1345 }
1346 g_free (mime_type);
1347 }
1348
1349 gtk_label_set_text (label, attribute_value);
1350 g_free (attribute_value);
1351}
1352
1353static void
1354value_field_update (FMPropertiesWindow *window, GtkLabel *label)
1355{
1356 gboolean use_original;
1357
1358 use_original = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), "show_original"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
label))))), "show_original")))
;
1359
1360 value_field_update_internal (label,
1361 (use_original ?
1362 window->details->original_files :
1363 window->details->target_files));
1364}
1365
1366static GtkLabel *
1367attach_label (GtkGrid *grid,
1368 GtkWidget *sibling,
1369 const char *initial_text,
1370 gboolean ellipsize_text,
1371 gboolean selectable,
1372 gboolean mnemonic)
1373{
1374 GtkWidget *label_field;
1375
1376 if (ellipsize_text) {
1377 label_field = gtk_label_new (initial_text);
1378 gtk_label_set_ellipsize (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))),
1379 PANGO_ELLIPSIZE_END);
1380 } else if (mnemonic) {
1381 label_field = gtk_label_new_with_mnemonic (initial_text);
1382 } else {
1383 label_field = gtk_label_new (initial_text);
1384 }
1385
1386 if (selectable) {
1387 gtk_label_set_selectable (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), TRUE(!(0)));
1388 }
1389
1390 gtk_label_set_xalign (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), 0);
1391 gtk_widget_show (label_field);
1392 if (ellipsize_text) {
1393 gtk_widget_set_hexpand (label_field, TRUE(!(0)));
1394 gtk_label_set_max_width_chars (GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field))))), 24);
1395 }
1396
1397 if (sibling != NULL((void*)0)) {
1398 gtk_grid_attach_next_to (grid, label_field, sibling,
1399 GTK_POS_RIGHT, 1, 1);
1400 } else {
1401 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), label_field);
1402 }
1403
1404 return GTK_LABEL (label_field)((((GtkLabel*) (void *) ((label_field)))));
1405}
1406
1407static GtkLabel *
1408attach_value_label (GtkGrid *grid,
1409 GtkWidget *sibling,
1410 const char *initial_text)
1411{
1412 return attach_label (grid, sibling, initial_text, FALSE(0), TRUE(!(0)), FALSE(0));
1413}
1414
1415static GtkLabel *
1416attach_ellipsizing_value_label (GtkGrid *grid,
1417 GtkWidget *sibling,
1418 const char *initial_text)
1419{
1420 return attach_label (grid, sibling, initial_text, TRUE(!(0)), TRUE(!(0)), FALSE(0));
1421}
1422
1423static GtkWidget*
1424attach_value_field_internal (FMPropertiesWindow *window,
1425 GtkGrid *grid,
1426 GtkWidget *sibling,
1427 const char *file_attribute_name,
1428 const char *inconsistent_string,
1429 gboolean show_original,
1430 gboolean ellipsize_text)
1431{
1432 GtkLabel *value_field;
1433
1434 if (ellipsize_text) {
1435 value_field = attach_ellipsizing_value_label (grid, sibling, "");
1436 } else {
1437 value_field = attach_value_label (grid, sibling, "");
1438 }
1439
1440 /* Stash a copy of the file attribute name in this field for the callback's sake. */
1441 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "file_attribute",
1442 g_strdup (file_attribute_name)g_strdup_inline (file_attribute_name), g_free);
1443
1444 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "inconsistent_string",
1445 g_strdup (inconsistent_string)g_strdup_inline (inconsistent_string), g_free);
1446
1447 g_object_set_data (G_OBJECT (value_field)((((GObject*) (void *) ((value_field))))), "show_original", GINT_TO_POINTER (show_original)((gpointer) (glong) (show_original)));
1448
1449 window->details->value_fields = g_list_prepend (window->details->value_fields,
1450 value_field);
1451 return GTK_WIDGET(value_field)((((GtkWidget*) (void *) ((value_field)))));
1452}
1453
1454static GtkWidget*
1455attach_value_field (FMPropertiesWindow *window,
1456 GtkGrid *grid,
1457 GtkWidget *sibling,
1458 const char *file_attribute_name,
1459 const char *inconsistent_string,
1460 gboolean show_original)
1461{
1462 return attach_value_field_internal (window,
1463 grid, sibling,
1464 file_attribute_name,
1465 inconsistent_string,
1466 show_original,
1467 FALSE(0));
1468}
1469
1470static GtkWidget*
1471attach_ellipsizing_value_field (FMPropertiesWindow *window,
1472 GtkGrid *grid,
1473 GtkWidget *sibling,
1474 const char *file_attribute_name,
1475 const char *inconsistent_string,
1476 gboolean show_original)
1477{
1478 return attach_value_field_internal (window,
1479 grid, sibling,
1480 file_attribute_name,
1481 inconsistent_string,
1482 show_original,
1483 TRUE(!(0)));
1484}
1485
1486static void
1487group_change_callback (CajaFile *file,
1488 GFile *res_loc,
1489 GError *error,
1490 FMPropertiesWindow *window)
1491{
1492 char *group;
1493
1494 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1494, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1495 g_assert (window->details->group_change_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if (window->details->group_change_file == file) _g_boolean_var_114
= 1; else _g_boolean_var_114 = 0; _g_boolean_var_114; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1495, ((const char*) (__func__)), "window->details->group_change_file == file"
); } while (0)
;
1496
1497 group = window->details->group_change_group;
1498 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if (group != ((void*)0)) _g_boolean_var_115 = 1; else _g_boolean_var_115
= 0; _g_boolean_var_115; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1498, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1499
1500 /* Report the error if it's an error. */
1501 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1502 fm_report_error_setting_group (file, error, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1503
1504 caja_file_unref (file);
1505 g_free (group);
1506
1507 window->details->group_change_file = NULL((void*)0);
1508 window->details->group_change_group = NULL((void*)0);
1509 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1510}
1511
1512static void
1513cancel_group_change_callback (FMPropertiesWindow *window)
1514{
1515 CajaFile *file;
1516 char *group;
1517
1518 file = window->details->group_change_file;
1519 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_116
= 1; else _g_boolean_var_116 = 0; _g_boolean_var_116; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1519, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1520
1521 group = window->details->group_change_group;
1522 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if (group != ((void*)0)) _g_boolean_var_117 = 1; else _g_boolean_var_117
= 0; _g_boolean_var_117; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1522, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1523
1524 caja_file_cancel (file, (CajaFileOperationCallback) group_change_callback, window);
1525
1526 g_free (group);
1527 caja_file_unref (file);
1528
1529 window->details->group_change_file = NULL((void*)0);
1530 window->details->group_change_group = NULL((void*)0);
1531 g_object_unref (window);
1532}
1533
1534static gboolean
1535schedule_group_change_timeout (FMPropertiesWindow *window)
1536{
1537 CajaFile *file;
1538 char *group;
1539
1540 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1540, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1541
1542 file = window->details->group_change_file;
1543 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_119
= 1; else _g_boolean_var_119 = 0; _g_boolean_var_119; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1543, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1544
1545 group = window->details->group_change_group;
1546 g_assert (group != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (group != ((void*)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120
= 0; _g_boolean_var_120; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1546, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1547
1548 eel_timed_wait_start
1549 ((EelCancelCallback) cancel_group_change_callback,
1550 window,
1551 _("Cancel Group Change?")dcgettext (((void*)0), "Cancel Group Change?", 5),
1552 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1553
1554 caja_file_set_group
1555 (file, group,
1556 (CajaFileOperationCallback) group_change_callback, window);
1557
1558 window->details->group_change_timeout = 0;
1559 return FALSE(0);
1560}
1561
1562static void
1563schedule_group_change (FMPropertiesWindow *window,
1564 CajaFile *file,
1565 const char *group)
1566{
1567 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1567, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1568 g_assert (window->details->group_change_group == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if (window->details->group_change_group == ((void*)0)
) _g_boolean_var_122 = 1; else _g_boolean_var_122 = 0; _g_boolean_var_122
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1568, ((const char*) (__func__)), "window->details->group_change_group == NULL"
); } while (0)
;
1569 g_assert (window->details->group_change_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if (window->details->group_change_file == ((void*)0))
_g_boolean_var_123 = 1; else _g_boolean_var_123 = 0; _g_boolean_var_123
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1569, ((const char*) (__func__)), "window->details->group_change_file == NULL"
); } while (0)
;
1570 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_124
= 1; else _g_boolean_var_124 = 0; _g_boolean_var_124; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1570, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1571
1572 window->details->group_change_file = caja_file_ref (file);
1573 window->details->group_change_group = g_strdup (group)g_strdup_inline (group);
1574 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) ((window))))))) (g_object_ref
) (((((GObject*) (void *) ((window)))))))
;
1575 window->details->group_change_timeout =
1576 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1577 (GSourceFunc) schedule_group_change_timeout,
1578 window);
1579}
1580
1581static void
1582unschedule_or_cancel_group_change (FMPropertiesWindow *window)
1583{
1584 CajaFile *file;
1585 char *group;
1586
1587 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_125 = 1; else _g_boolean_var_125 = 0; _g_boolean_var_125
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1587, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1588
1589 file = window->details->group_change_file;
1590 group = window->details->group_change_group;
1591
1592 g_assert ((file == NULL && group == NULL) ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if ((file == ((void*)0) && group == ((void*)0)) || (
file != ((void*)0) && group != ((void*)0))) _g_boolean_var_126
= 1; else _g_boolean_var_126 = 0; _g_boolean_var_126; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1593, ((const char*) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
1593 (file != NULL && group != NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if ((file == ((void*)0) && group == ((void*)0)) || (
file != ((void*)0) && group != ((void*)0))) _g_boolean_var_126
= 1; else _g_boolean_var_126 = 0; _g_boolean_var_126; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1593, ((const char*) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
;
1594
1595 if (file != NULL((void*)0)) {
1596 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_127
= 1; else _g_boolean_var_127 = 0; _g_boolean_var_127; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1596, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1597
1598 if (window->details->group_change_timeout == 0) {
1599 caja_file_cancel (file,
1600 (CajaFileOperationCallback) group_change_callback, window);
1601 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1602 }
1603
1604 caja_file_unref (file);
1605 g_free (group);
1606
1607 window->details->group_change_file = NULL((void*)0);
1608 window->details->group_change_group = NULL((void*)0);
1609 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1610 }
1611
1612 if (window->details->group_change_timeout > 0) {
1613 g_assert (file != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (file != ((void*)0)) _g_boolean_var_128 = 1; else _g_boolean_var_128
= 0; _g_boolean_var_128; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1613, ((const char*
) (__func__)), "file != NULL"); } while (0)
;
1614 g_source_remove (window->details->group_change_timeout);
1615 window->details->group_change_timeout = 0;
1616 }
1617}
1618
1619static void
1620changed_group_callback (GtkComboBox *combo_box, CajaFile *file)
1621{
1622 char *group;
1623 char *cur_group;
1624
1625 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_129
= 1; else _g_boolean_var_129 = 0; _g_boolean_var_129; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1625, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1626 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_130
= 1; else _g_boolean_var_130 = 0; _g_boolean_var_130; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1626, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1627
1628 group = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))));
1629 cur_group = caja_file_get_group_name (file);
1630
1631 if (group != NULL((void*)0) && strcmp (group, cur_group) != 0) {
1632 FMPropertiesWindow *window;
1633
1634 /* Try to change file group. If this fails, complain to user. */
1635 window = FM_PROPERTIES_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (combo_box), GTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) ((gtk_widget_get_ancestor (
((((GtkWidget*) (void *) ((combo_box))))), (gtk_window_get_type
())))))))
;
1636
1637 unschedule_or_cancel_group_change (window);
1638 schedule_group_change (window, file, group);
1639 }
1640 g_free (group);
1641 g_free (cur_group);
1642}
1643
1644/* checks whether the given column at the first level
1645 * of model has the specified entries in the given order. */
1646static gboolean
1647tree_model_entries_equal (GtkTreeModel *model,
1648 unsigned int column,
1649 GList *entries)
1650{
1651 GtkTreeIter iter;
1652 gboolean empty_model;
1653
1654 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_131
= 1; else _g_boolean_var_131 = 0; _g_boolean_var_131; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1654, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1655 g_assert (gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if (gtk_tree_model_get_column_type (model, column) == ((GType
) ((16) << (2)))) _g_boolean_var_132 = 1; else _g_boolean_var_132
= 0; _g_boolean_var_132; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1655, ((const char*
) (__func__)), "gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1656
1657 empty_model = !gtk_tree_model_get_iter_first (model, &iter);
1658
1659 if (!empty_model && entries != NULL((void*)0)) {
1660 GList *l;
1661
1662 l = entries;
1663
1664 do {
1665 char *val;
1666
1667 gtk_tree_model_get (model, &iter,
1668 column, &val,
1669 -1);
1670 if ((val == NULL((void*)0) && l->data != NULL((void*)0)) ||
1671 (val != NULL((void*)0) && l->data == NULL((void*)0)) ||
1672 (val != NULL((void*)0) && strcmp (val, l->data))) {
1673 g_free (val);
1674 return FALSE(0);
1675 }
1676
1677 g_free (val);
1678 l = l->next;
1679 } while (gtk_tree_model_iter_next (model, &iter));
1680
1681 return l == NULL((void*)0);
1682 } else {
1683 return (empty_model && entries == NULL((void*)0)) ||
1684 (!empty_model && entries != NULL((void*)0));
1685 }
1686}
1687
1688static char *
1689combo_box_get_active_entry (GtkComboBox *combo_box,
1690 unsigned int column)
1691{
1692 GtkTreeIter iter;
1693 char *val;
1694
1695 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1695, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1696
1697 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box))))), &iter)) {
1698 GtkTreeModel *model;
1699
1700 model = gtk_combo_box_get_model (combo_box);
1701 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_134
= 1; else _g_boolean_var_134 = 0; _g_boolean_var_134; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1701, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1702
1703 gtk_tree_model_get (model, &iter,
1704 column, &val,
1705 -1);
1706 return val;
1707 }
1708
1709 return NULL((void*)0);
1710}
1711
1712/* returns the index of the given entry in the the given column
1713 * at the first level of model. Returns -1 if entry can't be found
1714 * or entry is NULL.
1715 * */
1716static int
1717tree_model_get_entry_index (GtkTreeModel *model,
1718 unsigned int column,
1719 const char *entry)
1720{
1721 GtkTreeIter iter;
1722 gboolean empty_model;
1723
1724 g_assert (GTK_IS_TREE_MODEL (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((gtk_tree_model_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_135
= 1; else _g_boolean_var_135 = 0; _g_boolean_var_135; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1724, ((const char*) (__func__)), "GTK_IS_TREE_MODEL (model)"
); } while (0)
;
1725 g_assert (gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if (gtk_tree_model_get_column_type (model, column) == ((GType
) ((16) << (2)))) _g_boolean_var_136 = 1; else _g_boolean_var_136
= 0; _g_boolean_var_136; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1725, ((const char*
) (__func__)), "gtk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1726
1727 empty_model = !gtk_tree_model_get_iter_first (model, &iter);
1728 if (!empty_model && entry != NULL((void*)0)) {
1729 int index;
1730
1731 index = 0;
1732
1733 do {
1734 char *val;
1735
1736 gtk_tree_model_get (model, &iter,
1737 column, &val,
1738 -1);
1739 if (val != NULL((void*)0) && !strcmp (val, entry)) {
1740 g_free (val);
1741 return index;
1742 }
1743
1744 g_free (val);
1745 index++;
1746 } while (gtk_tree_model_iter_next (model, &iter));
1747 }
1748
1749 return -1;
1750}
1751
1752
1753static void
1754synch_groups_combo_box (GtkComboBox *combo_box, CajaFile *file)
1755{
1756 GList *groups;
1757 GList *node;
1758 GtkTreeModel *model;
1759 GtkListStore *store;
1760 char *current_group_name;
1761 int current_group_index;
1762
1763 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_137
= 1; else _g_boolean_var_137 = 0; _g_boolean_var_137; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1763, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1764 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_138
= 1; else _g_boolean_var_138 = 0; _g_boolean_var_138; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1764, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1765
1766 if (caja_file_is_gone (file)) {
1767 return;
1768 }
1769
1770 groups = caja_file_get_settable_group_names (file);
1771
1772 model = gtk_combo_box_get_model (combo_box);
1773 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
1774 g_assert (GTK_IS_LIST_STORE (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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_139
= 1; else _g_boolean_var_139 = 0; _g_boolean_var_139; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1774, ((const char*) (__func__)), "GTK_IS_LIST_STORE (model)"
); } while (0)
;
1775
1776 if (!tree_model_entries_equal (model, 0, groups)) {
1777 int group_index;
1778
1779 /* Clear the contents of ComboBox in a wacky way because there
1780 * is no function to clear all items and also no function to obtain
1781 * the number of items in a combobox.
1782 */
1783 gtk_list_store_clear (store);
1784
1785 for (node = groups, group_index = 0; node != NULL((void*)0); node = node->next, ++group_index) {
1786 const char *group_name;
1787
1788 group_name = (const char *)node->data;
1789 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), group_name);
1790 }
1791 }
1792
1793 current_group_name = caja_file_get_group_name (file);
1794 current_group_index = tree_model_get_entry_index (model, 0, current_group_name);
1795
1796 /* If current group wasn't in list, we prepend it (with a separator).
1797 * This can happen if the current group is an id with no matching
1798 * group in the groups file.
1799 */
1800 if (current_group_index < 0 && current_group_name != NULL((void*)0)) {
1801 if (groups != NULL((void*)0)) {
1802 /* add separator */
1803 gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), "-");
1804 }
1805
1806 gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (combo_box)((((GtkComboBoxText*) (void *) ((combo_box))))), current_group_name);
1807 current_group_index = 0;
1808 }
1809 gtk_combo_box_set_active (combo_box, current_group_index);
1810
1811 g_free (current_group_name);
1812 g_list_free_full (groups, g_free);
1813}
1814
1815static gboolean
1816combo_box_row_separator_func (GtkTreeModel *model,
1817 GtkTreeIter *iter,
1818 gpointer data)
1819{
1820 gchar *text;
1821 gboolean ret;
1822
1823 gtk_tree_model_get (model, iter, 0, &text, -1);
1824
1825 if (text == NULL((void*)0)) {
1826 return FALSE(0);
1827 }
1828
1829 if (strcmp (text, "-") == 0) {
1830 ret = TRUE(!(0));
1831 } else {
1832 ret = FALSE(0);
1833 }
1834
1835 g_free (text);
1836 return ret;
1837}
1838
1839static GtkComboBox *
1840attach_combo_box (GtkGrid *grid,
1841 GtkWidget *sibling,
1842 gboolean two_columns)
1843{
1844 GtkWidget *combo_box;
1845
1846 if (!two_columns) {
1847 combo_box = gtk_combo_box_text_new ();
1848 } else {
1849 GtkTreeModel *model;
1850 GtkCellRenderer *renderer;
1851
1852 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING))((((GtkTreeModel*) (void *) ((gtk_list_store_new (2, ((GType)
((16) << (2))), ((GType) ((16) << (2)))))))))
;
1853 combo_box = gtk_combo_box_new_with_model (model);
1854 g_object_unref (G_OBJECT (model)((((GObject*) (void *) ((model))))));
1855
1856 renderer = gtk_cell_renderer_text_new ();
1857 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box)((((GtkCellLayout*) (void *) ((combo_box))))), renderer, TRUE(!(0)));
1858 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo_box)((((GtkCellLayout*) (void *) ((combo_box))))), renderer,
1859 "text", 0);
1860
1861 }
1862
1863 gtk_widget_set_halign (combo_box, GTK_ALIGN_START);
1864
1865 gtk_widget_show (combo_box);
1866
1867 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box))))),
1868 combo_box_row_separator_func,
1869 NULL((void*)0),
1870 NULL((void*)0));
1871
1872 gtk_grid_attach_next_to (grid, combo_box, sibling,
1873 GTK_POS_RIGHT, 1, 1);
1874
1875 return GTK_COMBO_BOX (combo_box)((((GtkComboBox*) (void *) ((combo_box)))));
1876}
1877
1878static GtkComboBox*
1879attach_group_combo_box (GtkGrid *grid,
1880 GtkWidget *sibling,
1881 CajaFile *file)
1882{
1883 GtkComboBox *combo_box;
1884
1885 combo_box = attach_combo_box (grid, sibling, FALSE(0));
1886
1887 synch_groups_combo_box (combo_box, file);
1888
1889 /* Connect to signal to update menu when file changes. */
1890 g_signal_connect_object (file, "changed",
1891 G_CALLBACK (synch_groups_combo_box)((GCallback) (synch_groups_combo_box)),
1892 combo_box, G_CONNECT_SWAPPED);
1893 g_signal_connect_data (combo_box, "changed",
1894 G_CALLBACK (changed_group_callback)((GCallback) (changed_group_callback)),
1895 caja_file_ref (file),
1896 (GClosureNotify)caja_file_unref, 0);
1897
1898 return combo_box;
1899}
1900
1901static void
1902owner_change_callback (CajaFile *file,
1903 GFile *result_location,
1904 GError *error,
1905 FMPropertiesWindow *window)
1906{
1907 char *owner;
1908
1909 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_140 = 1; else _g_boolean_var_140 = 0; _g_boolean_var_140
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1909, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1910 g_assert (window->details->owner_change_file == file)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (window->details->owner_change_file == file) _g_boolean_var_141
= 1; else _g_boolean_var_141 = 0; _g_boolean_var_141; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1910, ((const char*) (__func__)), "window->details->owner_change_file == file"
); } while (0)
;
1911
1912 owner = window->details->owner_change_owner;
1913 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if (owner != ((void*)0)) _g_boolean_var_142 = 1; else _g_boolean_var_142
= 0; _g_boolean_var_142; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1913, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1914
1915 /* Report the error if it's an error. */
1916 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
1917 fm_report_error_setting_owner (file, error, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1918
1919 caja_file_unref (file);
1920 g_free (owner);
1921
1922 window->details->owner_change_file = NULL((void*)0);
1923 window->details->owner_change_owner = NULL((void*)0);
1924 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
1925}
1926
1927static void
1928cancel_owner_change_callback (FMPropertiesWindow *window)
1929{
1930 CajaFile *file;
1931 char *owner;
1932
1933 file = window->details->owner_change_file;
1934 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_143
= 1; else _g_boolean_var_143 = 0; _g_boolean_var_143; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1934, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1935
1936 owner = window->details->owner_change_owner;
1937 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if (owner != ((void*)0)) _g_boolean_var_144 = 1; else _g_boolean_var_144
= 0; _g_boolean_var_144; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1937, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1938
1939 caja_file_cancel (file, (CajaFileOperationCallback) owner_change_callback, window);
1940
1941 caja_file_unref (file);
1942 g_free (owner);
1943
1944 window->details->owner_change_file = NULL((void*)0);
1945 window->details->owner_change_owner = NULL((void*)0);
1946 g_object_unref (window);
1947}
1948
1949static gboolean
1950schedule_owner_change_timeout (FMPropertiesWindow *window)
1951{
1952 CajaFile *file;
1953 char *owner;
1954
1955 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_145 = 1; else _g_boolean_var_145 = 0; _g_boolean_var_145
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1955, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1956
1957 file = window->details->owner_change_file;
1958 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_146
= 1; else _g_boolean_var_146 = 0; _g_boolean_var_146; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1958, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1959
1960 owner = window->details->owner_change_owner;
1961 g_assert (owner != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if (owner != ((void*)0)) _g_boolean_var_147 = 1; else _g_boolean_var_147
= 0; _g_boolean_var_147; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1961, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1962
1963 eel_timed_wait_start
1964 ((EelCancelCallback) cancel_owner_change_callback,
1965 window,
1966 _("Cancel Owner Change?")dcgettext (((void*)0), "Cancel Owner Change?", 5),
1967 GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
1968
1969 caja_file_set_owner
1970 (file, owner,
1971 (CajaFileOperationCallback) owner_change_callback, window);
1972
1973 window->details->owner_change_timeout = 0;
1974 return FALSE(0);
1975}
1976
1977static void
1978schedule_owner_change (FMPropertiesWindow *window,
1979 CajaFile *file,
1980 const char *owner)
1981{
1982 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_148
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_148 = 1; else _g_boolean_var_148 = 0; _g_boolean_var_148
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1982, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1983 g_assert (window->details->owner_change_owner == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if (window->details->owner_change_owner == ((void*)0)
) _g_boolean_var_149 = 1; else _g_boolean_var_149 = 0; _g_boolean_var_149
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1983, ((const char*) (__func__)), "window->details->owner_change_owner == NULL"
); } while (0)
;
1984 g_assert (window->details->owner_change_file == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (window->details->owner_change_file == ((void*)0))
_g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1984, ((const char*) (__func__)), "window->details->owner_change_file == NULL"
); } while (0)
;
1985 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_151
= 1; else _g_boolean_var_151 = 0; _g_boolean_var_151; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1985, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
1986
1987 window->details->owner_change_file = caja_file_ref (file);
1988 window->details->owner_change_owner = g_strdup (owner)g_strdup_inline (owner);
1989 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) ((window))))))) (g_object_ref
) (((((GObject*) (void *) ((window)))))))
;
1990 window->details->owner_change_timeout =
1991 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1992 (GSourceFunc) schedule_owner_change_timeout,
1993 window);
1994}
1995
1996static void
1997unschedule_or_cancel_owner_change (FMPropertiesWindow *window)
1998{
1999 CajaFile *file;
2000 char *owner;
2001
2002 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_152 = 1; else _g_boolean_var_152 = 0; _g_boolean_var_152
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2002, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2003
2004 file = window->details->owner_change_file;
2005 owner = window->details->owner_change_owner;
2006
2007 g_assert ((file == NULL && owner == NULL) ||do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if ((file == ((void*)0) && owner == ((void*)0)) || (
file != ((void*)0) && owner != ((void*)0))) _g_boolean_var_153
= 1; else _g_boolean_var_153 = 0; _g_boolean_var_153; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2008, ((const char*) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
2008 (file != NULL && owner != NULL))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if ((file == ((void*)0) && owner == ((void*)0)) || (
file != ((void*)0) && owner != ((void*)0))) _g_boolean_var_153
= 1; else _g_boolean_var_153 = 0; _g_boolean_var_153; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2008, ((const char*) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
;
2009
2010 if (file != NULL((void*)0)) {
2011 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_154
= 1; else _g_boolean_var_154 = 0; _g_boolean_var_154; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2011, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2012
2013 if (window->details->owner_change_timeout == 0) {
2014 caja_file_cancel (file,
2015 (CajaFileOperationCallback) owner_change_callback, window);
2016 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
2017 }
2018
2019 caja_file_unref (file);
2020 g_free (owner);
2021
2022 window->details->owner_change_file = NULL((void*)0);
2023 window->details->owner_change_owner = NULL((void*)0);
2024 g_object_unref (G_OBJECT (window)((((GObject*) (void *) ((window))))));
2025 }
2026
2027 if (window->details->owner_change_timeout > 0) {
2028 g_assert (file != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if (file != ((void*)0)) _g_boolean_var_155 = 1; else _g_boolean_var_155
= 0; _g_boolean_var_155; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2028, ((const char*
) (__func__)), "file != NULL"); } while (0)
;
2029 g_source_remove (window->details->owner_change_timeout);
2030 window->details->owner_change_timeout = 0;
2031 }
2032}
2033
2034static void
2035changed_owner_callback (GtkComboBox *combo_box, CajaFile* file)
2036{
2037 char *owner_text;
2038 char **name_array;
2039 char *new_owner;
2040 char *cur_owner;
2041
2042 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2042, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2043 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_157
= 1; else _g_boolean_var_157 = 0; _g_boolean_var_157; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2043, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2044
2045 owner_text = combo_box_get_active_entry (combo_box, 0);
2046 if (! owner_text)
2047 return;
2048 name_array = g_strsplit (owner_text, " - ", 2);
2049 new_owner = name_array[0];
2050 g_free (owner_text);
2051 cur_owner = caja_file_get_owner_name (file);
2052
2053 if (strcmp (new_owner, cur_owner) != 0) {
2054 FMPropertiesWindow *window;
2055
2056 /* Try to change file owner. If this fails, complain to user. */
2057 window = FM_PROPERTIES_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (combo_box), GTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) ((gtk_widget_get_ancestor (
((((GtkWidget*) (void *) ((combo_box))))), (gtk_window_get_type
())))))))
;
2058
2059 unschedule_or_cancel_owner_change (window);
2060 schedule_owner_change (window, file, new_owner);
2061 }
2062 g_strfreev (name_array);
2063 g_free (cur_owner);
2064}
2065
2066static void
2067synch_user_menu (GtkComboBox *combo_box, CajaFile *file)
2068{
2069 GList *users;
2070 GList *node;
2071 GtkTreeModel *model;
2072 GtkListStore *store;
2073 GtkTreeIter iter;
2074 char *user_name;
2075 char *owner_name;
2076 int owner_index;
2077 char **name_array;
2078
2079 g_assert (GTK_IS_COMBO_BOX (combo_box))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((gtk_combo_box_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_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2079, ((const char*) (__func__)), "GTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2080 g_assert (CAJA_IS_FILE (file))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (caja_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_159
= 1; else _g_boolean_var_159 = 0; _g_boolean_var_159; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2080, ((const char*) (__func__)), "CAJA_IS_FILE (file)"); }
while (0)
;
2081
2082 if (caja_file_is_gone (file)) {
2083 return;
2084 }
2085
2086 users = caja_get_user_names ();
2087
2088 model = gtk_combo_box_get_model (combo_box);
2089 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
2090 g_assert (GTK_IS_LIST_STORE (model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((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_160
= 1; else _g_boolean_var_160 = 0; _g_boolean_var_160; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2090, ((const char*) (__func__)), "GTK_IS_LIST_STORE (model)"
); } while (0)
;
2091
2092 if (!tree_model_entries_equal (model, 1, users)) {
2093 int user_index;
2094
2095 /* Clear the contents of ComboBox in a wacky way because there
2096 * is no function to clear all items and also no function to obtain
2097 * the number of items in a combobox.
2098 */
2099 gtk_list_store_clear (store);
2100
2101 for (node = users, user_index = 0; node != NULL((void*)0); node = node->next, ++user_index) {
2102 char *combo_text;
2103
2104 user_name = (char *)node->data;
2105
2106 name_array = g_strsplit (user_name, "\n", 2);
2107 if (name_array[1] != NULL((void*)0)) {
2108 combo_text = g_strdup_printf ("%s - %s", name_array[0], name_array[1]);
2109 } else {
2110 combo_text = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2111 }
2112
2113 gtk_list_store_append (store, &iter);
2114 gtk_list_store_set (store, &iter,
2115 0, combo_text,
2116 1, user_name,
2117 -1);
2118
2119 g_strfreev (name_array);
2120 g_free (combo_text);
2121 }
2122 }
2123
2124 owner_name = caja_file_get_string_attribute (file, "owner");
2125 owner_index = tree_model_get_entry_index (model, 0, owner_name);
2126
2127 /* If owner wasn't in list, we prepend it (with a separator).
2128 * This can happen if the owner is an id with no matching
2129 * identifier in the passwords file.
2130 */
2131 if (owner_index < 0 && owner_name != NULL((void*)0)) {
2132 if (users != NULL((void*)0)) {
2133 /* add separator */
2134 gtk_list_store_prepend (store, &iter);
2135 gtk_list_store_set (store, &iter,
2136 0, "-",
2137 1, NULL((void*)0),
2138 -1);
2139 }
2140
2141 name_array = g_strsplit (owner_name, " - ", 2);
2142 if (name_array[1] != NULL((void*)0)) {
2143 user_name = g_strdup_printf ("%s\n%s", name_array[0], name_array[1]);
2144 } else {
2145 user_name = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2146 }
2147 owner_index = 0;
2148
2149 gtk_list_store_prepend (store, &iter);
2150 gtk_list_store_set (store, &iter,
2151 0, owner_name,
2152 1, user_name,
2153 -1);
2154
2155 g_free (user_name);
2156 g_strfreev (name_array);
2157 }
2158
2159 gtk_combo_box_set_active (combo_box, owner_index);
2160
2161 g_free (owner_name);
2162 g_list_free_full (users, g_free);
2163}
2164
2165static GtkComboBox*
2166attach_owner_combo_box (GtkGrid *grid,
2167 GtkWidget *sibling,
2168 CajaFile *file)
2169{
2170 GtkComboBox *combo_box;
2171
2172 combo_box = attach_combo_box (grid, sibling, TRUE(!(0)));
2173
2174 synch_user_menu (combo_box, file);
2175
2176 /* Connect to signal to update menu when file changes. */
2177 g_signal_connect_object (file, "changed",
2178 G_CALLBACK (synch_user_menu)((GCallback) (synch_user_menu)),
2179 combo_box, G_CONNECT_SWAPPED);
2180 g_signal_connect_data (combo_box, "changed",
2181 G_CALLBACK (changed_owner_callback)((GCallback) (changed_owner_callback)),
2182 caja_file_ref (file),
2183 (GClosureNotify)caja_file_unref, 0);
2184
2185 return combo_box;
2186}
2187
2188static gboolean
2189file_has_prefix (CajaFile *file,
2190 GList *prefix_candidates)
2191{
2192 GList *p;
2193 GFile *location, *candidate_location;
2194
2195 location = caja_file_get_location (file);
2196
2197 for (p = prefix_candidates; p != NULL((void*)0); p = p->next) {
2198 if (file == p->data) {
2199 continue;
2200 }
2201
2202 candidate_location = caja_file_get_location (CAJA_FILE (p->data)((((CajaFile*) (void *) ((p->data))))));
2203 if (g_file_has_prefix (location, candidate_location)) {
2204 g_object_unref (location);
2205 g_object_unref (candidate_location);
2206 return TRUE(!(0));
2207 }
2208 g_object_unref (candidate_location);
2209 }
2210
2211 g_object_unref (location);
2212
2213 return FALSE(0);
2214}
2215
2216static void
2217directory_contents_value_field_update (FMPropertiesWindow *window)
2218{
2219 CajaRequestStatus file_status, status;
2220 char *text, *temp;
2221 guint directory_count;
2222 guint file_count;
2223 guint total_count;
2224 guint unreadable_directory_count;
2225 goffset total_size;
2226 goffset total_size_on_disk;
2227 gboolean used_two_lines;
2228 GList *l;
2229 guint file_unreadable;
2230 goffset file_size;
2231 goffset file_size_on_disk;
2232 CajaFile *file = NULL((void*)0);
2233
2234 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_161 = 1; else _g_boolean_var_161 = 0; _g_boolean_var_161
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2234, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2235
2236 status = CAJA_REQUEST_DONE;
2237 file_status = CAJA_REQUEST_NOT_STARTED;
Value stored to 'file_status' is never read
2238 total_count = window->details->total_count;
2239 total_size = window->details->total_size;
2240 total_size_on_disk = window->details->total_size_on_disk;
2241 unreadable_directory_count = FALSE(0);
2242
2243 for (l = window->details->target_files; l; l = l->next) {
2244 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
2245
2246 if (file_has_prefix (file, window->details->target_files)) {
2247 /* don't count nested files twice */
2248 continue;
2249 }
2250
2251 if (caja_file_is_directory (file)) {
2252 file_status = caja_file_get_deep_counts (file,
2253 &directory_count,
2254 &file_count,
2255 &file_unreadable,
2256 &file_size,
2257 &file_size_on_disk,
2258 TRUE(!(0)));
2259 total_count += (file_count + directory_count);
2260 total_size += file_size;
2261 total_size_on_disk += file_size_on_disk;
2262
2263 if (file_unreadable) {
2264 unreadable_directory_count = TRUE(!(0));
2265 }
2266
2267 if (file_status != CAJA_REQUEST_DONE) {
2268 status = file_status;
2269 }
2270 } else {
2271 ++total_count;
2272 total_size += caja_file_get_size (file);
2273 total_size_on_disk += caja_file_get_size_on_disk (file);
2274 }
2275 }
2276
2277 /* If we've already displayed the total once, don't do another visible
2278 * count-up if the deep_count happens to get invalidated.
2279 * But still display the new total, since it might have changed.
2280 */
2281 if (window->details->deep_count_finished &&
2282 status != CAJA_REQUEST_DONE) {
2283 return;
2284 }
2285
2286 text = NULL((void*)0);
2287 used_two_lines = FALSE(0);
2288
2289 if (total_count == 0) {
2290 switch (status) {
2291 case CAJA_REQUEST_DONE:
2292 if (unreadable_directory_count == 0) {
2293 text = g_strdup (_("nothing"))g_strdup_inline (dcgettext (((void*)0), "nothing", 5));
2294 } else {
2295 text = g_strdup (_("unreadable"))g_strdup_inline (dcgettext (((void*)0), "unreadable", 5));
2296 }
2297
2298 break;
2299 default:
2300 text = g_strdup ("...")g_strdup_inline ("...");
2301 }
2302 } else {
2303 char *size_str;
2304 char *size_on_disk_str;
2305
2306 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
2307 size_str = g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
2308 size_on_disk_str = g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
2309 } else {
2310 size_str = g_format_size (total_size);
2311 size_on_disk_str = g_format_size (total_size_on_disk);
2312 }
2313
2314 text = g_strdup_printf (ngettext("%'d item, with size %s (%s on disk)",dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
2315 "%'d items, totalling %s (%s on disk)",dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
2316 total_count)dcngettext (((void*)0), "%'d item, with size %s (%s on disk)"
, "%'d items, totalling %s (%s on disk)", total_count, 5)
,
2317 total_count, size_str, size_on_disk_str);
2318 g_free (size_str);
2319 g_free (size_on_disk_str);
2320
2321 if (unreadable_directory_count != 0) {
2322 temp = text;
2323 text = g_strconcat (temp, "\n",
2324 _("(some contents unreadable)")dcgettext (((void*)0), "(some contents unreadable)", 5),
2325 NULL((void*)0));
2326 g_free (temp);
2327 used_two_lines = TRUE(!(0));
2328 }
2329 }
2330
2331 gtk_label_set_text (window->details->directory_contents_value_field,
2332 text);
2333 g_free (text);
2334
2335 /* Also set the title field here, with a trailing carriage return &
2336 * space if the value field has two lines. This is a hack to get the
2337 * "Contents:" title to line up with the first line of the
2338 * 2-line value. Maybe there's a better way to do this, but I
2339 * couldn't think of one.
2340 */
2341 text = g_strdup (_("Contents:"))g_strdup_inline (dcgettext (((void*)0), "Contents:", 5));
2342 if (used_two_lines) {
2343 temp = text;
2344 text = g_strconcat (temp, "\n ", NULL((void*)0));
2345 g_free (temp);
2346 }
2347 gtk_label_set_text (window->details->directory_contents_title_field,
2348 text);
2349 g_free (text);
2350
2351 if (status == CAJA_REQUEST_DONE) {
2352 window->details->deep_count_finished = TRUE(!(0));
2353 }
2354}
2355
2356static gboolean
2357update_directory_contents_callback (gpointer data)
2358{
2359 FMPropertiesWindow *window;
2360
2361 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2362
2363 window->details->update_directory_contents_timeout_id = 0;
2364 directory_contents_value_field_update (window);
2365
2366 return FALSE(0);
2367}
2368
2369static void
2370schedule_directory_contents_update (FMPropertiesWindow *window)
2371{
2372 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_162 = 1; else _g_boolean_var_162 = 0; _g_boolean_var_162
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2372, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2373
2374 if (window->details->update_directory_contents_timeout_id == 0) {
2375 window->details->update_directory_contents_timeout_id
2376 = g_timeout_add (DIRECTORY_CONTENTS_UPDATE_INTERVAL200,
2377 update_directory_contents_callback,
2378 window);
2379 }
2380}
2381
2382static GtkLabel *
2383attach_directory_contents_value_field (FMPropertiesWindow *window,
2384 GtkGrid *grid,
2385 GtkWidget *sibling)
2386{
2387 GtkLabel *value_field;
2388 GList *l;
2389 CajaFile *file = NULL((void*)0);
2390
2391 value_field = attach_value_label (grid, sibling, "");
2392
2393 g_assert (window->details->directory_contents_value_field == NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if (window->details->directory_contents_value_field ==
((void*)0)) _g_boolean_var_163 = 1; else _g_boolean_var_163 =
0; _g_boolean_var_163; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2393, ((const char*
) (__func__)), "window->details->directory_contents_value_field == NULL"
); } while (0)
;
2394 window->details->directory_contents_value_field = value_field;
2395
2396 gtk_label_set_line_wrap (value_field, TRUE(!(0)));
2397
2398 /* Fill in the initial value. */
2399 directory_contents_value_field_update (window);
2400
2401 for (l = window->details->target_files; l; l = l->next) {
2402 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
2403 caja_file_recompute_deep_counts (file);
2404
2405 g_signal_connect_object (file,
2406 "updated_deep_count_in_progress",
2407 G_CALLBACK (schedule_directory_contents_update)((GCallback) (schedule_directory_contents_update)),
2408 window, G_CONNECT_SWAPPED);
2409 }
2410
2411 return value_field;
2412}
2413
2414static GtkLabel *
2415attach_title_field (GtkGrid *grid,
2416 const char *title)
2417{
2418 return attach_label (grid, NULL((void*)0), title, FALSE(0), FALSE(0), TRUE(!(0)));
2419}
2420
2421
2422
2423#define INCONSISTENT_STATE_STRING"\xE2\x80\x92" \
2424 "\xE2\x80\x92"
2425
2426static void
2427append_title_value_pair (FMPropertiesWindow *window,
2428 GtkGrid *grid,
2429 const char *title,
2430 const char *file_attribute_name,
2431 const char *inconsistent_state,
2432 gboolean show_original)
2433{
2434 GtkLabel *title_label;
2435 GtkWidget *value;
2436
2437 title_label = attach_title_field (grid, title);
2438 value = attach_value_field (window, grid, GTK_WIDGET (title_label)((((GtkWidget*) (void *) ((title_label))))),
2439 file_attribute_name,
2440 inconsistent_state,
2441 show_original);
2442 gtk_label_set_mnemonic_widget (title_label, value);
2443}
2444
2445static void
2446append_title_and_ellipsizing_value (FMPropertiesWindow *window,
2447 GtkGrid *grid,
2448 const char *title,
2449 const char *file_attribute_name,
2450 const char *inconsistent_state,
2451 gboolean show_original)
2452{
2453 GtkLabel *title_label;
2454 GtkWidget *value;
2455
2456 title_label = attach_title_field (grid, title);
2457 value = attach_ellipsizing_value_field (window, grid,
2458 GTK_WIDGET (title_label)((((GtkWidget*) (void *) ((title_label))))),
2459 file_attribute_name,
2460 inconsistent_state,
2461 show_original);
2462 gtk_label_set_mnemonic_widget (title_label, value);
2463}
2464
2465static void
2466append_directory_contents_fields (FMPropertiesWindow *window,
2467 GtkGrid *grid)
2468{
2469 GtkLabel *title_field, *value_field;
2470 title_field = attach_title_field (grid, "");
2471 window->details->directory_contents_title_field = title_field;
2472 gtk_label_set_line_wrap (title_field, TRUE(!(0)));
2473
2474 value_field = attach_directory_contents_value_field
2475 (window, grid, GTK_WIDGET (title_field)((((GtkWidget*) (void *) ((title_field))))));
2476
2477 gtk_label_set_mnemonic_widget (title_field, GTK_WIDGET(value_field)((((GtkWidget*) (void *) ((value_field))))));
2478}
2479
2480static GtkWidget *
2481create_page_with_hbox (GtkNotebook *notebook,
2482 const char *title)
2483{
2484 GtkWidget *hbox;
2485
2486 g_assert (GTK_IS_NOTEBOOK (notebook))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((gtk_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; }))))) _g_boolean_var_164
= 1; else _g_boolean_var_164 = 0; _g_boolean_var_164; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2486, ((const char*) (__func__)), "GTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2487 g_assert (title != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if (title != ((void*)0)) _g_boolean_var_165 = 1; else _g_boolean_var_165
= 0; _g_boolean_var_165; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2487, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2488
2489 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2490 gtk_widget_show (hbox);
2491 gtk_container_set_border_width (GTK_CONTAINER (hbox)((((GtkContainer*) (void *) ((hbox))))), 12);
2492 gtk_box_set_spacing (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), 12);
2493 gtk_notebook_append_page (notebook, hbox, gtk_label_new (title));
2494
2495 return hbox;
2496}
2497
2498static GtkWidget *
2499create_page_with_vbox (GtkNotebook *notebook,
2500 const char *title)
2501{
2502 GtkWidget *vbox;
2503
2504 g_assert (GTK_IS_NOTEBOOK (notebook))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((gtk_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; }))))) _g_boolean_var_166
= 1; else _g_boolean_var_166 = 0; _g_boolean_var_166; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2504, ((const char*) (__func__)), "GTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2505 g_assert (title != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if (title != ((void*)0)) _g_boolean_var_167 = 1; else _g_boolean_var_167
= 0; _g_boolean_var_167; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2505, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2506
2507 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2508 gtk_widget_show (vbox);
2509
2510 gtk_container_set_border_width (GTK_CONTAINER (vbox)((((GtkContainer*) (void *) ((vbox))))), 12);
2511 gtk_notebook_append_page (notebook, vbox, gtk_label_new (title));
2512
2513 return vbox;
2514}
2515
2516static GtkWidget *
2517append_blank_row (GtkGrid *grid)
2518{
2519 return GTK_WIDGET (attach_title_field (grid, ""))((((GtkWidget*) (void *) ((attach_title_field (grid, ""))))));
2520}
2521
2522static void
2523append_blank_slim_row (GtkGrid *grid)
2524{
2525 GtkWidget *w;
2526 PangoAttribute *attribute;
2527 PangoAttrList *attr_list;
2528
2529 attr_list = pango_attr_list_new ();
2530 attribute = pango_attr_scale_new (0.30);
2531 pango_attr_list_insert (attr_list, attribute);
2532
2533 w = gtk_label_new (NULL((void*)0));
2534 gtk_label_set_attributes (GTK_LABEL (w)((((GtkLabel*) (void *) ((w))))), attr_list);
2535 gtk_widget_show (w);
2536
2537 pango_attr_list_unref (attr_list);
2538
2539 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), w);
2540}
2541
2542static GtkWidget *
2543create_grid_with_standard_properties (void)
2544{
2545 GtkWidget *grid;
2546
2547 grid = gtk_grid_new ();
2548 gtk_container_set_border_width (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), 6);
2549 gtk_grid_set_row_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), ROW_PAD6);
2550 gtk_grid_set_column_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), 12);
2551 gtk_orientable_set_orientation (GTK_ORIENTABLE (grid)((((GtkOrientable*) (void *) ((grid))))), GTK_ORIENTATION_VERTICAL);
2552 gtk_widget_show (grid);
2553
2554 return grid;
2555}
2556
2557static gboolean
2558is_merged_trash_directory (CajaFile *file)
2559{
2560 char *file_uri;
2561 gboolean result;
2562
2563 file_uri = caja_file_get_uri (file);
2564 result = strcmp (file_uri, "trash:///") == 0;
2565 g_free (file_uri);
2566
2567 return result;
2568}
2569
2570static gboolean
2571is_computer_directory (CajaFile *file)
2572{
2573 char *file_uri;
2574 gboolean result;
2575
2576 file_uri = caja_file_get_uri (file);
2577 result = strcmp (file_uri, "computer:///") == 0;
2578 g_free (file_uri);
2579
2580 return result;
2581}
2582
2583static gboolean
2584is_network_directory (CajaFile *file)
2585{
2586 char *file_uri;
2587 gboolean result;
2588
2589 file_uri = caja_file_get_uri (file);
2590 result = strcmp (file_uri, "network:///") == 0;
2591 g_free (file_uri);
2592
2593 return result;
2594}
2595
2596static gboolean
2597is_burn_directory (CajaFile *file)
2598{
2599 char *file_uri;
2600 gboolean result;
2601
2602 file_uri = caja_file_get_uri (file);
2603 result = strcmp (file_uri, "burn:///") == 0;
2604 g_free (file_uri);
2605
2606 return result;
2607}
2608
2609static gboolean
2610should_show_custom_icon_buttons (FMPropertiesWindow *window)
2611{
2612 if (is_multi_file_window (window)) {
2613 return FALSE(0);
2614 }
2615
2616 return TRUE(!(0));
2617}
2618
2619static gboolean
2620should_show_file_type (FMPropertiesWindow *window)
2621{
2622 if (!is_multi_file_window (window)
2623 && (is_merged_trash_directory (get_target_file (window)) ||
2624 is_computer_directory (get_target_file (window)) ||
2625 is_network_directory (get_target_file (window)) ||
2626 is_burn_directory (get_target_file (window)))) {
2627 return FALSE(0);
2628 }
2629
2630
2631 return TRUE(!(0));
2632}
2633
2634static gboolean
2635should_show_location_info (FMPropertiesWindow *window)
2636{
2637 if (!is_multi_file_window (window)
2638 && (is_merged_trash_directory (get_target_file (window)) ||
2639 is_computer_directory (get_target_file (window)) ||
2640 is_network_directory (get_target_file (window)) ||
2641 is_burn_directory (get_target_file (window)))) {
2642 return FALSE(0);
2643 }
2644
2645 return TRUE(!(0));
2646}
2647
2648static gboolean
2649should_show_accessed_date (FMPropertiesWindow *window)
2650{
2651 /* Accessed date for directory seems useless. If we some
2652 * day decide that it is useful, we should separately
2653 * consider whether it's useful for "trash:".
2654 */
2655 if (file_list_all_directories (window->details->target_files)
2656 || is_multi_file_window (window))
2657 {
2658 return FALSE(0);
2659 }
2660
2661 return TRUE(!(0));
2662}
2663
2664static gboolean
2665should_show_modified_date (FMPropertiesWindow *window)
2666{
2667 CajaFile *file;
2668
2669 if (is_multi_file_window (window))
2670 return FALSE(0);
2671
2672 file = get_original_file (window);
2673 if ((file != NULL((void*)0)) && caja_file_can_unmount (file))
2674 return FALSE(0);
2675
2676 return TRUE(!(0));
2677}
2678
2679static gboolean
2680should_show_link_target (FMPropertiesWindow *window)
2681{
2682 if (!is_multi_file_window (window)
2683 && caja_file_is_symbolic_link (get_target_file (window))) {
2684 return TRUE(!(0));
2685 }
2686
2687 return FALSE(0);
2688}
2689
2690static gboolean
2691should_show_free_space (FMPropertiesWindow *window)
2692{
2693
2694 if (!is_multi_file_window (window)
2695 && (is_merged_trash_directory (get_target_file (window)) ||
2696 is_computer_directory (get_target_file (window)) ||
2697 is_network_directory (get_target_file (window)) ||
2698 is_burn_directory (get_target_file (window)))) {
2699 return FALSE(0);
2700 }
2701
2702 if (file_list_all_directories (window->details->target_files)) {
2703 return TRUE(!(0));
2704 }
2705
2706 return FALSE(0);
2707}
2708
2709static gboolean
2710should_show_volume_usage (FMPropertiesWindow *window)
2711{
2712 CajaFile *file;
2713 gboolean success = FALSE(0);
2714
2715 if (is_multi_file_window (window)) {
2716 return FALSE(0);
2717 }
2718
2719 file = get_original_file (window);
2720
2721 if (file == NULL((void*)0)) {
2722 return FALSE(0);
2723 }
2724
2725 if (caja_file_can_unmount (file)) {
2726 return TRUE(!(0));
2727 }
2728
2729#ifdef TODO_GIO
2730 /* Look at is_mountpoint for activation uri */
2731#endif
2732 return success;
2733}
2734
2735static void
2736paint_used_legend (GtkWidget *widget,
2737 cairo_t *cr,
2738 gpointer data)
2739{
2740 FMPropertiesWindow *window;
2741 gint width, height;
2742 GtkAllocation allocation;
2743
2744 gtk_widget_get_allocation (widget, &allocation);
2745
2746 width = allocation.width;
2747 height = allocation.height;
2748
2749 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2750
2751 cairo_rectangle (cr,
2752 2,
2753 2,
2754 width - 4,
2755 height - 4);
2756
2757 gdk_cairo_set_source_rgba (cr, &window->details->used_color);
2758 cairo_fill_preserve (cr);
2759
2760 gdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2761 cairo_stroke (cr);
2762}
2763
2764static void
2765paint_free_legend (GtkWidget *widget,
2766 cairo_t *cr, gpointer data)
2767{
2768 FMPropertiesWindow *window;
2769 gint width, height;
2770 GtkAllocation allocation;
2771
2772 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2773 gtk_widget_get_allocation (widget, &allocation);
2774
2775 width = allocation.width;
2776 height = allocation.height;
2777
2778 cairo_rectangle (cr,
2779 2,
2780 2,
2781 width - 4,
2782 height - 4);
2783
2784 gdk_cairo_set_source_rgba (cr, &window->details->free_color);
2785 cairo_fill_preserve(cr);
2786
2787 gdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2788 cairo_stroke (cr);
2789}
2790
2791static void
2792paint_pie_chart (GtkWidget *widget,
2793 cairo_t *cr,
2794 gpointer data)
2795{
2796
2797 FMPropertiesWindow *window;
2798 gint width, height;
2799 double free, used;
2800 double angle1, angle2, split, xc, yc, radius;
2801 GtkAllocation allocation;
2802
2803 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) ((data)))));
2804 gtk_widget_get_allocation (widget, &allocation);
2805
2806 width = allocation.width;
2807 height = allocation.height;
2808
2809
2810 free = (double)window->details->volume_free / (double)window->details->volume_capacity;
2811 used = 1.0 - free;
2812
2813 angle1 = free * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2814 angle2 = used * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2815 split = (2 * G_PI3.1415926535897932384626433832795028841971693993751 - angle1) * .5;
2816 xc = width / 2;
2817 yc = height / 2;
2818
2819 if (width < height) {
2820 radius = width / 2 - 8;
2821 } else {
2822 radius = height / 2 - 8;
2823 }
2824
2825 if (angle1 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle1 != 0) {
2826 angle1 = angle1 + split;
2827 }
2828
2829 if (angle2 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle2 != 0) {
2830 angle2 = angle2 - split;
2831 }
2832
2833 if (used > 0) {
2834 if (free != 0) {
2835 cairo_move_to (cr,xc,yc);
2836 }
2837
2838 cairo_arc (cr, xc, yc, radius, angle1, angle2);
2839
2840 if (free != 0) {
2841 cairo_line_to (cr,xc,yc);
2842 }
2843
2844 gdk_cairo_set_source_rgba (cr, &window->details->used_color);
2845 cairo_fill_preserve (cr);
2846
2847 gdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2848
2849 cairo_stroke (cr);
2850 }
2851
2852 if (free > 0) {
2853 if (used != 0) {
2854 cairo_move_to (cr,xc,yc);
2855 }
2856
2857 cairo_arc_negative (cr, xc, yc, radius, angle1, angle2);
2858
2859 if (used != 0) {
2860 cairo_line_to (cr,xc,yc);
2861 }
2862
2863
2864 gdk_cairo_set_source_rgba (cr, &window->details->free_color);
2865 cairo_fill_preserve(cr);
2866
2867 gdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2868
2869 cairo_stroke (cr);
2870 }
2871}
2872
2873
2874/* Copied from gtk/gtkstyle.c */
2875
2876static void
2877rgb_to_hls (gdouble *r,
2878 gdouble *g,
2879 gdouble *b)
2880{
2881 gdouble min;
2882 gdouble max;
2883 gdouble red;
2884 gdouble green;
2885 gdouble blue;
2886 gdouble h, l, s;
2887 gdouble delta;
2888
2889 red = *r;
2890 green = *g;
2891 blue = *b;
2892
2893 if (red > green)
2894 {
2895 if (red > blue)
2896 max = red;
2897 else
2898 max = blue;
2899
2900 if (green < blue)
2901 min = green;
2902 else
2903 min = blue;
2904 }
2905 else
2906 {
2907 if (green > blue)
2908 max = green;
2909 else
2910 max = blue;
2911
2912 if (red < blue)
2913 min = red;
2914 else
2915 min = blue;
2916 }
2917
2918 l = (max + min) / 2;
2919 s = 0;
2920 h = 0;
2921
2922 if (max != min)
2923 {
2924 if (l <= 0.5)
2925 s = (max - min) / (max + min);
2926 else
2927 s = (max - min) / (2 - max - min);
2928
2929 delta = max -min;
2930 if (red == max)
2931 h = (green - blue) / delta;
2932 else if (green == max)
2933 h = 2 + (blue - red) / delta;
2934 else if (blue == max)
2935 h = 4 + (red - green) / delta;
2936
2937 h *= 60;
2938 if (h < 0.0)
2939 h += 360;
2940 }
2941
2942 *r = h;
2943 *g = l;
2944 *b = s;
2945}
2946
2947static void
2948hls_to_rgb (gdouble *h,
2949 gdouble *l,
2950 gdouble *s)
2951{
2952 gdouble hue;
2953 gdouble lightness;
2954 gdouble saturation;
2955 gdouble m1, m2;
2956 gdouble r, g, b;
2957
2958 lightness = *l;
2959 saturation = *s;
2960
2961 if (lightness <= 0.5)
2962 m2 = lightness * (1 + saturation);
2963 else
2964 m2 = lightness + saturation - lightness * saturation;
2965 m1 = 2 * lightness - m2;
2966
2967 if (saturation == 0)
2968 {
2969 *h = lightness;
2970 *l = lightness;
2971 *s = lightness;
2972 }
2973 else
2974 {
2975 hue = *h + 120;
2976 while (hue > 360)
2977 hue -= 360;
2978 while (hue < 0)
2979 hue += 360;
2980
2981 if (hue < 60)
2982 r = m1 + (m2 - m1) * hue / 60;
2983 else if (hue < 180)
2984 r = m2;
2985 else if (hue < 240)
2986 r = m1 + (m2 - m1) * (240 - hue) / 60;
2987 else
2988 r = m1;
2989
2990 hue = *h;
2991 while (hue > 360)
2992 hue -= 360;
2993 while (hue < 0)
2994 hue += 360;
2995
2996 if (hue < 60)
2997 g = m1 + (m2 - m1) * hue / 60;
2998 else if (hue < 180)
2999 g = m2;
3000 else if (hue < 240)
3001 g = m1 + (m2 - m1) * (240 - hue) / 60;
3002 else
3003 g = m1;
3004
3005 hue = *h - 120;
3006 while (hue > 360)
3007 hue -= 360;
3008 while (hue < 0)
3009 hue += 360;
3010
3011 if (hue < 60)
3012 b = m1 + (m2 - m1) * hue / 60;
3013 else if (hue < 180)
3014 b = m2;
3015 else if (hue < 240)
3016 b = m1 + (m2 - m1) * (240 - hue) / 60;
3017 else
3018 b = m1;
3019
3020 *h = r;
3021 *l = g;
3022 *s = b;
3023 }
3024}
3025static void
3026_pie_style_shade (GdkRGBA *a,
3027 GdkRGBA *b,
3028 gdouble k)
3029{
3030 gdouble red;
3031 gdouble green;
3032 gdouble blue;
3033
3034 red = a->red;
3035 green = a->green;
3036 blue = a->blue;
3037
3038 rgb_to_hls (&red, &green, &blue);
3039
3040 green *= k;
3041 if (green > 1.0)
3042 green = 1.0;
3043 else if (green < 0.0)
3044 green = 0.0;
3045
3046 blue *= k;
3047 if (blue > 1.0)
3048 blue = 1.0;
3049 else if (blue < 0.0)
3050 blue = 0.0;
3051
3052 hls_to_rgb (&red, &green, &blue);
3053
3054 b->red = red;
3055 b->green = green;
3056 b->blue = blue;
3057 b->alpha = a->alpha;
3058}
3059
3060
3061static GtkWidget*
3062create_pie_widget (FMPropertiesWindow *window)
3063{
3064 CajaFile *file;
3065 GtkGrid *grid;
3066 GtkStyleContext *style;
3067
3068 GtkWidget *pie_canvas;
3069 GtkWidget *used_canvas;
3070 GtkWidget *used_label;
3071 GtkWidget *free_canvas;
3072 GtkWidget *free_label;
3073 GtkWidget *capacity_label;
3074 GtkWidget *fstype_label;
3075 gchar *capacity;
3076 gchar *used;
3077 gchar *free;
3078 gchar *uri;
3079 gchar *concat;
3080 GFile *location;
3081 GFileInfo *info;
3082
3083 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
3084 capacity = g_format_size_full(window->details->volume_capacity, G_FORMAT_SIZE_IEC_UNITS);
3085 free = g_format_size_full(window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3086 used = g_format_size_full(window->details->volume_capacity - window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3087 }
3088 else {
3089 capacity = g_format_size(window->details->volume_capacity);
3090 free = g_format_size(window->details->volume_free);
3091 used = g_format_size(window->details->volume_capacity - window->details->volume_free);
3092 }
3093
3094 file = get_original_file (window);
3095
3096 uri = caja_file_get_activation_uri (file);
3097
3098 grid = GTK_GRID (gtk_grid_new ())((((GtkGrid*) (void *) ((gtk_grid_new ())))));
3099 gtk_container_set_border_width (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), 5);
3100 gtk_grid_set_column_spacing (GTK_GRID (grid)((((GtkGrid*) (void *) ((grid))))), 5);
3101 style = gtk_widget_get_style_context (GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid))))));
3102
3103 if (!gtk_style_context_lookup_color (style, "chart_rgba_1", &window->details->used_color)) {
3104
3105 window->details->used_color.red = USED_FILL_R0.988235294;
3106 window->details->used_color.green = USED_FILL_G0.91372549;
3107 window->details->used_color.blue = USED_FILL_B0.309803922;
3108 window->details->used_color.alpha = 1;
3109
3110 }
3111
3112
3113 if (!gtk_style_context_lookup_color (style, "chart_rgba_2", &window->details->free_color)) {
3114 window->details->free_color.red = FREE_FILL_R0.447058824;
3115 window->details->free_color.green = FREE_FILL_G0.623529412;
3116 window->details->free_color.blue = FREE_FILL_B0.811764706;
3117 window->details->free_color.alpha = 1;
3118
3119 }
3120
3121 _pie_style_shade (&window->details->used_color, &window->details->used_stroke_color, 0.7);
3122 _pie_style_shade (&window->details->free_color, &window->details->free_stroke_color, 0.7);
3123
3124 pie_canvas = gtk_drawing_area_new ();
3125 gtk_widget_set_size_request (pie_canvas, 200, 200);
3126
3127 used_canvas = gtk_drawing_area_new ();
3128
3129 gtk_widget_set_valign (used_canvas, GTK_ALIGN_CENTER);
3130 gtk_widget_set_halign (used_canvas, GTK_ALIGN_CENTER);
3131
3132 gtk_widget_set_size_request (used_canvas, 20, 20);
3133 /* Translators: "used" refers to the capacity of the filesystem */
3134 concat = g_strconcat (used, " ", _("used")dcgettext (((void*)0), "used", 5), NULL((void*)0));
3135 used_label = gtk_label_new (concat);
3136 g_free (concat);
3137
3138 free_canvas = gtk_drawing_area_new ();
3139
3140 gtk_widget_set_valign (free_canvas, GTK_ALIGN_CENTER);
3141 gtk_widget_set_halign (free_canvas, GTK_ALIGN_CENTER);
3142
3143 gtk_widget_set_size_request (free_canvas, 20, 20);
3144 /* Translators: "free" refers to the capacity of the filesystem */
3145 concat = g_strconcat (free, " ", _("free")dcgettext (((void*)0), "free", 5), NULL((void*)0));
3146 free_label = gtk_label_new (concat);
3147 g_free (concat);
3148
3149 concat = g_strconcat (_("Total capacity:")dcgettext (((void*)0), "Total capacity:", 5), " ", capacity, NULL((void*)0));
3150 capacity_label = gtk_label_new (concat);
3151 g_free (concat);
3152 fstype_label = gtk_label_new (NULL((void*)0));
3153
3154 location = g_file_new_for_uri (uri);
3155 info = g_file_query_filesystem_info (location, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3156 NULL((void*)0), NULL((void*)0));
3157 if (info) {
3158 const char *fs_type;
3159
3160 fs_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type");
3161
3162 if (fs_type != NULL((void*)0)) {
3163 concat = g_strconcat (_("Filesystem type:")dcgettext (((void*)0), "Filesystem type:", 5), " ", fs_type, NULL((void*)0));
3164 gtk_label_set_text (GTK_LABEL (fstype_label)((((GtkLabel*) (void *) ((fstype_label))))), concat);
3165 g_free (concat);
3166 }
3167
3168 g_object_unref (info);
3169 }
3170 g_object_unref (location);
3171
3172 g_free (uri);
3173 g_free (capacity);
3174 g_free (used);
3175 g_free (free);
3176
3177 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), pie_canvas,
3178 "height", 4,
3179 NULL((void*)0));
3180 gtk_grid_attach_next_to (grid, used_canvas, pie_canvas,
3181 GTK_POS_RIGHT, 1, 1);
3182 gtk_grid_attach_next_to (grid, used_label, used_canvas,
3183 GTK_POS_RIGHT, 1, 1);
3184
3185 gtk_grid_attach_next_to (grid, free_canvas, used_canvas,
3186 GTK_POS_BOTTOM, 1, 1);
3187 gtk_grid_attach_next_to (grid, free_label, free_canvas,
3188 GTK_POS_RIGHT, 1, 1);
3189
3190 gtk_grid_attach_next_to (grid, capacity_label, free_canvas,
3191 GTK_POS_BOTTOM, 2, 1);
3192 gtk_grid_attach_next_to (grid, fstype_label, capacity_label,
3193 GTK_POS_BOTTOM, 2, 1);
3194
3195 g_signal_connect (pie_canvas, "draw",g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
3196 G_CALLBACK (paint_pie_chart), window)g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
;
3197 g_signal_connect (used_canvas, "draw",g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
3198 G_CALLBACK (paint_used_legend), window)g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3199 g_signal_connect (free_canvas, "draw",g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
3200 G_CALLBACK (paint_free_legend), window)g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3201
3202 return GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid)))));
3203
3204}
3205
3206static GtkWidget*
3207create_volume_usage_widget (FMPropertiesWindow *window)
3208{
3209 GtkWidget *piewidget;
3210 gchar *uri;
3211 CajaFile *file;
3212 GFile *location;
3213 GFileInfo *info;
3214
3215 file = get_original_file (window);
3216
3217 uri = caja_file_get_activation_uri (file);
3218
3219 location = g_file_new_for_uri (uri);
3220 info = g_file_query_filesystem_info (location, "filesystem::*", NULL((void*)0), NULL((void*)0));
3221
3222 if (info) {
3223 window->details->volume_capacity = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE"filesystem::size");
3224 window->details->volume_free = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
3225
3226 g_object_unref (info);
3227 } else {
3228 window->details->volume_capacity = 0;
3229 window->details->volume_free = 0;
3230 }
3231
3232 g_object_unref (location);
3233
3234 piewidget = create_pie_widget (window);
3235
3236 gtk_widget_show_all (piewidget);
3237
3238 return piewidget;
3239}
3240
3241static void
3242create_basic_page (FMPropertiesWindow *window)
3243{
3244 GtkGrid *grid;
3245 GtkWidget *icon_pixmap_widget;
3246 GtkWidget *hbox, *vbox;
3247
3248 hbox = create_page_with_hbox (window->details->notebook, _("Basic")dcgettext (((void*)0), "Basic", 5));
3249
3250 /* Icon pixmap */
3251
3252 icon_pixmap_widget = create_image_widget (
3253 window, should_show_custom_icon_buttons (window));
3254
3255 gtk_widget_set_halign (icon_pixmap_widget, GTK_ALIGN_END);
3256 gtk_widget_set_valign (icon_pixmap_widget, GTK_ALIGN_START);
3257 gtk_widget_show (icon_pixmap_widget);
3258
3259 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), icon_pixmap_widget, FALSE(0), FALSE(0), 0);
3260
3261 window->details->icon_chooser = NULL((void*)0);
3262
3263 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3264
3265 gtk_widget_show (vbox);
3266 gtk_container_add (GTK_CONTAINER (hbox)((((GtkContainer*) (void *) ((hbox))))), vbox);
3267
3268 grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
3269 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))), GTK_WIDGET (grid)((((GtkWidget*) (void *) ((grid))))), FALSE(0), FALSE(0), 0);
3270 window->details->basic_grid = grid;
3271
3272 /* Name label. The text will be determined in update_name_field */
3273 window->details->name_label = attach_title_field (grid, NULL((void*)0));
3274
3275 /* Name field */
3276 window->details->name_field = NULL((void*)0);
3277 update_name_field (window);
3278
3279 /* Start with name field selected, if it's an entry. */
3280 if (CAJA_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (caja_entry_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; }))))
) {
3281 caja_entry_select_all (CAJA_ENTRY (window->details->name_field)((((CajaEntry*) (void *) ((window->details->name_field)
))))
);
3282 gtk_widget_grab_focus (GTK_WIDGET (window->details->name_field)((((GtkWidget*) (void *) ((window->details->name_field)
))))
);
3283 }
3284
3285 if (fm_ditem_page_should_show (window->details->target_files)) {
3286 GtkSizeGroup *label_size_group;
3287 GtkWidget *box;
3288
3289 label_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
3290 gtk_size_group_add_widget (label_size_group,
3291 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
);
3292 box = fm_ditem_page_make_box (label_size_group,
3293 window->details->target_files);
3294
3295 gtk_grid_attach_next_to (window->details->basic_grid, box,
3296 GTK_WIDGET (window->details->name_label)((((GtkWidget*) (void *) ((window->details->name_label)
))))
,
3297 GTK_POS_BOTTOM, 2, 1);
3298 }
3299
3300 if (should_show_file_type (window)) {
3301 append_title_value_pair (window,
3302 grid, _("Type:")dcgettext (((void*)0), "Type:", 5),
3303 "type",
3304 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3305 FALSE(0));
3306 }
3307
3308 if (should_show_link_target (window)) {
3309 append_title_and_ellipsizing_value (window, grid,
3310 _("Link target:")dcgettext (((void*)0), "Link target:", 5),
3311 "link_target",
3312 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3313 FALSE(0));
3314 }
3315
3316 if (is_multi_file_window (window) ||
3317 caja_file_is_directory (get_target_file (window))) {
3318 append_directory_contents_fields (window, grid);
3319 } else {
3320 append_title_value_pair (window, grid, _("Size:")dcgettext (((void*)0), "Size:", 5),
3321 "size_detail",
3322 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3323 FALSE(0));
3324 append_title_value_pair (window, grid, _("Size on Disk:")dcgettext (((void*)0), "Size on Disk:", 5),
3325 "size_on_disk_detail",
3326 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3327 FALSE(0));
3328 }
3329
3330 append_blank_row (grid);
3331
3332 if (should_show_location_info (window)) {
3333 append_title_and_ellipsizing_value (window, grid, _("Location:")dcgettext (((void*)0), "Location:", 5),
3334 "where",
3335 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3336 TRUE(!(0)));
3337
3338 append_title_and_ellipsizing_value (window, grid,
3339 _("Volume:")dcgettext (((void*)0), "Volume:", 5),
3340 "volume",
3341 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3342 FALSE(0));
3343 }
3344
3345 if (should_show_accessed_date (window)
3346 || should_show_modified_date (window))
3347 {
3348 append_blank_row (grid);
3349 }
3350
3351 if (should_show_accessed_date (window))
3352 {
3353 append_title_value_pair (window, grid, _("Accessed:")dcgettext (((void*)0), "Accessed:", 5),
3354 "date_accessed",
3355 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3356 FALSE(0));
3357 }
3358
3359 if (should_show_modified_date (window))
3360 {
3361 append_title_value_pair (window, grid, _("Modified:")dcgettext (((void*)0), "Modified:", 5),
3362 "date_modified",
3363 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3364 FALSE(0));
3365 append_title_value_pair (window, grid, _("Created:")dcgettext (((void*)0), "Created:", 5),
3366 "date_created",
3367 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3368 FALSE(0));
3369 }
3370
3371 if (should_show_free_space (window)) {
3372 append_blank_row (grid);
3373
3374 append_title_value_pair (window, grid, _("Free space:")dcgettext (((void*)0), "Free space:", 5),
3375 "free_space",
3376 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3377 FALSE(0));
3378 }
3379
3380 if (should_show_volume_usage (window)) {
3381 GtkWidget *volume_usage;
3382
3383 volume_usage = create_volume_usage_widget (window);
3384 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), volume_usage,
3385 "width", 2,
3386 NULL((void*)0));
3387 }
3388}
3389
3390static GHashTable *
3391get_initial_emblems (GList *files)
3392{
3393 GHashTable *ret;
3394 GList *l;
3395
3396 ret = g_hash_table_new_full (g_direct_hash,
3397 g_direct_equal,
3398 NULL((void*)0),
3399 (GDestroyNotify) eel_g_list_free_deep);
3400
3401 for (l = files; l != NULL((void*)0); l = l->next) {
3402 CajaFile *file;
3403 GList *keywords;
3404
3405 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3406
3407 keywords = caja_file_get_keywords (file);
3408 g_hash_table_insert (ret, file, keywords);
3409 }
3410
3411 return ret;
3412}
3413
3414static gboolean
3415files_has_directory (FMPropertiesWindow *window)
3416{
3417 GList *l;
3418
3419 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3420 CajaFile *file;
3421 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3422 if (caja_file_is_directory (file)) {
3423 return TRUE(!(0));
3424 }
3425
3426 }
3427
3428 return FALSE(0);
3429}
3430
3431static gboolean
3432files_has_changable_permissions_directory (FMPropertiesWindow *window)
3433{
3434 GList *l;
3435
3436 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3437 CajaFile *file;
3438 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3439 if (caja_file_is_directory (file) &&
3440 caja_file_can_get_permissions (file) &&
3441 caja_file_can_set_permissions (file)) {
3442 return TRUE(!(0));
3443 }
3444
3445 }
3446
3447 return FALSE(0);
3448}
3449
3450
3451static gboolean
3452files_has_file (FMPropertiesWindow *window)
3453{
3454 GList *l;
3455
3456 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3457 CajaFile *file;
3458 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3459 if (!caja_file_is_directory (file)) {
3460 return TRUE(!(0));
3461 }
3462
3463 }
3464
3465 return FALSE(0);
3466}
3467
3468
3469static void
3470create_emblems_page (FMPropertiesWindow *window)
3471{
3472 GtkWidget *emblems_table, *button, *scroller;
3473 GdkPixbuf *pixbuf;
3474 char *label;
3475 GList *icons, *l;
3476 CajaIconInfo *info;
3477 gint scale;
3478
3479 /* The emblems wrapped table */
3480 scroller = eel_scrolled_wrap_table_new (TRUE(!(0)), GTK_SHADOW_NONE, &emblems_table);
3481
3482 gtk_container_set_border_width (GTK_CONTAINER (emblems_table)((((GtkContainer*) (void *) ((emblems_table))))), 12);
3483
3484 /* stop GTK 3.22 builds from ballooning the properties dialog to full screen height */
3485 gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (scroller)((((GtkScrolledWindow*) (void *) ((scroller))))), 300);
3486
3487 gtk_widget_show (scroller);
3488
3489 gtk_notebook_append_page (window->details->notebook,
3490 scroller, gtk_label_new (_("Emblems")dcgettext (((void*)0), "Emblems", 5)));
3491
3492 icons = caja_emblem_list_available ();
3493 scale = gtk_widget_get_scale_factor (scroller);
3494
3495 window->details->initial_emblems = get_initial_emblems (window->details->original_files);
3496
3497 l = icons;
3498 while (l != NULL((void*)0)) {
3499 char *emblem_name;
3500
3501 emblem_name = l->data;
3502 l = l->next;
3503
3504 if (!caja_emblem_should_show_in_list (emblem_name)) {
3505 continue;
3506 }
3507
3508 info = caja_icon_info_lookup_from_name (emblem_name, CAJA_ICON_SIZE_SMALL32, scale);
3509 pixbuf = caja_icon_info_get_pixbuf_nodefault_at_size (info, CAJA_ICON_SIZE_SMALL32);
3510
3511 if (pixbuf == NULL((void*)0)) {
3512 continue;
3513 }
3514
3515 label = g_strdup (caja_icon_info_get_display_name (info))g_strdup_inline (caja_icon_info_get_display_name (info));
3516 g_object_unref (info);
3517
3518 if (label == NULL((void*)0)) {
3519 label = caja_emblem_get_keyword_from_icon_name (emblem_name);
3520 }
3521
3522 button = eel_labeled_image_check_button_new (label, pixbuf);
3523 eel_labeled_image_set_fixed_image_height (EEL_LABELED_IMAGE (gtk_bin_get_child (GTK_BIN (button)))((((EelLabeledImage*) (void *) ((gtk_bin_get_child (((((GtkBin
*) (void *) ((button)))))))))))
, STANDARD_EMBLEM_HEIGHT52 * scale);
3524 eel_labeled_image_set_spacing (EEL_LABELED_IMAGE (gtk_bin_get_child (GTK_BIN (button)))((((EelLabeledImage*) (void *) ((gtk_bin_get_child (((((GtkBin
*) (void *) ((button)))))))))))
, EMBLEM_LABEL_SPACING2 * scale);
3525
3526 g_free (label);
3527 g_object_unref (pixbuf);
3528
3529 /* Attach parameters and signal handler. */
3530 g_object_set_data_full (G_OBJECT (button)((((GObject*) (void *) ((button))))), "caja_emblem_name",
3531 caja_emblem_get_keyword_from_icon_name (emblem_name), g_free);
3532
3533 window->details->emblem_buttons =
3534 g_list_append (window->details->emblem_buttons,
3535 button);
3536
3537 g_signal_connect_object (button, "toggled",
3538 G_CALLBACK (emblem_button_toggled)((GCallback) (emblem_button_toggled)),
3539 G_OBJECT (window)((((GObject*) (void *) ((window))))),
3540 0);
3541
3542 gtk_container_add (GTK_CONTAINER (emblems_table)((((GtkContainer*) (void *) ((emblems_table))))), button);
3543 }
3544 g_list_free_full (icons, g_free);
3545 gtk_widget_show_all (emblems_table);
3546}
3547
3548static void
3549start_long_operation (FMPropertiesWindow *window)
3550{
3551 if (window->details->long_operation_underway == 0) {
3552 /* start long operation */
3553 GdkDisplay *display;
3554 GdkCursor * cursor;
3555
3556 display = gtk_widget_get_display (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
3557 cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
3558 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))), cursor);
3559 g_object_unref (cursor);
3560 }
3561 window->details->long_operation_underway ++;
3562}
3563
3564static void
3565end_long_operation (FMPropertiesWindow *window)
3566{
3567 if (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))) != NULL((void*)0) &&
3568 window->details->long_operation_underway == 1) {
3569 /* finished !! */
3570 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))), NULL((void*)0));
3571 }
3572 window->details->long_operation_underway--;
3573}
3574
3575static void
3576permission_change_callback (CajaFile *file,
3577 GFile *res_loc,
3578 GError *error,
3579 gpointer callback_data)
3580{
3581 FMPropertiesWindow *window;
3582 g_assert (callback_data != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if (callback_data != ((void*)0)) _g_boolean_var_168 = 1; else
_g_boolean_var_168 = 0; _g_boolean_var_168; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 3582, ((const char*
) (__func__)), "callback_data != NULL"); } while (0)
;
3583
3584 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
3585 end_long_operation (window);
3586
3587 /* Report the error if it's an error. */
3588 fm_report_error_setting_permissions (file, error, NULL((void*)0));
3589
3590 g_object_unref (window);
3591}
3592
3593static void
3594update_permissions (FMPropertiesWindow *window,
3595 guint32 vfs_new_perm,
3596 guint32 vfs_mask,
3597 gboolean is_folder,
3598 gboolean apply_to_both_folder_and_dir,
3599 gboolean use_original)
3600{
3601 GList *l;
3602
3603 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3604 CajaFile *file;
3605 guint32 permissions;
3606
3607 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3608
3609 if (!caja_file_can_get_permissions (file)) {
3610 continue;
3611 }
3612
3613 if (!apply_to_both_folder_and_dir &&
3614 ((caja_file_is_directory (file) && !is_folder) ||
3615 (!caja_file_is_directory (file) && is_folder))) {
3616 continue;
3617 }
3618
3619 permissions = caja_file_get_permissions (file);
3620 if (use_original) {
3621 gpointer ptr;
3622 if (g_hash_table_lookup_extended (window->details->initial_permissions,
3623 file, NULL((void*)0), &ptr)) {
3624 permissions = (permissions & ~vfs_mask) | (GPOINTER_TO_INT (ptr)((gint) (glong) (ptr)) & vfs_mask);
3625 }
3626 } else {
3627 permissions = (permissions & ~vfs_mask) | vfs_new_perm;
3628 }
3629
3630 start_long_operation (window);
3631 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
3632 caja_file_set_permissions
3633 (file, permissions,
3634 permission_change_callback,
3635 window);
3636 }
3637}
3638
3639static gboolean
3640initial_permission_state_consistent (FMPropertiesWindow *window,
3641 guint32 mask,
3642 gboolean is_folder,
3643 gboolean both_folder_and_dir)
3644{
3645 GList *l;
3646 gboolean first;
3647 guint32 first_permissions;
3648
3649 first = TRUE(!(0));
3650 first_permissions = 0;
3651 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3652 CajaFile *file;
3653 guint32 permissions;
3654
3655 file = l->data;
3656
3657 if (!both_folder_and_dir &&
3658 ((caja_file_is_directory (file) && !is_folder) ||
3659 (!caja_file_is_directory (file) && is_folder))) {
3660 continue;
3661 }
3662
3663 permissions = GPOINTER_TO_INT (g_hash_table_lookup (window->details->initial_permissions,((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
3664 file))((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
;
3665
3666 if (first) {
3667 if ((permissions & mask) != mask &&
3668 (permissions & mask) != 0) {
3669 /* Not fully on or off -> inconsistent */
3670 return FALSE(0);
3671 }
3672
3673 first_permissions = permissions;
3674 first = FALSE(0);
3675
3676 } else if ((permissions & mask) != (first_permissions & mask)) {
3677 /* Not same permissions as first -> inconsistent */
3678 return FALSE(0);
3679 }
3680 }
3681 return TRUE(!(0));
3682}
3683
3684static void
3685permission_button_toggled (GtkToggleButton *button,
3686 FMPropertiesWindow *window)
3687{
3688 gboolean is_folder, is_special;
3689 guint32 permission_mask;
3690 gboolean inconsistent;
3691 gboolean on;
3692
3693 permission_mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
3694 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
3695 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
3696 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
3697 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
3698 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
3699
3700 if (gtk_toggle_button_get_active (button)
3701 && !gtk_toggle_button_get_inconsistent (button)) {
3702 /* Go to the initial state unless the initial state was
3703 consistent, or we support recursive apply */
3704 inconsistent = TRUE(!(0));
3705 on = TRUE(!(0));
3706
3707 if (!window->details->has_recursive_apply &&
3708 initial_permission_state_consistent (window, permission_mask, is_folder, is_special)) {
3709 inconsistent = FALSE(0);
3710 on = TRUE(!(0));
3711 }
3712 } else if (gtk_toggle_button_get_inconsistent (button)
3713 && !gtk_toggle_button_get_active (button)) {
3714 inconsistent = FALSE(0);
3715 on = TRUE(!(0));
3716 } else {
3717 inconsistent = FALSE(0);
3718 on = FALSE(0);
3719 }
3720
3721 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3722 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3723 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3724
3725 gtk_toggle_button_set_active (button, on);
3726 gtk_toggle_button_set_inconsistent (button, inconsistent);
3727
3728 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3729 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3730 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3731
3732 update_permissions (window,
3733 on?permission_mask:0,
3734 permission_mask,
3735 is_folder,
3736 is_special,
3737 inconsistent);
3738}
3739
3740static void
3741permission_button_update (FMPropertiesWindow *window,
3742 GtkToggleButton *button)
3743{
3744 GList *l;
3745 gboolean all_set;
3746 gboolean all_unset;
3747 gboolean all_cannot_set;
3748 gboolean is_folder, is_special;
3749 gboolean no_match;
3750 gboolean sensitive;
3751 guint32 button_permission;
3752
3753 if (gtk_toggle_button_get_inconsistent (button) &&
3754 window->details->has_recursive_apply) {
3755 /* Never change from an inconsistent state if we have dirs, even
3756 * if the current state is now consistent, because its a useful
3757 * state for recursive apply.
3758 */
3759 return;
3760 }
3761
3762 button_permission = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
3763 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
3764 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
3765 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
3766 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
3767 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
3768
3769 all_set = TRUE(!(0));
3770 all_unset = TRUE(!(0));
3771 all_cannot_set = TRUE(!(0));
3772 no_match = TRUE(!(0));
3773 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3774 CajaFile *file;
3775 guint32 file_permissions;
3776
3777 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
3778
3779 if (!caja_file_can_get_permissions (file)) {
3780 continue;
3781 }
3782
3783 if (!is_special &&
3784 ((caja_file_is_directory (file) && !is_folder) ||
3785 (!caja_file_is_directory (file) && is_folder))) {
3786 continue;
3787 }
3788
3789 no_match = FALSE(0);
3790
3791 file_permissions = caja_file_get_permissions (file);
3792
3793 if ((file_permissions & button_permission) == button_permission) {
3794 all_unset = FALSE(0);
3795 } else if ((file_permissions & button_permission) == 0) {
3796 all_set = FALSE(0);
3797 } else {
3798 all_unset = FALSE(0);
3799 all_set = FALSE(0);
3800 }
3801
3802 if (caja_file_can_set_permissions (file)) {
3803 all_cannot_set = FALSE(0);
3804 }
3805 }
3806
3807 sensitive = !all_cannot_set;
3808 if (!is_folder) {
3809 /* Don't insitive files when we have recursive apply */
3810 sensitive |= window->details->has_recursive_apply;
3811 }
3812
3813
3814 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3815 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3816 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((button
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3817
3818 gtk_toggle_button_set_active (button, !all_unset);
3819 /* if actually inconsistent, or default value for file buttons
3820 if no files are selected. (useful for recursive apply) */
3821 gtk_toggle_button_set_inconsistent (button,
3822 (!all_unset && !all_set) ||
3823 (!is_folder && no_match));
3824 gtk_widget_set_sensitive (GTK_WIDGET (button)((((GtkWidget*) (void *) ((button))))), sensitive);
3825
3826 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3827 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3828 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
button)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3829}
3830
3831static void
3832set_up_permissions_checkbox (FMPropertiesWindow *window,
3833 GtkWidget *check_button,
3834 guint32 permission,
3835 gboolean is_folder)
3836{
3837 /* Load up the check_button with data we'll need when updating its state. */
3838 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "permission",
3839 GINT_TO_POINTER (permission)((gpointer) (glong) (permission)));
3840 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "properties_window",
3841 window);
3842 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "is-folder",
3843 GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
3844
3845 window->details->permission_buttons =
3846 g_list_prepend (window->details->permission_buttons,
3847 check_button);
3848
3849 g_signal_connect_object (check_button, "toggled",
3850 G_CALLBACK (permission_button_toggled)((GCallback) (permission_button_toggled)),
3851 window,
3852 0);
3853}
3854
3855static GtkWidget *
3856add_permissions_checkbox_with_label (FMPropertiesWindow *window,
3857 GtkGrid *grid,
3858 GtkWidget *sibling,
3859 const char *label,
3860 guint32 permission_to_check,
3861 GtkLabel *label_for,
3862 gboolean is_folder)
3863{
3864 GtkWidget *check_button;
3865 gboolean a11y_enabled;
3866
3867 check_button = gtk_check_button_new_with_mnemonic (label);
3868 gtk_widget_show (check_button);
3869 if (sibling) {
3870 gtk_grid_attach_next_to (grid, check_button, sibling,
3871 GTK_POS_RIGHT, 1, 1);
3872 } else {
3873 gtk_container_add (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), check_button);
3874 }
3875
3876 set_up_permissions_checkbox (window,
3877 check_button,
3878 permission_to_check,
3879 is_folder);
3880
3881 a11y_enabled = GTK_IS_ACCESSIBLE (gtk_widget_get_accessible (check_button))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(gtk_widget_get_accessible (check_button))); GType __t = ((gtk_accessible_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; }))))
;
3882 if (a11y_enabled && label_for != NULL((void*)0)) {
3883 eel_accessibility_set_up_label_widget_relation (GTK_WIDGET (label_for)((((GtkWidget*) (void *) ((label_for))))),
3884 check_button);
3885 }
3886
3887 return check_button;
3888}
3889
3890static GtkWidget *
3891add_permissions_checkbox (FMPropertiesWindow *window,
3892 GtkGrid *grid,
3893 GtkWidget *sibling,
3894 CheckboxType type,
3895 guint32 permission_to_check,
3896 GtkLabel *label_for,
3897 gboolean is_folder)
3898{
3899 const gchar *label;
3900
3901 if (type == PERMISSIONS_CHECKBOXES_READ) {
3902 label = _("_Read")dcgettext (((void*)0), "_Read", 5);
3903 } else if (type == PERMISSIONS_CHECKBOXES_WRITE) {
3904 label = _("_Write")dcgettext (((void*)0), "_Write", 5);
3905 } else {
3906 label = _("E_xecute")dcgettext (((void*)0), "E_xecute", 5);
3907 }
3908
3909 return add_permissions_checkbox_with_label (window, grid,
3910 sibling,
3911 label,
3912 permission_to_check,
3913 label_for,
3914 is_folder);
3915}
3916
3917enum {
3918 UNIX_PERM_SUID = S_ISUID04000,
3919 UNIX_PERM_SGID = S_ISGID02000,
3920 UNIX_PERM_STICKY = 01000, /* S_ISVTX not defined on all systems */
3921 UNIX_PERM_USER_READ = S_IRUSR0400,
3922 UNIX_PERM_USER_WRITE = S_IWUSR0200,
3923 UNIX_PERM_USER_EXEC = S_IXUSR0100,
3924 UNIX_PERM_USER_ALL = S_IRUSR0400 | S_IWUSR0200 | S_IXUSR0100,
3925 UNIX_PERM_GROUP_READ = S_IRGRP(0400 >> 3),
3926 UNIX_PERM_GROUP_WRITE = S_IWGRP(0200 >> 3),
3927 UNIX_PERM_GROUP_EXEC = S_IXGRP(0100 >> 3),
3928 UNIX_PERM_GROUP_ALL = S_IRGRP(0400 >> 3) | S_IWGRP(0200 >> 3) | S_IXGRP(0100 >> 3),
3929 UNIX_PERM_OTHER_READ = S_IROTH((0400 >> 3) >> 3),
3930 UNIX_PERM_OTHER_WRITE = S_IWOTH((0200 >> 3) >> 3),
3931 UNIX_PERM_OTHER_EXEC = S_IXOTH((0100 >> 3) >> 3),
3932 UNIX_PERM_OTHER_ALL = S_IROTH((0400 >> 3) >> 3) | S_IWOTH((0200 >> 3) >> 3) | S_IXOTH((0100 >> 3) >> 3)
3933};
3934
3935typedef enum {
3936 PERMISSION_READ = (1<<0),
3937 PERMISSION_WRITE = (1<<1),
3938 PERMISSION_EXEC = (1<<2)
3939} PermissionValue;
3940
3941typedef enum {
3942 PERMISSION_USER,
3943 PERMISSION_GROUP,
3944 PERMISSION_OTHER
3945} PermissionType;
3946
3947static guint32 vfs_perms[3][3] = {
3948 {UNIX_PERM_USER_READ, UNIX_PERM_USER_WRITE, UNIX_PERM_USER_EXEC},
3949 {UNIX_PERM_GROUP_READ, UNIX_PERM_GROUP_WRITE, UNIX_PERM_GROUP_EXEC},
3950 {UNIX_PERM_OTHER_READ, UNIX_PERM_OTHER_WRITE, UNIX_PERM_OTHER_EXEC},
3951};
3952
3953static guint32
3954permission_to_vfs (PermissionType type, PermissionValue perm)
3955{
3956 guint32 vfs_perm;
3957 g_assert (type >= 0 && type < 3)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if (type >= 0 && type < 3) _g_boolean_var_169
= 1; else _g_boolean_var_169 = 0; _g_boolean_var_169; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 3957, ((const char*) (__func__)), "type >= 0 && type < 3"
); } while (0)
;
3958
3959 vfs_perm = 0;
3960 if (perm & PERMISSION_READ) {
3961 vfs_perm |= vfs_perms[type][0];
3962 }
3963 if (perm & PERMISSION_WRITE) {
3964 vfs_perm |= vfs_perms[type][1];
3965 }
3966 if (perm & PERMISSION_EXEC) {
3967 vfs_perm |= vfs_perms[type][2];
3968 }
3969
3970 return vfs_perm;
3971}
3972
3973
3974static PermissionValue
3975permission_from_vfs (PermissionType type, guint32 vfs_perm)
3976{
3977 PermissionValue perm;
3978 g_assert (type >= 0 && type < 3)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if (type >= 0 && type < 3) _g_boolean_var_170
= 1; else _g_boolean_var_170 = 0; _g_boolean_var_170; }), 1)
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 3978, ((const char*) (__func__)), "type >= 0 && type < 3"
); } while (0)
;
3979
3980 perm = 0;
3981 if (vfs_perm & vfs_perms[type][0]) {
3982 perm |= PERMISSION_READ;
3983 }
3984 if (vfs_perm & vfs_perms[type][1]) {
3985 perm |= PERMISSION_WRITE;
3986 }
3987 if (vfs_perm & vfs_perms[type][2]) {
3988 perm |= PERMISSION_EXEC;
3989 }
3990
3991 return perm;
3992}
3993
3994static void
3995permission_combo_changed (GtkWidget *combo, FMPropertiesWindow *window)
3996{
3997 GtkTreeIter iter;
3998 GtkTreeModel *model;
3999 gboolean is_folder, use_original;
4000 PermissionType type;
4001 int new_perm, mask;
4002 guint32 vfs_new_perm, vfs_mask;
4003
4004 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4005 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4006
4007 if (is_folder) {
4008 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4009 } else {
4010 mask = PERMISSION_READ|PERMISSION_WRITE;
4011 }
4012
4013 vfs_mask = permission_to_vfs (type, mask);
4014
4015 model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))));
4016
4017 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4018 return;
4019 }
4020 gtk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
4021 vfs_new_perm = permission_to_vfs (type, new_perm);
4022
4023 update_permissions (window, vfs_new_perm, vfs_mask,
4024 is_folder, FALSE(0), use_original);
4025}
4026
4027static void
4028permission_combo_add_multiple_choice (GtkComboBox *combo, GtkTreeIter *iter)
4029{
4030 GtkTreeModel *model;
4031 GtkListStore *store;
4032 gboolean found;
4033
4034 model = gtk_combo_box_get_model (combo);
4035 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
4036
4037 found = FALSE(0);
4038 gtk_tree_model_get_iter_first (model, iter);
4039 do {
4040 gboolean multi;
4041 gtk_tree_model_get (model, iter, 2, &multi, -1);
4042
4043 if (multi) {
4044 found = TRUE(!(0));
4045 break;
4046 }
4047 } while (gtk_tree_model_iter_next (model, iter));
4048
4049 if (!found) {
4050 gtk_list_store_append (store, iter);
4051 gtk_list_store_set (store, iter, 0, "---", 1, 0, 2, TRUE(!(0)), -1);
4052 }
4053}
4054
4055static void
4056permission_combo_update (FMPropertiesWindow *window,
4057 GtkComboBox *combo)
4058{
4059 PermissionType type;
4060 PermissionValue perm, all_dir_perm, all_file_perm, all_perm;
4061 gboolean is_folder, no_files, no_dirs, all_file_same, all_dir_same, all_same;
4062 gboolean all_dir_cannot_set, all_file_cannot_set, sensitive;
4063 GtkTreeIter iter;
4064 int mask;
4065 GtkTreeModel *model;
4066 GtkListStore *store;
4067 GList *l;
4068 gboolean is_multi;
4069
4070 model = gtk_combo_box_get_model (combo);
4071
4072 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4073 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4074
4075 is_multi = FALSE(0);
4076 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4077 gtk_tree_model_get (model, &iter, 2, &is_multi, -1);
4078 }
4079
4080 if (is_multi && window->details->has_recursive_apply) {
4081 /* Never change from an inconsistent state if we have dirs, even
4082 * if the current state is now consistent, because its a useful
4083 * state for recursive apply.
4084 */
4085 return;
4086 }
4087
4088 no_files = TRUE(!(0));
4089 no_dirs = TRUE(!(0));
4090 all_dir_same = TRUE(!(0));
4091 all_file_same = TRUE(!(0));
4092 all_dir_perm = 0;
4093 all_file_perm = 0;
4094 all_dir_cannot_set = TRUE(!(0));
4095 all_file_cannot_set = TRUE(!(0));
4096
4097 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4098 CajaFile *file;
4099 guint32 file_permissions;
4100
4101 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4102
4103 if (!caja_file_can_get_permissions (file)) {
4104 continue;
4105 }
4106
4107 if (caja_file_is_directory (file)) {
4108 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4109 } else {
4110 mask = PERMISSION_READ|PERMISSION_WRITE;
4111 }
4112
4113 file_permissions = caja_file_get_permissions (file);
4114
4115 perm = permission_from_vfs (type, file_permissions) & mask;
4116
4117 if (caja_file_is_directory (file)) {
4118 if (no_dirs) {
4119 all_dir_perm = perm;
4120 no_dirs = FALSE(0);
4121 } else if (perm != all_dir_perm) {
4122 all_dir_same = FALSE(0);
4123 }
4124
4125 if (caja_file_can_set_permissions (file)) {
4126 all_dir_cannot_set = FALSE(0);
4127 }
4128 } else {
4129 if (no_files) {
4130 all_file_perm = perm;
4131 no_files = FALSE(0);
4132 } else if (perm != all_file_perm) {
4133 all_file_same = FALSE(0);
4134 }
4135
4136 if (caja_file_can_set_permissions (file)) {
4137 all_file_cannot_set = FALSE(0);
4138 }
4139 }
4140 }
4141
4142 if (is_folder) {
4143 all_same = all_dir_same;
4144 all_perm = all_dir_perm;
4145 } else {
4146 all_same = all_file_same && !no_files;
4147 all_perm = all_file_perm;
4148 }
4149
4150 store = GTK_LIST_STORE (model)((((GtkListStore*) (void *) ((model)))));
4151 if (all_same) {
4152 gboolean found;
4153
4154 found = FALSE(0);
4155 gtk_tree_model_get_iter_first (model, &iter);
4156 do {
4157 int current_perm;
4158 gtk_tree_model_get (model, &iter, 1, &current_perm, -1);
4159
4160 if (current_perm == all_perm) {
4161 found = TRUE(!(0));
4162 break;
4163 }
4164 } while (gtk_tree_model_iter_next (model, &iter));
4165
4166 if (!found) {
4167 GString *str;
4168 str = g_string_new ("");
4169
4170 if (!(all_perm & PERMISSION_READ)) {
4171 /* Translators: this gets concatenated to "no read",
4172 * "no access", etc. (see following strings)
4173 */
4174 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_171; if (__val != ((void
*)0)) _g_boolean_var_171 = 1; else _g_boolean_var_171 = 0; _g_boolean_var_171
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4175 }
4176 if (is_folder) {
4177 g_string_append (str, _("list"))(__builtin_constant_p (dcgettext (((void*)0), "list", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "list"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_172; if (__val != ((void
*)0)) _g_boolean_var_172 = 1; else _g_boolean_var_172 = 0; _g_boolean_var_172
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "list", 5), (gssize) -1))
;
4178 } else {
4179 g_string_append (str, _("read"))(__builtin_constant_p (dcgettext (((void*)0), "read", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "read"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_173; if (__val != ((void
*)0)) _g_boolean_var_173 = 1; else _g_boolean_var_173 = 0; _g_boolean_var_173
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "read", 5), (gssize) -1))
;
4180 }
4181
4182 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_174; if (__val != ((void
*)0)) _g_boolean_var_174 = 1; else _g_boolean_var_174 = 0; _g_boolean_var_174
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
4183
4184 if (!(all_perm & PERMISSION_WRITE)) {
4185 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_175; if (__val != ((void
*)0)) _g_boolean_var_175 = 1; else _g_boolean_var_175 = 0; _g_boolean_var_175
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4186 }
4187 if (is_folder) {
4188 g_string_append (str, _("create/delete"))(__builtin_constant_p (dcgettext (((void*)0), "create/delete"
, 5)) ? __extension__ ({ const char * const __val = (dcgettext
(((void*)0), "create/delete", 5)); g_string_append_len_inline
(str, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if (__val != ((void*)0)) _g_boolean_var_176 = 1; else _g_boolean_var_176
= 0; _g_boolean_var_176; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, dcgettext (((void*)0), "create/delete", 5), (gssize) -
1))
;
4189 } else {
4190 g_string_append (str, _("write"))(__builtin_constant_p (dcgettext (((void*)0), "write", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "write"
, 5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_177; if (__val != ((void
*)0)) _g_boolean_var_177 = 1; else _g_boolean_var_177 = 0; _g_boolean_var_177
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "write", 5), (gssize) -1))
;
4191 }
4192
4193 if (is_folder) {
4194 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_178; if (__val != ((void
*)0)) _g_boolean_var_178 = 1; else _g_boolean_var_178 = 0; _g_boolean_var_178
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, ", ", (gssize) -1
))
;
4195
4196 if (!(all_perm & PERMISSION_EXEC)) {
4197 g_string_append (str, _("no "))(__builtin_constant_p (dcgettext (((void*)0), "no ", 5)) ? __extension__
({ const char * const __val = (dcgettext (((void*)0), "no ",
5)); g_string_append_len_inline (str, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_179; if (__val != ((void
*)0)) _g_boolean_var_179 = 1; else _g_boolean_var_179 = 0; _g_boolean_var_179
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (str, dcgettext (((void
*)0), "no ", 5), (gssize) -1))
;
4198 }
4199 g_string_append (str, _("access"))(__builtin_constant_p (dcgettext (((void*)0), "access", 5)) ?
__extension__ ({ const char * const __val = (dcgettext (((void
*)0), "access", 5)); g_string_append_len_inline (str, __val, (
__builtin_expect (__extension__ ({ int _g_boolean_var_180; if
(__val != ((void*)0)) _g_boolean_var_180 = 1; else _g_boolean_var_180
= 0; _g_boolean_var_180; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, dcgettext (((void*)0), "access", 5), (gssize) -1))
;
4200 }
4201
4202 gtk_list_store_append (store, &iter);
4203 gtk_list_store_set (store, &iter,
4204 0, str->str,
4205 1, all_perm, -1);
4206
4207 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
4208 }
4209 } else {
4210 permission_combo_add_multiple_choice (combo, &iter);
4211 }
4212
4213 g_signal_handlers_block_by_func (G_OBJECT (combo),g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4214 G_CALLBACK (permission_combo_changed),g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4215 window)g_signal_handlers_block_matched ((((((GObject*) (void *) ((combo
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4216
4217 gtk_combo_box_set_active_iter (combo, &iter);
4218
4219 /* Also enable if no files found (for recursive
4220 file changes when only selecting folders) */
4221 if (is_folder) {
4222 sensitive = !all_dir_cannot_set;
4223 } else {
4224 sensitive = !all_file_cannot_set ||
4225 window->details->has_recursive_apply;
4226 }
4227 gtk_widget_set_sensitive (GTK_WIDGET (combo)((((GtkWidget*) (void *) ((combo))))), sensitive);
4228
4229 g_signal_handlers_unblock_by_func (G_OBJECT (combo),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4230 G_CALLBACK (permission_combo_changed),g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4231 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) ((
combo)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4232
4233}
4234
4235static void
4236add_permissions_combo_box (FMPropertiesWindow *window, GtkGrid *grid,
4237 PermissionType type, gboolean is_folder,
4238 gboolean short_label)
4239{
4240 GtkWidget *combo;
4241 GtkLabel *label;
4242 GtkListStore *store;
4243 GtkCellRenderer *cell;
4244 GtkTreeIter iter;
4245
4246 if (short_label) {
4247 label = attach_title_field (grid, _("Access:")dcgettext (((void*)0), "Access:", 5));
4248 } else if (is_folder) {
4249 label = attach_title_field (grid, _("Folder access:")dcgettext (((void*)0), "Folder access:", 5));
4250 } else {
4251 label = attach_title_field (grid, _("File access:")dcgettext (((void*)0), "File access:", 5));
4252 }
4253
4254 store = gtk_list_store_new (3, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_INT((GType) ((6) << (2))), G_TYPE_BOOLEAN((GType) ((5) << (2))));
4255 combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))));
4256
4257 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) ((combo))))), "is-folder", GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
4258 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) ((combo))))), "permission-type", GINT_TO_POINTER (type)((gpointer) (glong) (type)));
4259
4260 if (is_folder) {
4261 if (type != PERMISSION_USER) {
4262 gtk_list_store_append (store, &iter);
4263 /* Translators: this is referred to the permissions
4264 * the user has in a directory.
4265 */
4266 gtk_list_store_set (store, &iter, 0, _("None")dcgettext (((void*)0), "None", 5), 1, 0, -1);
4267 }
4268 gtk_list_store_append (store, &iter);
4269 gtk_list_store_set (store, &iter, 0, _("List files only")dcgettext (((void*)0), "List files only", 5), 1, PERMISSION_READ, -1);
4270 gtk_list_store_append (store, &iter);
4271 gtk_list_store_set (store, &iter, 0, _("Access files")dcgettext (((void*)0), "Access files", 5), 1, PERMISSION_READ|PERMISSION_EXEC, -1);
4272 gtk_list_store_append (store, &iter);
4273 gtk_list_store_set (store, &iter, 0, _("Create and delete files")dcgettext (((void*)0), "Create and delete files", 5), 1, PERMISSION_READ|PERMISSION_EXEC|PERMISSION_WRITE, -1);
4274 } else {
4275 if (type != PERMISSION_USER) {
4276 gtk_list_store_append (store, &iter);
4277 gtk_list_store_set (store, &iter, 0, _("None")dcgettext (((void*)0), "None", 5), 1, 0, -1);
4278 }
4279 gtk_list_store_append (store, &iter);
4280 gtk_list_store_set (store, &iter, 0, _("Read-only")dcgettext (((void*)0), "Read-only", 5), 1, PERMISSION_READ, -1);
4281 gtk_list_store_append (store, &iter);
4282 gtk_list_store_set (store, &iter, 0, _("Read and write")dcgettext (((void*)0), "Read and write", 5), 1, PERMISSION_READ|PERMISSION_WRITE, -1);
4283 }
4284 if (window->details->has_recursive_apply) {
4285 permission_combo_add_multiple_choice (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
4286 }
4287
4288 g_object_unref (store);
4289
4290 window->details->permission_combos =
4291 g_list_prepend (window->details->permission_combos,
4292 combo);
4293
4294 g_signal_connect (combo, "changed", G_CALLBACK (permission_combo_changed), window)g_signal_connect_data ((combo), ("changed"), (((GCallback) (permission_combo_changed
))), (window), ((void*)0), (GConnectFlags) 0)
;
4295
4296 cell = gtk_cell_renderer_text_new ();
4297 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell, TRUE(!(0)));
4298 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo)((((GtkCellLayout*) (void *) ((combo))))), cell,
4299 "text", 0,
4300 NULL((void*)0));
4301
4302 gtk_label_set_mnemonic_widget (label, combo);
4303 gtk_widget_show (combo);
4304
4305 gtk_grid_attach_next_to (grid, combo, GTK_WIDGET (label)((((GtkWidget*) (void *) ((label))))),
4306 GTK_POS_RIGHT, 1, 1);
4307}
4308
4309
4310static GtkWidget *
4311append_special_execution_checkbox (FMPropertiesWindow *window,
4312 GtkGrid *grid,
4313 GtkWidget *sibling,
4314 const char *label_text,
4315 guint32 permission_to_check)
4316{
4317 GtkWidget *check_button;
4318
4319 check_button = gtk_check_button_new_with_mnemonic (label_text);
4320 gtk_widget_show (check_button);
4321
4322 if (sibling != NULL((void*)0)) {
4323 gtk_grid_attach_next_to (grid, check_button, sibling,
4324 GTK_POS_RIGHT, 1, 1);
4325 } else {
4326 gtk_container_add_with_properties (GTK_CONTAINER (grid)((((GtkContainer*) (void *) ((grid))))), check_button,
4327 "left-attach", 1,
4328 NULL((void*)0));
4329 }
4330
4331 set_up_permissions_checkbox (window,
4332 check_button,
4333 permission_to_check,
4334 FALSE(0));
4335 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) ((check_button))))), "is-special",
4336 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4337
4338 return check_button;
4339}
4340
4341static void
4342append_special_execution_flags (FMPropertiesWindow *window, GtkGrid *grid)
4343{
4344 GtkWidget *title;
4345
4346 append_blank_slim_row (grid);
4347 title = GTK_WIDGET (attach_title_field (grid, _("Special flags:")))((((GtkWidget*) (void *) ((attach_title_field (grid, dcgettext
(((void*)0), "Special flags:", 5)))))))
;
4348
4349 append_special_execution_checkbox (window, grid, title, _("Set _user ID")dcgettext (((void*)0), "Set _user ID", 5), UNIX_PERM_SUID);
4350 append_special_execution_checkbox (window, grid, NULL((void*)0), _("Set gro_up ID")dcgettext (((void*)0), "Set gro_up ID", 5), UNIX_PERM_SGID);
4351 append_special_execution_checkbox (window, grid, NULL((void*)0), _("_Sticky")dcgettext (((void*)0), "_Sticky", 5), UNIX_PERM_STICKY);
4352}
4353
4354static gboolean
4355all_can_get_permissions (GList *file_list)
4356{
4357 GList *l;
4358 for (l = file_list; l != NULL((void*)0); l = l->next) {
4359 CajaFile *file;
4360
4361 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4362
4363 if (!caja_file_can_get_permissions (file)) {
4364 return FALSE(0);
4365 }
4366 }
4367
4368 return TRUE(!(0));
4369}
4370
4371static gboolean
4372all_can_set_permissions (GList *file_list)
4373{
4374 GList *l;
4375 for (l = file_list; l != NULL((void*)0); l = l->next) {
4376 CajaFile *file;
4377
4378 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4379
4380 if (!caja_file_can_set_permissions (file)) {
4381 return FALSE(0);
4382 }
4383 }
4384
4385 return TRUE(!(0));
4386}
4387
4388static GHashTable *
4389get_initial_permissions (GList *file_list)
4390{
4391 GHashTable *ret;
4392 GList *l;
4393
4394 ret = g_hash_table_new (g_direct_hash,
4395 g_direct_equal);
4396
4397 for (l = file_list; l != NULL((void*)0); l = l->next) {
4398 guint32 permissions;
4399 CajaFile *file;
4400
4401 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4402
4403 permissions = caja_file_get_permissions (file);
4404 g_hash_table_insert (ret, file,
4405 GINT_TO_POINTER (permissions)((gpointer) (glong) (permissions)));
4406 }
4407
4408 return ret;
4409}
4410
4411static void
4412create_simple_permissions (FMPropertiesWindow *window, GtkGrid *page_grid)
4413{
4414 gboolean has_file, has_directory;
4415 GtkLabel *group_label;
4416 GtkLabel *owner_label;
4417 GtkLabel *execute_label;
4418 GtkWidget *value;
4419
4420 has_file = files_has_file (window);
4421 has_directory = files_has_directory (window);
4422
4423 if (!is_multi_file_window (window) && caja_file_can_set_owner (get_target_file (window))) {
4424 GtkComboBox *owner_combo_box;
4425
4426 owner_label = attach_title_field (page_grid, _("_Owner:")dcgettext (((void*)0), "_Owner:", 5));
4427 /* Combo box in this case. */
4428 owner_combo_box = attach_owner_combo_box (page_grid,
4429 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4430 get_target_file (window));
4431 gtk_label_set_mnemonic_widget (owner_label,
4432 GTK_WIDGET (owner_combo_box)((((GtkWidget*) (void *) ((owner_combo_box))))));
4433 } else {
4434 owner_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4435 /* Static text in this case. */
4436 value = attach_value_field (window,
4437 page_grid, GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4438 "owner",
4439 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4440 FALSE(0));
4441 gtk_label_set_mnemonic_widget (owner_label, value);
4442 }
4443
4444 if (has_directory) {
4445 add_permissions_combo_box (window, page_grid,
4446 PERMISSION_USER, TRUE(!(0)), FALSE(0));
4447 }
4448 if (has_file || window->details->has_recursive_apply) {
4449 add_permissions_combo_box (window, page_grid,
4450 PERMISSION_USER, FALSE(0), !has_directory);
4451 }
4452
4453 append_blank_slim_row (page_grid);
4454
4455 if (!is_multi_file_window (window) && caja_file_can_set_group (get_target_file (window))) {
4456 GtkComboBox *group_combo_box;
4457
4458 group_label = attach_title_field (page_grid, _("_Group:")dcgettext (((void*)0), "_Group:", 5));
4459
4460 /* Combo box in this case. */
4461 group_combo_box = attach_group_combo_box (page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4462 get_target_file (window));
4463 gtk_label_set_mnemonic_widget (group_label,
4464 GTK_WIDGET (group_combo_box)((((GtkWidget*) (void *) ((group_combo_box))))));
4465 } else {
4466 group_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4467
4468 /* Static text in this case. */
4469 value = attach_value_field (window, page_grid,
4470 GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4471 "group",
4472 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4473 FALSE(0));
4474 gtk_label_set_mnemonic_widget (group_label, value);
4475 }
4476
4477 if (has_directory) {
4478 add_permissions_combo_box (window, page_grid,
4479 PERMISSION_GROUP, TRUE(!(0)),
4480 FALSE(0));
4481 }
4482 if (has_file || window->details->has_recursive_apply) {
4483 add_permissions_combo_box (window, page_grid,
4484 PERMISSION_GROUP, FALSE(0),
4485 !has_directory);
4486 }
4487
4488 append_blank_slim_row (page_grid);
4489
4490 group_label = attach_title_field (page_grid, _("Others")dcgettext (((void*)0), "Others", 5));
4491
4492 if (has_directory) {
4493 add_permissions_combo_box (window, page_grid,
4494 PERMISSION_OTHER, TRUE(!(0)),
4495 FALSE(0));
4496 }
4497 if (has_file || window->details->has_recursive_apply) {
4498 add_permissions_combo_box (window, page_grid,
4499 PERMISSION_OTHER, FALSE(0),
4500 !has_directory);
4501 }
4502
4503 append_blank_slim_row (page_grid);
4504
4505 execute_label = attach_title_field (page_grid, _("Execute:")dcgettext (((void*)0), "Execute:", 5));
4506 add_permissions_checkbox_with_label (window, page_grid,
4507 GTK_WIDGET (execute_label)((((GtkWidget*) (void *) ((execute_label))))),
4508 _("Allow _executing file as program")dcgettext (((void*)0), "Allow _executing file as program", 5),
4509 UNIX_PERM_USER_EXEC|UNIX_PERM_GROUP_EXEC|UNIX_PERM_OTHER_EXEC,
4510 execute_label, FALSE(0));
4511}
4512
4513static void
4514create_permission_checkboxes (FMPropertiesWindow *window,
4515 GtkGrid *page_grid,
4516 gboolean is_folder)
4517{
4518 GtkLabel *owner_perm_label;
4519 GtkLabel *group_perm_label;
4520 GtkLabel *other_perm_label;
4521 GtkGrid *check_button_grid;
4522 GtkWidget *w;
4523
4524 owner_perm_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4525 group_perm_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4526 other_perm_label = attach_title_field (page_grid, _("Others:")dcgettext (((void*)0), "Others:", 5));
4527
4528 check_button_grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
4529 gtk_widget_show (GTK_WIDGET (check_button_grid)((((GtkWidget*) (void *) ((check_button_grid))))));
4530
4531 gtk_grid_attach_next_to (page_grid, GTK_WIDGET (check_button_grid)((((GtkWidget*) (void *) ((check_button_grid))))),
4532 GTK_WIDGET (owner_perm_label)((((GtkWidget*) (void *) ((owner_perm_label))))),
4533 GTK_POS_RIGHT, 1, 3);
4534
4535 w = add_permissions_checkbox (window,
4536 check_button_grid,
4537 NULL((void*)0),
4538 PERMISSIONS_CHECKBOXES_READ,
4539 UNIX_PERM_USER_READ,
4540 owner_perm_label,
4541 is_folder);
4542
4543 w = add_permissions_checkbox (window,
4544 check_button_grid,
4545 w,
4546 PERMISSIONS_CHECKBOXES_WRITE,
4547 UNIX_PERM_USER_WRITE,
4548 owner_perm_label,
4549 is_folder);
4550
4551 w = add_permissions_checkbox (window,
4552 check_button_grid,
4553 w,
4554 PERMISSIONS_CHECKBOXES_EXECUTE,
4555 UNIX_PERM_USER_EXEC,
4556 owner_perm_label,
4557 is_folder);
4558
4559 w = add_permissions_checkbox (window,
4560 check_button_grid,
4561 NULL((void*)0),
4562 PERMISSIONS_CHECKBOXES_READ,
4563 UNIX_PERM_GROUP_READ,
4564 group_perm_label,
4565 is_folder);
4566
4567 w = add_permissions_checkbox (window,
4568 check_button_grid,
4569 w,
4570 PERMISSIONS_CHECKBOXES_WRITE,
4571 UNIX_PERM_GROUP_WRITE,
4572 group_perm_label,
4573 is_folder);
4574
4575 w = add_permissions_checkbox (window,
4576 check_button_grid,
4577 w,
4578 PERMISSIONS_CHECKBOXES_EXECUTE,
4579 UNIX_PERM_GROUP_EXEC,
4580 group_perm_label,
4581 is_folder);
4582
4583 w = add_permissions_checkbox (window,
4584 check_button_grid,
4585 NULL((void*)0),
4586 PERMISSIONS_CHECKBOXES_READ,
4587 UNIX_PERM_OTHER_READ,
4588 other_perm_label,
4589 is_folder);
4590
4591 w = add_permissions_checkbox (window,
4592 check_button_grid,
4593 w,
4594 PERMISSIONS_CHECKBOXES_WRITE,
4595 UNIX_PERM_OTHER_WRITE,
4596 other_perm_label,
4597 is_folder);
4598
4599 add_permissions_checkbox (window,
4600 check_button_grid,
4601 w,
4602 PERMISSIONS_CHECKBOXES_EXECUTE,
4603 UNIX_PERM_OTHER_EXEC,
4604 other_perm_label,
4605 is_folder);
4606}
4607
4608static void
4609create_advanced_permissions (FMPropertiesWindow *window, GtkGrid *page_grid)
4610{
4611 GtkLabel *group_label;
4612 GtkLabel *owner_label;
4613 gboolean has_directory, has_file;
4614
4615 if (!is_multi_file_window (window) && caja_file_can_set_owner (get_target_file (window))) {
4616 GtkComboBox *owner_combo_box;
4617
4618 owner_label = attach_title_field (page_grid, _("_Owner:")dcgettext (((void*)0), "_Owner:", 5));
4619 /* Combo box in this case. */
4620 owner_combo_box = attach_owner_combo_box (page_grid,
4621 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4622 get_target_file (window));
4623 gtk_label_set_mnemonic_widget (owner_label,
4624 GTK_WIDGET (owner_combo_box)((((GtkWidget*) (void *) ((owner_combo_box))))));
4625 } else {
4626 GtkWidget *value;
4627 owner_label = attach_title_field (page_grid, _("Owner:")dcgettext (((void*)0), "Owner:", 5));
4628
4629 /* Static text in this case. */
4630 value = attach_value_field (window,
4631 page_grid,
4632 GTK_WIDGET (owner_label)((((GtkWidget*) (void *) ((owner_label))))),
4633 "owner",
4634 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4635 FALSE(0));
4636 gtk_label_set_mnemonic_widget (owner_label, value);
4637 }
4638
4639 if (!is_multi_file_window (window) && caja_file_can_set_group (get_target_file (window))) {
4640 GtkComboBox *group_combo_box;
4641
4642 group_label = attach_title_field (page_grid, _("_Group:")dcgettext (((void*)0), "_Group:", 5));
4643
4644 /* Combo box in this case. */
4645 group_combo_box = attach_group_combo_box (page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4646 get_target_file (window));
4647 gtk_label_set_mnemonic_widget (group_label,
4648 GTK_WIDGET (group_combo_box)((((GtkWidget*) (void *) ((group_combo_box))))));
4649 } else {
4650 group_label = attach_title_field (page_grid, _("Group:")dcgettext (((void*)0), "Group:", 5));
4651
4652 /* Static text in this case. */
4653 attach_value_field (window, page_grid, GTK_WIDGET (group_label)((((GtkWidget*) (void *) ((group_label))))),
4654 "group",
4655 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4656 FALSE(0));
4657 }
4658
4659 append_blank_slim_row (page_grid);
4660
4661 has_directory = files_has_directory (window);
4662 has_file = files_has_file (window);
4663
4664 if (has_directory) {
4665 if (has_file || window->details->has_recursive_apply) {
4666 attach_title_field (page_grid, _("Folder Permissions:")dcgettext (((void*)0), "Folder Permissions:", 5));
4667 }
4668 create_permission_checkboxes (window, page_grid, TRUE(!(0)));
4669 }
4670
4671 if (has_file || window->details->has_recursive_apply) {
4672 if (has_directory) {
4673 attach_title_field (page_grid, _("File Permissions:")dcgettext (((void*)0), "File Permissions:", 5));
4674 }
4675 create_permission_checkboxes (window, page_grid, FALSE(0));
4676 }
4677
4678 append_blank_slim_row (page_grid);
4679 append_special_execution_flags (window, page_grid);
4680
4681 append_title_value_pair
4682 (window, page_grid, _("Text view:")dcgettext (((void*)0), "Text view:", 5),
4683 "permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4684 FALSE(0));
4685}
4686
4687static void
4688set_recursive_permissions_done (gpointer callback_data)
4689{
4690 FMPropertiesWindow *window;
4691
4692 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) ((callback_data)))));
4693 end_long_operation (window);
4694
4695 g_object_unref (window);
4696}
4697
4698
4699static void
4700apply_recursive_clicked (GtkWidget *recursive_button,
4701 FMPropertiesWindow *window)
4702{
4703 guint32 file_permission, file_permission_mask;
4704 guint32 dir_permission, dir_permission_mask;
4705 guint32 vfs_mask, vfs_new_perm, p;
4706 gboolean active, is_folder, is_special, use_original;
4707 GList *l;
4708 GtkTreeModel *model;
4709 GtkTreeIter iter;
4710 PermissionType type;
4711 int new_perm, mask;
4712 GtkWidget *button = NULL((void*)0);
4713 GtkWidget *combo = NULL((void*)0);
4714
4715 file_permission = 0;
4716 file_permission_mask = 0;
4717 dir_permission = 0;
4718 dir_permission_mask = 0;
4719
4720 /* Advanced mode and execute checkbox: */
4721 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
4722 button = l->data;
4723
4724 if (gtk_toggle_button_get_inconsistent (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))))) {
4725 continue;
4726 }
4727
4728 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)((((GtkToggleButton*) (void *) ((button))))));
4729 p = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
4730 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "permission")))
;
4731 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
4732 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-folder")))
;
4733 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
4734 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
button))))), "is-special")))
;
4735
4736 if (is_folder || is_special) {
4737 dir_permission_mask |= p;
4738 if (active) {
4739 dir_permission |= p;
4740 }
4741 }
4742 if (!is_folder || is_special) {
4743 file_permission_mask |= p;
4744 if (active) {
4745 file_permission |= p;
4746 }
4747 }
4748 }
4749 /* Simple mode, minus exec checkbox */
4750 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
4751 combo = l->data;
4752
4753 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))), &iter)) {
4754 continue;
4755 }
4756
4757 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "permission-type")))
;
4758 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo),((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
4759 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
combo))))), "is-folder")))
;
4760
4761 model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)((((GtkComboBox*) (void *) ((combo))))));
4762 gtk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
4763 if (use_original) {
4764 continue;
4765 }
4766 vfs_new_perm = permission_to_vfs (type, new_perm);
4767
4768 if (is_folder) {
4769 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4770 } else {
4771 mask = PERMISSION_READ|PERMISSION_WRITE;
4772 }
4773 vfs_mask = permission_to_vfs (type, mask);
4774
4775 if (is_folder) {
4776 dir_permission_mask |= vfs_mask;
4777 dir_permission |= vfs_new_perm;
4778 } else {
4779 file_permission_mask |= vfs_mask;
4780 file_permission |= vfs_new_perm;
4781 }
4782 }
4783
4784 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4785 CajaFile *file;
4786
4787 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
4788
4789 if (caja_file_is_directory (file) &&
4790 caja_file_can_set_permissions (file)) {
4791 char *uri;
4792
4793 uri = caja_file_get_uri (file);
4794 start_long_operation (window);
4795 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
4796 caja_file_set_permissions_recursive (uri,
4797 file_permission,
4798 file_permission_mask,
4799 dir_permission,
4800 dir_permission_mask,
4801 set_recursive_permissions_done,
4802 window);
4803 g_free (uri);
4804 }
4805 }
4806}
4807
4808static void
4809create_permissions_page (FMPropertiesWindow *window)
4810{
4811 GtkWidget *vbox;
4812 GList *file_list;
4813
4814 vbox = create_page_with_vbox (window->details->notebook,
4815 _("Permissions")dcgettext (((void*)0), "Permissions", 5));
4816
4817 file_list = window->details->original_files;
4818
4819 window->details->initial_permissions = NULL((void*)0);
4820
4821 if (all_can_get_permissions (file_list) && all_can_get_permissions (window->details->target_files)) {
4822 GtkGrid *page_grid;
4823
4824 window->details->initial_permissions = get_initial_permissions (window->details->target_files);
4825 window->details->has_recursive_apply = files_has_changable_permissions_directory (window);
4826
4827 if (!all_can_set_permissions (file_list)) {
4828 add_prompt_and_separator (
4829 vbox,
4830 _("You are not the owner, so you cannot change these permissions.")dcgettext (((void*)0), "You are not the owner, so you cannot change these permissions."
, 5)
);
4831 }
4832
4833 page_grid = GTK_GRID (create_grid_with_standard_properties ())((((GtkGrid*) (void *) ((create_grid_with_standard_properties
())))))
;
4834
4835 gtk_widget_show (GTK_WIDGET (page_grid)((((GtkWidget*) (void *) ((page_grid))))));
4836 gtk_box_pack_start (GTK_BOX (vbox)((((GtkBox*) (void *) ((vbox))))),
4837 GTK_WIDGET (page_grid)((((GtkWidget*) (void *) ((page_grid))))),
4838 TRUE(!(0)), TRUE(!(0)), 0);
4839
4840 if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_SHOW_ADVANCED_PERMISSIONS"show-advanced-permissions")) {
4841 create_advanced_permissions (window, page_grid);
4842 } else {
4843 create_simple_permissions (window, page_grid);
4844 }
4845
4846 append_blank_slim_row (page_grid);
4847
4848#ifdef HAVE_SELINUX1
4849 append_title_value_pair
4850 (window, page_grid, _("SELinux context:")dcgettext (((void*)0), "SELinux context:", 5),
4851 "selinux_context", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4852 FALSE(0));
4853#endif
4854 append_title_value_pair
4855 (window, page_grid, _("Last changed:")dcgettext (((void*)0), "Last changed:", 5),
4856 "date_permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4857 FALSE(0));
4858
4859 if (window->details->has_recursive_apply) {
4860 GtkWidget *button, *hbox;
4861
4862 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4863 gtk_widget_show (hbox);
4864 gtk_container_add_with_properties (GTK_CONTAINER (page_grid)((((GtkContainer*) (void *) ((page_grid))))), hbox,
4865 "width", 2,
4866 NULL((void*)0));
4867
4868 button = gtk_button_new_with_mnemonic (_("Apply Permissions to Enclosed Files")dcgettext (((void*)0), "Apply Permissions to Enclosed Files",
5)
);
4869 gtk_widget_show (button);
4870 gtk_box_pack_start (GTK_BOX (hbox)((((GtkBox*) (void *) ((hbox))))), button, FALSE(0), FALSE(0), 0);
4871 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4872 G_CALLBACK (apply_recursive_clicked),g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4873 window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
;
4874 }
4875 } else {
4876 char *prompt_text;
4877
4878 if (!is_multi_file_window (window)) {
4879 char *file_name;
4880
4881 file_name = caja_file_get_display_name (get_target_file (window));
4882 prompt_text = g_strdup_printf (_("The permissions of \"%s\" could not be determined.")dcgettext (((void*)0), "The permissions of \"%s\" could not be determined."
, 5)
, file_name);
4883 g_free (file_name);
4884 } else {
4885 prompt_text = g_strdup (_("The permissions of the selected file could not be determined."))g_strdup_inline (dcgettext (((void*)0), "The permissions of the selected file could not be determined."
, 5))
;
4886 }
4887
4888 add_prompt (vbox, prompt_text, TRUE(!(0)));
4889 g_free (prompt_text);
4890 }
4891}
4892
4893static void
4894append_extension_pages (FMPropertiesWindow *window)
4895{
4896 GList *providers;
4897 GList *module_providers;
4898 GList *p;
4899
4900 providers = caja_extensions_get_for_type (CAJA_TYPE_PROPERTY_PAGE_PROVIDER(caja_property_page_provider_get_type ()));
4901
4902 /* FIXME: we also need the property pages from two old modules that
4903 * are not registered as proper extensions. This is going to work
4904 * this way until some generic solution is introduced.
4905 */
4906 module_providers = caja_module_get_extensions_for_type (CAJA_TYPE_PROPERTY_PAGE_PROVIDER(caja_property_page_provider_get_type ()));
4907 for (p = module_providers; p != NULL((void*)0); p = p->next) {
4908 const gchar *type_name = G_OBJECT_TYPE_NAME (G_OBJECT (p->data))(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (((((GObject
*) (void *) ((p->data)))))))->g_class))->g_type)))))
;
4909 if (g_strcmp0 (type_name, "CajaNotesViewerProvider") == 0 ||
4910 g_strcmp0 (type_name, "CajaImagePropertiesPageProvider") == 0) {
4911 providers = g_list_prepend (providers, p->data);
4912 }
4913 }
4914
4915 for (p = providers; p != NULL((void*)0); p = p->next) {
4916 CajaPropertyPageProvider *provider;
4917 GList *pages;
4918 GList *l;
4919
4920 provider = CAJA_PROPERTY_PAGE_PROVIDER (p->data)((((CajaPropertyPageProvider*) (void *) ((p->data)))));
4921
4922 pages = caja_property_page_provider_get_pages
4923 (provider, window->details->original_files);
4924
4925 for (l = pages; l != NULL((void*)0); l = l->next) {
4926 CajaPropertyPage *page;
4927 GtkWidget *page_widget;
4928 GtkWidget *label;
4929
4930 page = CAJA_PROPERTY_PAGE (l->data)((((CajaPropertyPage*) (void *) ((l->data)))));
4931
4932 g_object_get (G_OBJECT (page)((((GObject*) (void *) ((page))))),
4933 "page", &page_widget, "label", &label,
4934 NULL((void*)0));
4935
4936 gtk_notebook_append_page (window->details->notebook,
4937 page_widget, label);
4938
4939 g_object_set_data (G_OBJECT (page_widget)((((GObject*) (void *) ((page_widget))))),
4940 "is-extension-page",
4941 page);
4942
4943 g_object_unref (page_widget);
4944 g_object_unref (label);
4945
4946 g_object_unref (page);
4947 }
4948
4949 g_list_free (pages);
4950 }
4951
4952 caja_module_extension_list_free (providers);
4953}
4954
4955static gboolean
4956should_show_emblems (FMPropertiesWindow *window)
4957{
4958 /* FIXME bugzilla.gnome.org 45643:
4959 * Emblems aren't displayed on the the desktop Trash icon, so
4960 * we shouldn't pretend that they work by showing them here.
4961 * When bug 5643 is fixed we can remove this case.
4962 */
4963 if (!is_multi_file_window (window)
4964 && is_merged_trash_directory (get_target_file (window))) {
4965 return FALSE(0);
4966 }
4967
4968 return TRUE(!(0));
4969}
4970
4971static gboolean
4972should_show_permissions (FMPropertiesWindow *window)
4973{
4974 CajaFile *file;
4975
4976 file = get_target_file (window);
4977
4978 /* Don't show permissions for Trash and Computer since they're not
4979 * really file system objects.
4980 */
4981 if (!is_multi_file_window (window)
4982 && (is_merged_trash_directory (file) ||
4983 is_computer_directory (file))) {
4984 return FALSE(0);
4985 }
4986
4987 return TRUE(!(0));
4988}
4989
4990static char *
4991get_pending_key (GList *file_list)
4992{
4993 GList *l;
4994 GList *uris;
4995 GString *key;
4996 char *ret;
4997
4998 uris = NULL((void*)0);
4999 for (l = file_list; l != NULL((void*)0); l = l->next) {
5000 uris = g_list_prepend (uris, caja_file_get_uri (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))))));
5001 }
5002 uris = g_list_sort (uris, (GCompareFunc)strcmp);
5003
5004 key = g_string_new ("");
5005 for (l = uris; l != NULL((void*)0); l = l->next) {
5006 g_string_append (key, l->data)(__builtin_constant_p (l->data) ? __extension__ ({ const char
* const __val = (l->data); g_string_append_len_inline (key
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if (__val != ((void*)0)) _g_boolean_var_181 = 1; else _g_boolean_var_181
= 0; _g_boolean_var_181; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(key, l->data, (gssize) -1))
;
5007 g_string_append (key, ";")(__builtin_constant_p (";") ? __extension__ ({ const char * const
__val = (";"); g_string_append_len_inline (key, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_182; if (__val != ((void
*)0)) _g_boolean_var_182 = 1; else _g_boolean_var_182 = 0; _g_boolean_var_182
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (key, ";", (gssize) -1)
)
;
5008 }
5009
5010 g_list_free_full (uris, g_free);
5011
5012 ret = key->str;
5013 g_string_free (key, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((key)
, ((0))) : g_string_free_and_steal (key)) : (g_string_free) (
(key), ((0))))
;
5014
5015 return ret;
5016}
5017
5018static StartupData *
5019startup_data_new (GList *original_files,
5020 GList *target_files,
5021 const char *pending_key,
5022 GtkWidget *parent_widget)
5023{
5024 StartupData *data;
5025 GList *l;
5026
5027 data = g_new0 (StartupData, 1)(StartupData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (StartupData); 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; }))
;
5028 data->original_files = caja_file_list_copy (original_files);
5029 data->target_files = caja_file_list_copy (target_files);
5030 data->parent_widget = parent_widget;
5031 data->pending_key = g_strdup (pending_key)g_strdup_inline (pending_key);
5032 data->pending_files = g_hash_table_new (g_direct_hash,
5033 g_direct_equal);
5034
5035 for (l = data->target_files; l != NULL((void*)0); l = l->next) {
5036 g_hash_table_insert (data->pending_files, l->data, l->data);
5037 }
5038
5039 return data;
5040}
5041
5042static void
5043startup_data_free (StartupData *data)
5044{
5045 caja_file_list_free (data->original_files);
5046 caja_file_list_free (data->target_files);
5047 g_hash_table_destroy (data->pending_files);
5048 g_free (data->pending_key);
5049 g_free (data);
5050}
5051
5052static void
5053file_changed_callback (CajaFile *file, gpointer user_data)
5054{
5055 FMPropertiesWindow *window = FM_PROPERTIES_WINDOW (user_data)((((FMPropertiesWindow*) (void *) ((user_data)))));
5056
5057 if (!g_list_find (window->details->changed_files, file)) {
5058 caja_file_ref (file);
5059 window->details->changed_files = g_list_prepend (window->details->changed_files, file);
5060
5061 schedule_files_update (window);
5062 }
5063}
5064
5065static gboolean
5066is_a_special_file (CajaFile *file)
5067{
5068 if (file == NULL((void*)0) ||
5069 CAJA_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (caja_desktop_icon_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; }))))
||
5070 is_merged_trash_directory (file) ||
5071 is_computer_directory (file)) {
5072 return TRUE(!(0));
5073 }
5074 return FALSE(0);
5075}
5076
5077static gboolean
5078should_show_open_with (FMPropertiesWindow *window)
5079{
5080 CajaFile *file;
5081
5082 /* Don't show open with tab for desktop special icons (trash, etc)
5083 * We don't get the open-with menu for these anyway.
5084 *
5085 * Also don't show it for folders. Changing the default app for folders
5086 * leads to all sort of hard to understand errors.
5087 */
5088
5089 if (is_multi_file_window (window)) {
5090 if (!file_list_attributes_identical (window->details->original_files,
5091 "mime_type")) {
5092 return FALSE(0);
5093 } else {
5094
5095 GList *l;
5096
5097 for (l = window->details->original_files; l; l = l->next) {
5098 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5099 if (caja_file_is_directory (file) ||
5100 is_a_special_file (file)) {
5101 return FALSE(0);
5102 }
5103 }
5104 }
5105 } else {
5106 file = get_original_file (window);
5107 if (caja_file_is_directory (file) ||
5108 is_a_special_file (file)) {
5109 return FALSE(0);
5110 }
5111 }
5112 return TRUE(!(0));
5113}
5114
5115static void
5116create_open_with_page (FMPropertiesWindow *window)
5117{
5118 GtkWidget *vbox;
5119 char *mime_type;
5120
5121 mime_type = caja_file_get_mime_type (get_target_file (window));
5122
5123 if (!is_multi_file_window (window)) {
5124 char *uri;
5125
5126 uri = caja_file_get_uri (get_target_file (window));
5127
5128 if (uri == NULL((void*)0)) {
5129 return;
5130 }
5131
5132 vbox = caja_mime_application_chooser_new (uri, mime_type);
5133
5134 g_free (uri);
5135 } else {
5136 GList *uris;
5137
5138 uris = window->details->original_files;
5139 if (uris == NULL((void*)0)) {
5140 return;
5141 }
5142 vbox = caja_mime_application_chooser_new_for_multiple_files (uris, mime_type);
5143 }
5144
5145 gtk_widget_show (vbox);
5146 g_free (mime_type);
5147
5148 gtk_notebook_append_page (window->details->notebook,
5149 vbox, gtk_label_new (_("Open With")dcgettext (((void*)0), "Open With", 5)));
5150}
5151
5152
5153static FMPropertiesWindow *
5154create_properties_window (StartupData *startup_data)
5155{
5156 FMPropertiesWindow *window;
5157 GList *l;
5158 GtkWidget *action_area;
5159
5160 window = FM_PROPERTIES_WINDOW (gtk_widget_new (fm_properties_window_get_type (), NULL))((((FMPropertiesWindow*) (void *) ((gtk_widget_new (fm_properties_window_get_type
(), ((void*)0)))))))
;
5161
5162 window->details->original_files = caja_file_list_copy (startup_data->original_files);
5163
5164 window->details->target_files = caja_file_list_copy (startup_data->target_files);
5165
5166 gtk_window_set_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
5167 gtk_widget_get_screen (startup_data->parent_widget));
5168
5169 gtk_window_set_type_hint (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), GDK_WINDOW_TYPE_HINT_DIALOG);
5170
5171 /* Set initial window title */
5172 update_properties_window_title (window);
5173
5174 /* Start monitoring the file attributes we display. Note that some
5175 * of the attributes are for the original file, and some for the
5176 * target files.
5177 */
5178
5179 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5180 CajaFile *file;
5181 CajaFileAttributes attributes;
5182
5183 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5184
5185 attributes =
5186 CAJA_FILE_ATTRIBUTES_FOR_ICON(CAJA_FILE_ATTRIBUTE_INFO | CAJA_FILE_ATTRIBUTE_LINK_INFO | CAJA_FILE_ATTRIBUTE_THUMBNAIL
)
|
5187 CAJA_FILE_ATTRIBUTE_INFO |
5188 CAJA_FILE_ATTRIBUTE_LINK_INFO;
5189
5190 caja_file_monitor_add (file,
5191 &window->details->original_files,
5192 attributes);
5193 }
5194
5195 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5196 CajaFile *file;
5197 CajaFileAttributes attributes;
5198
5199 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5200
5201 attributes = 0;
5202 if (caja_file_is_directory (file)) {
5203 attributes |= CAJA_FILE_ATTRIBUTE_DEEP_COUNTS;
5204 }
5205
5206 attributes |= CAJA_FILE_ATTRIBUTE_INFO;
5207 caja_file_monitor_add (file, &window->details->target_files, attributes);
5208 }
5209
5210 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5211 g_signal_connect_object (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5212 "changed",
5213 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5214 G_OBJECT (window)((((GObject*) (void *) ((window))))),
5215 0);
5216 }
5217
5218 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5219 g_signal_connect_object (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5220 "changed",
5221 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5222 G_OBJECT (window)((((GObject*) (void *) ((window))))),
5223 0);
5224 }
5225
5226 /* Create the notebook tabs. */
5227 window->details->notebook = GTK_NOTEBOOK (gtk_notebook_new ())((((GtkNotebook*) (void *) ((gtk_notebook_new ())))));
5228
5229 gtk_widget_add_events (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
, GDK_SCROLL_MASK);
5230 g_signal_connect (window->details->notebook,g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5231 "scroll-event",g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5232 G_CALLBACK (eel_notebook_scroll_event_cb),g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
5233 NULL)g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_notebook_scroll_event_cb))), (((void*)0
)), ((void*)0), (GConnectFlags) 0)
;
5234
5235 gtk_widget_show (GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
);
5236 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((window)))))))))))
,
5237 GTK_WIDGET (window->details->notebook)((((GtkWidget*) (void *) ((window->details->notebook)))
))
,
5238 TRUE(!(0)), TRUE(!(0)), 0);
5239
5240 /* Create the pages. */
5241 create_basic_page (window);
5242
5243 if (should_show_emblems (window)) {
5244 create_emblems_page (window);
5245 }
5246
5247 if (should_show_permissions (window)) {
5248 create_permissions_page (window);
5249 }
5250
5251 if (should_show_open_with (window)) {
5252 create_open_with_page (window);
5253 }
5254
5255 /* append pages from available views */
5256 append_extension_pages (window);
5257
5258 eel_dialog_add_button (GTK_DIALOG (window)((((GtkDialog*) (void *) ((window))))),
5259 _("_Help")dcgettext (((void*)0), "_Help", 5),
5260 "help-browser",
5261 GTK_RESPONSE_HELP);
5262
5263 action_area = gtk_widget_get_parent (eel_dialog_add_button (GTK_DIALOG (window)((((GtkDialog*) (void *) ((window))))),
5264 _("_Close")dcgettext (((void*)0), "_Close", 5),
5265 "window-close",
5266 GTK_RESPONSE_CLOSE));
5267
5268 /* FIXME - HIGificiation, should be done inside GTK+ */
5269 gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkContainer*) (void *) ((gtk_dialog_get_content_area (((
((GtkDialog*) (void *) ((window)))))))))))
, 12);
5270 gtk_container_set_border_width (GTK_CONTAINER (action_area)((((GtkContainer*) (void *) ((action_area))))), 0);
5271 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((window)))))))))))
, 12);
5272
5273 /* Update from initial state */
5274 properties_window_update (window, NULL((void*)0));
5275
5276 return window;
5277}
5278
5279static GList *
5280get_target_file_list (GList *original_files)
5281{
5282 GList *ret;
5283 GList *l;
5284
5285 ret = NULL((void*)0);
5286
5287 for (l = original_files; l != NULL((void*)0); l = l->next) {
5288 CajaFile *target;
5289
5290 target = get_target_file_for_original_file (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))));
5291
5292 ret = g_list_prepend (ret, target);
5293 }
5294
5295 ret = g_list_reverse (ret);
5296
5297 return ret;
5298}
5299
5300static void
5301add_window (FMPropertiesWindow *window)
5302{
5303 if (!is_multi_file_window (window)) {
5304 g_hash_table_insert (windows,
5305 get_original_file (window),
5306 window);
5307 g_object_set_data (G_OBJECT (window)((((GObject*) (void *) ((window))))), "window_key",
5308 get_original_file (window));
5309 }
5310}
5311
5312static void
5313remove_window (FMPropertiesWindow *window)
5314{
5315 gpointer key;
5316
5317 key = g_object_get_data (G_OBJECT (window)((((GObject*) (void *) ((window))))), "window_key");
5318 if (key) {
5319 g_hash_table_remove (windows, key);
5320 }
5321}
5322
5323static GtkWindow *
5324get_existing_window (GList *file_list)
5325{
5326 if (!file_list->next) {
5327 return g_hash_table_lookup (windows, file_list->data);
5328 }
5329
5330 return NULL((void*)0);
5331}
5332
5333static void
5334cancel_create_properties_window_callback (gpointer callback_data)
5335{
5336 remove_pending ((StartupData *)callback_data, TRUE(!(0)), FALSE(0), TRUE(!(0)));
5337}
5338
5339static void
5340parent_widget_destroyed_callback (GtkWidget *widget, gpointer callback_data)
5341{
5342 g_assert (widget == ((StartupData *)callback_data)->parent_widget)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if (widget == ((StartupData *)callback_data)->parent_widget
) _g_boolean_var_183 = 1; else _g_boolean_var_183 = 0; _g_boolean_var_183
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5342, ((const char*) (__func__)), "widget == ((StartupData *)callback_data)->parent_widget"
); } while (0)
;
5343
5344 remove_pending ((StartupData *)callback_data, TRUE(!(0)), TRUE(!(0)), FALSE(0));
5345}
5346
5347static void
5348cancel_call_when_ready_callback (gpointer key,
5349 gpointer value,
5350 gpointer user_data)
5351{
5352 caja_file_cancel_call_when_ready
5353 (CAJA_FILE (key)((((CajaFile*) (void *) ((key))))),
5354 is_directory_ready_callback,
5355 user_data);
5356}
5357
5358static void
5359remove_pending (StartupData *startup_data,
5360 gboolean cancel_call_when_ready,
5361 gboolean cancel_timed_wait,
5362 gboolean cancel_destroy_handler)
5363{
5364 if (cancel_call_when_ready) {
5365 g_hash_table_foreach (startup_data->pending_files,
5366 cancel_call_when_ready_callback,
5367 startup_data);
5368
5369 }
5370 if (cancel_timed_wait) {
5371 eel_timed_wait_stop
5372 (cancel_create_properties_window_callback, startup_data);
5373 }
5374 if (cancel_destroy_handler) {
5375 g_signal_handlers_disconnect_by_func (startup_data->parent_widget,g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5376 G_CALLBACK (parent_widget_destroyed_callback),g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5377 startup_data)g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
;
5378 }
5379
5380 g_hash_table_remove (pending_lists, startup_data->pending_key);
5381
5382 startup_data_free (startup_data);
5383}
5384
5385static void
5386is_directory_ready_callback (CajaFile *file,
5387 gpointer data)
5388{
5389 StartupData *startup_data;
5390
5391 startup_data = data;
5392
5393 g_hash_table_remove (startup_data->pending_files, file);
5394
5395 if (g_hash_table_size (startup_data->pending_files) == 0) {
5396 FMPropertiesWindow *new_window;
5397
5398 new_window = create_properties_window (startup_data);
5399
5400 add_window (new_window);
5401
5402 remove_pending (startup_data, FALSE(0), TRUE(!(0)), TRUE(!(0)));
5403
5404 gtk_window_present (GTK_WINDOW (new_window)((((GtkWindow*) (void *) ((new_window))))));
5405 }
5406}
5407
5408
5409void
5410fm_properties_window_present (GList *original_files,
5411 GtkWidget *parent_widget)
5412{
5413 GList *l, *next;
5414 GtkWidget *parent_window;
5415 StartupData *startup_data;
5416 GList *target_files;
5417 GtkWindow *existing_window;
5418 char *pending_key;
5419
5420 g_return_if_fail (original_files != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (original_files != ((void*)0)) _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__
)), "original_files != NULL"); return; } } while (0)
;
5421 g_return_if_fail (GTK_IS_WIDGET (parent_widget))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent_widget)); GType __t = ((gtk_widget_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_185 = 1; else _g_boolean_var_185 = 0; _g_boolean_var_185
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "GTK_IS_WIDGET (parent_widget)")
; return; } } while (0)
;
5422
5423 /* Create the hash tables first time through. */
5424 if (windows == NULL((void*)0)) {
5425 windows = eel_g_hash_table_new_free_at_exit
5426 (NULL((void*)0), NULL((void*)0), "property windows");
5427 }
5428
5429 if (pending_lists == NULL((void*)0)) {
5430 pending_lists = eel_g_hash_table_new_free_at_exit
5431 (g_str_hash, g_str_equal, "pending property window files");
5432 }
5433
5434 /* Look to see if there's already a window for this file. */
5435 existing_window = get_existing_window (original_files);
5436 if (existing_window != NULL((void*)0)) {
5437 gtk_window_set_screen (existing_window,
5438 gtk_widget_get_screen (parent_widget));
5439 gtk_window_present (existing_window);
5440 return;
5441 }
5442
5443
5444 pending_key = get_pending_key (original_files);
5445
5446 /* Look to see if we're already waiting for a window for this file. */
5447 if (g_hash_table_lookup (pending_lists, pending_key) != NULL((void*)0)) {
5448 return;
5449 }
5450
5451 target_files = get_target_file_list (original_files);
5452
5453 startup_data = startup_data_new (original_files,
5454 target_files,
5455 pending_key,
5456 parent_widget);
5457
5458 caja_file_list_free (target_files);
5459 g_free(pending_key);
5460
5461 /* Wait until we can tell whether it's a directory before showing, since
5462 * some one-time layout decisions depend on that info.
5463 */
5464
5465 g_hash_table_insert (pending_lists, startup_data->pending_key, startup_data->pending_key);
5466 g_signal_connect (parent_widget, "destroy",g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
5467 G_CALLBACK (parent_widget_destroyed_callback), startup_data)g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
;
5468
5469 parent_window = gtk_widget_get_ancestor (parent_widget, GTK_TYPE_WINDOW(gtk_window_get_type ()));
5470
5471 eel_timed_wait_start
5472 (cancel_create_properties_window_callback,
5473 startup_data,
5474 _("Creating Properties window.")dcgettext (((void*)0), "Creating Properties window.", 5),
5475 parent_window == NULL((void*)0) ? NULL((void*)0) : GTK_WINDOW (parent_window)((((GtkWindow*) (void *) ((parent_window))))));
5476
5477
5478 for (l = startup_data->target_files; l != NULL((void*)0); l = next) {
5479 next = l->next;
5480 caja_file_call_when_ready
5481 (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))),
5482 CAJA_FILE_ATTRIBUTE_INFO,
5483 is_directory_ready_callback,
5484 startup_data);
5485 }
5486}
5487
5488static void
5489real_response (GtkDialog *dialog,
5490 int response)
5491{
5492 GError *error = NULL((void*)0);
5493
5494 switch (response) {
5495 case GTK_RESPONSE_HELP:
5496 gtk_show_uri_on_window (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))),
5497 "help:mate-user-guide/goscaja-51",
5498 gtk_get_current_event_time (),
5499 &error);
5500 if (error != NULL((void*)0)) {
5501 eel_show_error_dialog (_("There was an error displaying help.")dcgettext (((void*)0), "There was an error displaying help.",
5)
, error->message,
5502 GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))));
5503 g_error_free (error);
5504 }
5505 break;
5506
5507 case GTK_RESPONSE_NONE:
5508 case GTK_RESPONSE_CLOSE:
5509 case GTK_RESPONSE_DELETE_EVENT:
5510 gtk_widget_destroy (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
5511 break;
5512
5513 default:
5514 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5514, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5515 break;
5516 }
5517}
5518
5519static void
5520real_destroy (GtkWidget *object)
5521{
5522 FMPropertiesWindow *window;
5523 GList *l;
5524
5525 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) ((object)))));
5526
5527 remove_window (window);
5528
5529 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5530 caja_file_monitor_remove (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))), &window->details->original_files);
5531 }
5532 caja_file_list_free (window->details->original_files);
5533 window->details->original_files = NULL((void*)0);
5534
5535 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5536 caja_file_monitor_remove (CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data))))), &window->details->target_files);
5537 }
5538 caja_file_list_free (window->details->target_files);
5539 window->details->target_files = NULL((void*)0);
5540
5541 caja_file_list_free (window->details->changed_files);
5542 window->details->changed_files = NULL((void*)0);
5543
5544 window->details->name_field = NULL((void*)0);
5545
5546 g_list_free (window->details->emblem_buttons);
5547 window->details->emblem_buttons = NULL((void*)0);
5548
5549 if (window->details->initial_emblems) {
5550 g_hash_table_destroy (window->details->initial_emblems);
5551 window->details->initial_emblems = NULL((void*)0);
5552 }
5553
5554 g_list_free (window->details->permission_buttons);
5555 window->details->permission_buttons = NULL((void*)0);
5556
5557 g_list_free (window->details->permission_combos);
5558 window->details->permission_combos = NULL((void*)0);
5559
5560 if (window->details->initial_permissions) {
5561 g_hash_table_destroy (window->details->initial_permissions);
5562 window->details->initial_permissions = NULL((void*)0);
5563 }
5564
5565 g_list_free (window->details->value_fields);
5566 window->details->value_fields = NULL((void*)0);
5567
5568 if (window->details->update_directory_contents_timeout_id != 0) {
5569 g_source_remove (window->details->update_directory_contents_timeout_id);
5570 window->details->update_directory_contents_timeout_id = 0;
5571 }
5572
5573 if (window->details->update_files_timeout_id != 0) {
5574 g_source_remove (window->details->update_files_timeout_id);
5575 window->details->update_files_timeout_id = 0;
5576 }
5577
5578 GTK_WIDGET_CLASS (fm_properties_window_parent_class)((((GtkWidgetClass*) (void *) ((fm_properties_window_parent_class
)))))
->destroy (object);
5579}
5580
5581static void
5582real_finalize (GObject *object)
5583{
5584 FMPropertiesWindow *window;
5585
5586 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) ((object)))));
5587
5588 g_list_free_full (window->details->mime_list, g_free);
5589
5590 g_free (window->details->pending_name);
5591
5592 G_OBJECT_CLASS (fm_properties_window_parent_class)((((GObjectClass*) (void *) ((fm_properties_window_parent_class
)))))
->finalize (object);
5593}
5594
5595/* converts
5596 * file://foo/foobar/foofoo/bar
5597 * to
5598 * foofoo/bar
5599 * if
5600 * file://foo/foobar
5601 * is the parent
5602 *
5603 * It does not resolve any symlinks.
5604 * */
5605static char *
5606make_relative_uri_from_full (const char *uri,
5607 const char *base_uri)
5608{
5609 g_assert (uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if (uri != ((void*)0)) _g_boolean_var_186 = 1; else _g_boolean_var_186
= 0; _g_boolean_var_186; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5609, ((const char*
) (__func__)), "uri != NULL"); } while (0)
;
5610 g_assert (base_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if (base_uri != ((void*)0)) _g_boolean_var_187 = 1; else _g_boolean_var_187
= 0; _g_boolean_var_187; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5610, ((const char*
) (__func__)), "base_uri != NULL"); } while (0)
;
5611
5612 if (g_str_has_prefix (uri, base_uri)(__builtin_constant_p (base_uri)? __extension__ ({ const char
* const __str = (uri); const char * const __prefix = (base_uri
); gboolean __result = (0); if (__builtin_expect (__extension__
({ int _g_boolean_var_188; if (__str == ((void*)0) || __prefix
== ((void*)0)) _g_boolean_var_188 = 1; else _g_boolean_var_188
= 0; _g_boolean_var_188; }), 0)) __result = (g_str_has_prefix
) (__str, __prefix); else { const size_t __str_len = strlen (
((__str) + !(__str))); const size_t __prefix_len = strlen (((
__prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (uri, base_uri) )
) {
5613 uri += strlen (base_uri);
5614 if (*uri != '/') {
5615 return NULL((void*)0);
5616 }
5617
5618 while (*uri == '/') {
5619 uri++;
5620 }
5621
5622 if (*uri != '\0') {
5623 return g_strdup (uri)g_strdup_inline (uri);
5624 }
5625 }
5626
5627 return NULL((void*)0);
5628}
5629
5630/* icon selection callback to set the image of the file object to the selected file */
5631static void
5632set_icon (const char* icon_uri, FMPropertiesWindow *properties_window)
5633{
5634 char *icon_path;
5635
5636 g_assert (icon_uri != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if (icon_uri != ((void*)0)) _g_boolean_var_189 = 1; else _g_boolean_var_189
= 0; _g_boolean_var_189; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5636, ((const char*
) (__func__)), "icon_uri != NULL"); } while (0)
;
5637 g_assert (FM_IS_PROPERTIES_WINDOW (properties_window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((properties_window)); GType __t = (fm_properties_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_190 = 1; else _g_boolean_var_190 =
0; _g_boolean_var_190; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5637, ((const char*
) (__func__)), "FM_IS_PROPERTIES_WINDOW (properties_window)")
; } while (0)
;
5638
5639 icon_path = g_filename_from_uri (icon_uri, NULL((void*)0), NULL((void*)0));
5640 /* we don't allow remote URIs */
5641 if (icon_path != NULL((void*)0)) {
5642 GList *l;
5643 CajaFile *file = NULL((void*)0);
5644
5645 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
5646 char *file_uri;
5647
5648 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5649
5650 file_uri = caja_file_get_uri (file);
5651
5652 if (caja_file_is_mime_type (file, "application/x-desktop")) {
5653 if (caja_link_local_set_icon (file_uri, icon_path)) {
5654 caja_file_invalidate_attributes (file,
5655 CAJA_FILE_ATTRIBUTE_INFO |
5656 CAJA_FILE_ATTRIBUTE_LINK_INFO);
5657 }
5658 } else {
5659 char *real_icon_uri;
5660
5661 real_icon_uri = make_relative_uri_from_full (icon_uri, file_uri);
5662
5663 if (real_icon_uri == NULL((void*)0)) {
5664 real_icon_uri = g_strdup (icon_uri)g_strdup_inline (icon_uri);
5665 }
5666
5667 caja_file_set_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0), real_icon_uri);
5668 caja_file_set_metadata (file, CAJA_METADATA_KEY_ICON_SCALE"icon-scale", NULL((void*)0), NULL((void*)0));
5669
5670 g_free (real_icon_uri);
5671 }
5672
5673 g_free (file_uri);
5674 }
5675
5676 g_free (icon_path);
5677 }
5678}
5679
5680static void
5681update_preview_callback (GtkFileChooser *icon_chooser,
5682 FMPropertiesWindow *window)
5683{
5684 GdkPixbuf *pixbuf, *scaled_pixbuf;
5685 char *filename;
5686
5687 pixbuf = NULL((void*)0);
5688
5689 filename = gtk_file_chooser_get_filename (icon_chooser);
5690 if (filename != NULL((void*)0)) {
5691 pixbuf = gdk_pixbuf_new_from_file (filename, NULL((void*)0));
5692 }
5693
5694 if (pixbuf != NULL((void*)0)) {
5695 GtkWidget *preview_widget;
5696
5697 preview_widget = gtk_file_chooser_get_preview_widget (icon_chooser);
5698 gtk_file_chooser_set_preview_widget_active (icon_chooser, TRUE(!(0)));
5699
5700 if (gdk_pixbuf_get_width (pixbuf) > PREVIEW_IMAGE_WIDTH96) {
5701 double scale;
5702
5703 scale = (double)gdk_pixbuf_get_height (pixbuf) /
5704 gdk_pixbuf_get_width (pixbuf);
5705
5706 scaled_pixbuf = gdk_pixbuf_scale_simple
5707 (pixbuf,
5708 PREVIEW_IMAGE_WIDTH96,
5709 scale * PREVIEW_IMAGE_WIDTH96,
5710 GDK_INTERP_HYPER);
5711 g_object_unref (pixbuf);
5712 pixbuf = scaled_pixbuf;
5713 }
5714
5715 gtk_image_set_from_pixbuf (GTK_IMAGE (preview_widget)((((GtkImage*) (void *) ((preview_widget))))), pixbuf);
5716 } else {
5717 gtk_file_chooser_set_preview_widget_active (icon_chooser, FALSE(0));
5718 }
5719
5720 g_free (filename);
5721
5722 if (pixbuf != NULL((void*)0)) {
5723 g_object_unref (pixbuf);
5724 }
5725}
5726
5727static void
5728custom_icon_file_chooser_response_cb (GtkDialog *dialog,
5729 gint response,
5730 FMPropertiesWindow *window)
5731{
5732 char *uri;
5733
5734 switch (response) {
5735 case GTK_RESPONSE_NO:
5736 reset_icon (window);
5737 break;
5738
5739 case GTK_RESPONSE_OK:
5740 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))));
5741 set_icon (uri, window);
5742 g_free (uri);
5743 break;
5744
5745 default:
5746 break;
5747 }
5748
5749 gtk_widget_hide (GTK_WIDGET (dialog)((((GtkWidget*) (void *) ((dialog))))));
5750}
5751
5752static void
5753select_image_button_callback (GtkWidget *widget,
5754 FMPropertiesWindow *window)
5755{
5756 GtkWidget *dialog;
5757 GList *l;
5758 CajaFile *file;
5759 char *image_path;
5760 gboolean revert_is_sensitive;
5761
5762 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_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_191 = 1; else _g_boolean_var_191 = 0; _g_boolean_var_191
; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5762, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
5763
5764 dialog = window->details->icon_chooser;
5765
5766 if (dialog == NULL((void*)0)) {
5767 GtkWidget *preview;
5768 GtkFileFilter *filter;
5769
5770 dialog = eel_file_chooser_dialog_new (_("Select Custom Icon")dcgettext (((void*)0), "Select Custom Icon", 5), GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
5771 GTK_FILE_CHOOSER_ACTION_OPEN,
5772 "document-revert", GTK_RESPONSE_NO,
5773 "process-stop", GTK_RESPONSE_CANCEL,
5774 "document-open", GTK_RESPONSE_OK,
5775 NULL((void*)0));
5776 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), ICONDIR"/usr/local/share/icons", NULL((void*)0));
5777 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), PIXMAPDIR"/usr/local/share/pixmaps", NULL((void*)0));
5778 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog)((((GtkWindow*) (void *) ((dialog))))), TRUE(!(0)));
5779
5780 filter = gtk_file_filter_new ();
5781 gtk_file_filter_add_pixbuf_formats (filter);
5782 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), filter);
5783
5784 preview = gtk_image_new ();
5785 gtk_widget_set_size_request (preview, PREVIEW_IMAGE_WIDTH96, -1);
5786 gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), preview);
5787 gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), FALSE(0));
5788 gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), FALSE(0));
5789
5790 g_signal_connect (dialog, "update-preview",g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
5791 G_CALLBACK (update_preview_callback), window)g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
5792
5793 window->details->icon_chooser = dialog;
5794
5795 g_object_add_weak_pointer (G_OBJECT (dialog)((((GObject*) (void *) ((dialog))))),
5796 (gpointer *) &window->details->icon_chooser);
5797 }
5798
5799 /* it's likely that the user wants to pick an icon that is inside a local directory */
5800 if (g_list_length (window->details->original_files) == 1) {
5801 file = CAJA_FILE (window->details->original_files->data)((((CajaFile*) (void *) ((window->details->original_files
->data)))))
;
5802
5803 if (caja_file_is_directory (file)) {
5804 char *uri;
5805
5806 uri = caja_file_get_uri (file);
5807
5808 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
5809 if (image_path != NULL((void*)0)) {
5810 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog)((((GtkFileChooser*) (void *) ((dialog))))), image_path);
5811 g_free (image_path);
5812 }
5813
5814 g_free (uri);
5815 }
5816 }
5817
5818 revert_is_sensitive = FALSE(0);
5819 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5820 file = CAJA_FILE (l->data)((((CajaFile*) (void *) ((l->data)))));
5821 image_path = caja_file_get_metadata (file, CAJA_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
5822 revert_is_sensitive = (image_path != NULL((void*)0));
5823 g_free (image_path);
5824
5825 if (revert_is_sensitive) {
5826 break;
5827 }
5828 }
5829 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog)((((GtkDialog*) (void *) ((dialog))))), GTK_RESPONSE_NO, revert_is_sensitive);
5830
5831 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
5832 G_CALLBACK (custom_icon_file_chooser_response_cb), window)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
;
5833 gtk_widget_show (dialog);
5834}
5835
5836static void
5837fm_properties_window_class_init (FMPropertiesWindowClass *class)
5838{
5839 GtkBindingSet *binding_set;
5840
5841 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))))->finalize = real_finalize;
5842
5843 GTK_WIDGET_CLASS (class)((((GtkWidgetClass*) (void *) ((class)))))->destroy = real_destroy;
5844
5845 GTK_DIALOG_CLASS (class)((((GtkDialogClass*) (void *) ((class)))))->response = real_response;
5846
5847 binding_set = gtk_binding_set_by_class (class);
5848 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape0xff1b, 0,
5849 "close", 0);
5850}
5851
5852static void
5853fm_properties_window_init (FMPropertiesWindow *window)
5854{
5855 window->details = fm_properties_window_get_instance_private (window);
5856}
diff --git a/2024-07-29-023715-6438-1/scanview.css b/2024-07-29-023715-6438-1/scanview.css new file mode 100644 index 000000000..cf8a5a6ad --- /dev/null +++ b/2024-07-29-023715-6438-1/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/2024-07-29-023715-6438-1/sorttable.js b/2024-07-29-023715-6438-1/sorttable.js new file mode 100644 index 000000000..32faa078d --- /dev/null +++ b/2024-07-29-023715-6438-1/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("